icfp11/src/control_parser.rl

201 lines
5.7 KiB
Plaintext
Raw Normal View History

2008-07-12 00:17:29 +00:00
#include "control_parser.h"
#include <stdlib.h>
#include <stdio.h>
2008-07-12 01:29:24 +00:00
#include <sys/socket.h>
2008-07-12 00:17:29 +00:00
typedef control_parser_ctx context;
static void extract(context *ctx, char *fpc) {
2008-07-12 01:29:24 +00:00
gssize curpos = (fpc - ctx->buffer->str);
gssize len = curpos - ctx->mark;
2008-07-12 00:17:29 +00:00
g_string_truncate(ctx->tmp, 0);
g_string_append_len(ctx->tmp, ctx->buffer->str + ctx->mark, len);
2008-07-12 01:29:24 +00:00
ctx->mark = -1;
2008-07-12 01:42:49 +00:00
/* printf("Read chunk '%s'\n", ctx->tmp->str); */
2008-07-12 00:17:29 +00:00
}
static double extract_double(context *ctx, char *fpc) {
extract(ctx, fpc);
return strtod(ctx->tmp->str, NULL);
}
2008-07-12 01:29:24 +00:00
static timestamp extract_ts(context *ctx, char *fpc) {
extract(ctx, fpc);
return atoi(ctx->tmp->str);
}
2008-07-12 00:17:29 +00:00
%%{
machine control_parser;
variable cs ctx->cs;
2008-07-12 09:32:10 +00:00
action done {
t->alive = 0;
/* fprintf(stderr, "Run finished\n"); */
fbreak;
}
2008-07-12 00:17:29 +00:00
action mark { ctx->mark = fpc - ctx->buffer->str; }
2008-07-12 01:29:24 +00:00
action telemetrystart { ctx->tm = telemetry_new(); }
action telemetrystop {
g_queue_push_tail(&t->telemetry, ctx->tm);
2008-07-12 01:58:56 +00:00
if (!t->alive) {
t->vehicle.accel = ctx->tm->vehicle.accel;
t->vehicle.turn = ctx->tm->vehicle.turn;
2008-07-12 08:49:48 +00:00
gettimeofday(&t->started, NULL);
2008-07-12 09:32:10 +00:00
/* fprintf(stderr, "New run\n"); */
2008-07-12 09:02:49 +00:00
} else {
2008-07-12 09:07:19 +00:00
/* fprintf(stderr, "time difference [ms]: %i\n", getcurts(t) - ctx->tm->ts); */
2008-07-12 01:58:56 +00:00
}
2008-07-12 01:52:33 +00:00
t->last_ts = ctx->tm->ts;
2008-07-12 01:29:24 +00:00
ctx->tm = NULL;
t->alive = 1;
}
action vehicle {
2008-07-12 01:42:49 +00:00
ctx->tm->ts = ctx->ts;
2008-07-12 01:58:56 +00:00
ctx->tm->vehicle.x = ctx->x;
ctx->tm->vehicle.y = ctx->y;
ctx->tm->vehicle.dir = ctx->dir;
ctx->tm->vehicle.speed = ctx->speed;
2008-07-12 01:29:24 +00:00
t->vehicle.x = ctx->x;
t->vehicle.y = ctx->y;
2008-07-12 01:42:49 +00:00
t->vehicle.dir = ctx->dir;
t->vehicle.speed = ctx->speed;
2008-07-12 01:52:33 +00:00
/* printf("Vehicle at %f / %f\n", ctx->x, ctx->y); */
2008-07-12 01:29:24 +00:00
}
2008-07-12 00:17:29 +00:00
2008-07-12 00:49:03 +00:00
SP = " ";
2008-07-12 00:17:29 +00:00
2008-07-12 01:29:24 +00:00
double = '-'? (digit | '.')*;
dx = double >mark % { t->map.dx = extract_double(ctx, fpc); };
dy = double >mark % { t->map.dy = extract_double(ctx, fpc); };
min_sensor = double >mark % { t->map.min_sensor = extract_double(ctx, fpc); };
max_sensor = double >mark % { t->map.max_sensor = extract_double(ctx, fpc); };
max_speed = double >mark % { t->map.max_speed = extract_double(ctx, fpc); };
max_turn = double >mark % { t->map.max_turn = extract_double(ctx, fpc); };
max_hard_turn = double >mark % { t->map.max_hard_turn = extract_double(ctx, fpc); };
2008-07-12 00:39:26 +00:00
2008-07-12 00:49:03 +00:00
init = "I" SP dx SP dy SP double SP min_sensor SP max_sensor SP max_speed SP max_turn SP max_hard_turn SP ";";
2008-07-12 01:29:24 +00:00
x = double >mark % { ctx->x = extract_double(ctx, fpc); };
y = double >mark % { ctx->y = extract_double(ctx, fpc); };
r = double >mark % { ctx->r = extract_double(ctx, fpc); };
dir = double >mark % { ctx->dir = extract_double(ctx, fpc); };
speed = double >mark % { ctx->speed = extract_double(ctx, fpc); };
ctl = (
"a" @ { ctx->tm->vehicle.accel = ACCEL; }
| "-" @ { ctx->tm->vehicle.accel = ROLL; }
| "b" @ { ctx->tm->vehicle.accel = BREAK; }
) (
"L" @ { ctx->tm->vehicle.turn = TURN_HARD_LEFT; }
| "l" @ { ctx->tm->vehicle.turn = TURN_LEFT; }
| "-" @ { ctx->tm->vehicle.turn = TURN_STRAIGHT; }
| "r" @ { ctx->tm->vehicle.turn = TURN_RIGHT; }
| "R" @ { ctx->tm->vehicle.turn = TURN_HARD_RIGHT; }
);
timestamp = (digit*) >mark % { ctx->ts = extract_ts(ctx, fpc); };
score = (digit*) >mark % { printf("Score %u\n", extract_ts(ctx, fpc)); };
2008-07-12 00:49:03 +00:00
2008-07-12 01:42:49 +00:00
boulder = "b" SP x SP y SP r SP % {
object o = { BOLDER, ctx->x, ctx->y, ctx->r, 0, 0 };
g_array_append_val(ctx->tm->objects, o);
};
crater = "c" SP x SP y SP r SP % {
object o = { CRATER, ctx->x, ctx->y, ctx->r, 0, 0 };
g_array_append_val(ctx->tm->objects, o);
};
homebase = "h" SP x SP y SP r SP; # ignore it
martian = "m" SP x SP y SP dir SP speed SP % {
object o = { MARTIAN, ctx->x, ctx->y, ctx->r, ctx->dir, ctx->speed };
g_array_append_val(ctx->tm->objects, o);
};
2008-07-12 00:49:03 +00:00
object = boulder | crater | homebase | martian;
objects = object*;
2008-07-12 01:29:24 +00:00
telemetry = ( ("T" SP timestamp SP ctl SP x SP y SP dir SP speed SP) %vehicle objects) >telemetrystart ";" % telemetrystop;
# crash
Boulder = "B" SP timestamp SP ";";
# fell
Crater = "C" SP timestamp SP ";";
# killed by martian
Kill = "K" SP timestamp SP ";";
Success = "S" SP timestamp SP ";";
End = "E" SP timestamp SP score SP ";";
2008-07-12 00:39:26 +00:00
2008-07-12 09:32:10 +00:00
main := init? (telemetry | Boulder)* (Crater | Kill | Success)? End @ done;
2008-07-12 00:17:29 +00:00
}%%
%% write data;
static int control_parser_has_error(context *ctx) {
return ctx->cs == control_parser_error;
}
static int control_parser_is_finished(context *ctx) {
return ctx->cs >= control_parser_first_final;
}
void control_parser_new(trial *t) {
context *ctx = t->parse_ctx = g_slice_new(context);
%% write init;
ctx->buffer = g_string_sized_new(0);
ctx->tmp = g_string_sized_new(0);
2008-07-12 01:29:24 +00:00
ctx->mark = -1;
ctx->pos = 0;
2008-07-12 00:17:29 +00:00
}
void control_parser_reset(trial *t) {
context *ctx = t->parse_ctx;
%% write init;
g_string_truncate(ctx->tmp, 0);
2008-07-12 01:29:24 +00:00
ctx->mark = -1;
2008-07-12 09:32:10 +00:00
/* fprintf(stderr, "Parser reset\n"); */
2008-07-12 00:17:29 +00:00
}
void control_parser_free(trial *t) {
g_string_free(t->parse_ctx->buffer, TRUE);
g_string_free(t->parse_ctx->tmp, TRUE);
g_slice_free(context, t->parse_ctx);
}
run_t control_parse(trial *t) {
context *ctx = t->parse_ctx;
gsize wehave;
2008-07-12 01:29:24 +00:00
if (0 < (wehave = ctx->buffer->len - ctx->pos)) {
2008-07-12 00:17:29 +00:00
char *p, *pe;
2008-07-12 01:29:24 +00:00
p = ctx->buffer->str + ctx->pos;
2008-07-12 00:17:29 +00:00
pe = p + wehave;
2008-07-12 01:58:56 +00:00
/* fprintf(stderr, "Parsing '%s' (len=%zu)\n", p, wehave); */
2008-07-12 00:17:29 +00:00
%% write exec;
2008-07-12 01:29:24 +00:00
ctx->pos = p - ctx->buffer->str;
if (ctx->mark == -1) {
g_string_erase(ctx->buffer, 0, ctx->pos);
ctx->pos = 0;
} else if (ctx->mark) {
g_string_erase(ctx->buffer, 0, ctx->mark);
ctx->pos -= ctx->mark;
ctx->mark = 0;
}
} else {
fprintf(stderr, "No data to parse\n");
2008-07-12 00:17:29 +00:00
}
if (control_parser_has_error(ctx)) {
2008-07-12 09:32:10 +00:00
fprintf(stderr, "Parse error: '%s'\n", ctx->buffer->str + ctx->pos);
2008-07-12 01:29:24 +00:00
shutdown(t->socket, SHUT_RDWR);
close(t->socket);
exit(126);
2008-07-12 00:17:29 +00:00
return RUN_ERROR;
}
if (control_parser_is_finished(ctx)) return RUN_DONE;
return RUN_GO_ON;
}