#include "control_parser.h" #include #include typedef control_parser_ctx context; static void extract(context *ctx, char *fpc) { gsize len = (fpc - ctx->buffer->str) - ctx->mark; g_string_truncate(ctx->tmp, 0); g_string_append_len(ctx->tmp, ctx->buffer->str + ctx->mark, len); ctx->read += len; } static double extract_double(context *ctx, char *fpc) { extract(ctx, fpc); return strtod(ctx->tmp->str, NULL); } %%{ machine control_parser; variable cs ctx->cs; action done { fbreak; } action mark { ctx->mark = fpc - ctx->buffer->str; } action telemetrystart { } action vehicle { } SP = " "; 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); }; 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 ";"; x = double; y = double; r = double; dir = double; speed = double; ctl = [ab\-] [Ll\-rR]; timestamp = double; boulder = "b" SP x SP y SP r SP; crater = "b" SP x SP y SP r SP; homebase = "b" SP x SP y SP r SP; martian = "m" SP x SP y SP dir SP speed SP; object = boulder | crater | homebase | martian; objects = object*; telemetry = ( ("T" SP timestamp SP ctl SP x SP y SP dir SP speed SP) %vehicle objects) >telemetrystart ";"; main := init @ done; }%% %% 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); } void control_parser_reset(trial *t) { context *ctx = t->parse_ctx; %% write init; g_string_truncate(ctx->tmp, 0); } 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; if (0 < (wehave = ctx->buffer->len - ctx->read)) { char *p, *pe; p = ctx->buffer->str + ctx->read; pe = p + wehave; %% write exec; g_string_erase(ctx->buffer, 0, ctx->read); ctx->mark -= ctx->read; ctx->read = 0; } if (control_parser_has_error(ctx)) { fprintf(stderr, "Parse error\n"); return RUN_ERROR; } if (control_parser_is_finished(ctx)) return RUN_DONE; return RUN_GO_ON; }