/* Require bison minimal version */ %require "3.2" /* write out a header file containing the token defines */ %header // Code for the header file generated by bison %code requires { #include #define MAX_X 500 #define MAX_Y 500 typedef void* yyscan_t; struct parser_state { bool field[MAX_X][MAX_Y]; size_t head_x; size_t head_y; size_t tail_x; size_t tail_y; unsigned long visited; }; } // Code for the c file %{ #include #include #include "parser.h" #include "lexer.h" void yyerror(struct parser_state* state, yyscan_t scanner, const char* msg) { (void)state; (void)scanner; fprintf(stderr, "\033[93mSyntax Error: %s\033[0m\n", msg); } %} // define a reentrant parser %define api.pure // enable parser tracing and detailed error messages (plus Lookahead Correction) %define parse.trace %define parse.error detailed %define parse.lac full %lex-param { yyscan_t scanner } %parse-param { struct parser_state* state } %parse-param { yyscan_t scanner } %union { unsigned long num; } %start input %token NEWLINE %token DOWN UP LEFT RIGHT %token NUM %term END_OF_FILE %% input : line input | END_OF_FILE { return 0; } ; line : movement NEWLINE | NEWLINE ; movement : UP NUM { for (size_t i = 0; i < $2; i++) { state->head_y++; if ((state->head_y - state->tail_y) > 1) { state->tail_y = state->head_y - 1; state->tail_x = state->head_x; } if (!state->field[state->tail_x][state->tail_y]) { state->field[state->tail_x][state->tail_y] = true; state->visited++; } } } | DOWN NUM { for (size_t i = 0; i < $2; i++) { state->head_y--; if ((state->tail_y - state->head_y) > 1) { state->tail_y = state->head_y + 1; state->tail_x = state->head_x; } if (!state->field[state->tail_x][state->tail_y]) { state->field[state->tail_x][state->tail_y] = true; state->visited++; } } } | RIGHT NUM { for (size_t i = 0; i < $2; i++) { state->head_x++; if ((state->head_x - state->tail_x) > 1) { state->tail_x = state->head_x - 1; state->tail_y = state->head_y; } if (!state->field[state->tail_x][state->tail_y]) { state->field[state->tail_x][state->tail_y] = true; state->visited++; } } } | LEFT NUM { for (size_t i = 0; i < $2; i++) { state->head_x--; if ((state->tail_x - state->head_x) > 1) { state->tail_x = state->head_x + 1; state->tail_y = state->head_y; } if (!state->field[state->tail_x][state->tail_y]) { state->field[state->tail_x][state->tail_y] = true; state->visited++; } } } ; %% int main(void) { struct parser_state *state = calloc(1, sizeof(struct parser_state)); if (!state) { fprintf(stderr, "\033[91m[error] Ran out of memory\033[0m\n"); return EXIT_FAILURE; } state->head_x = MAX_X / 2; state->head_y = MAX_Y / 2; state->tail_x = MAX_X / 2; state->tail_y = MAX_Y / 2; state->visited = 1; // the starting position state->field[state->tail_x][state->tail_y] = true; yyscan_t scanner; if (yylex_init(&scanner)) { fprintf(stderr, "\033[91m[error] Could not initialize lexer\033[0m\n"); return EXIT_FAILURE; } if (yyparse(state, scanner)) { // TODO: Error handling https://www.gnu.org/software/bison/manual/html_node/Parser-Function.html // error during parse occured return EXIT_FAILURE; } yylex_destroy(scanner); // task 1 printf("Visited nodes: %zu\n", state->visited); return 0; }