/* 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 BUFSIZE 14 typedef void* yyscan_t; struct parser_state { // for storing the most recently read 14 chars char buffer[BUFSIZE]; // location tracker unsigned long loc; bool found_start_of_packet; unsigned long packet_start; bool found_start_of_msg; unsigned long msg_start; bool check_matrix[26]; }; } // Code for the c file %{ #include #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 { char cval; } %start input %token NEWLINE %token CHAR %term END_OF_FILE %% input : msg blanks END_OF_FILE { return 0; } ; blanks : NEWLINE blanks | NEWLINE ; msg : bit msg | bit ; bit : CHAR { if (!state->found_start_of_packet || !state->found_start_of_msg) { state->loc++; // left shift existing data for (int i = 0; i < (BUFSIZE-1); i++) { state->buffer[i] = state->buffer[i+1]; } state->buffer[BUFSIZE-1] = $1; // check whether condition is met // offset array indices by the base -- 'a' char offset = 'a'; // Search for start of packet bool search_sop = !state->found_start_of_packet; // sop - start of packet bool search_som = !state->found_start_of_msg; // som - start of message if (search_sop) { state->found_start_of_packet = true; } if (search_som) { state->found_start_of_msg = true; } // the start of packet only concerns itself with the last 4 characters read; the start of message with the last 14 // hence, we check the last 4 first, then the rest for (int i = BUFSIZE - 4; i < BUFSIZE; i++) { if (!state->check_matrix[state->buffer[i] - offset]) { state->check_matrix[state->buffer[i] - offset] = true; } else { if (search_sop) { state->found_start_of_packet = false; } if (search_som) { state->found_start_of_msg = false; } break; } } // now check the remaining elements for (int i = 0; i < BUFSIZE - 4; i++) { if (!state->check_matrix[state->buffer[i] - offset]) { state->check_matrix[state->buffer[i] - offset] = true; } else { if (search_som) { state->found_start_of_msg = false; } break; } } if (search_sop && state->found_start_of_packet) { state->packet_start = state->loc; } if (search_som && state->found_start_of_msg) { state->msg_start = state->loc; } // housekeeping; reset the fields to false for (int i = 0; i < BUFSIZE; i++) { state->check_matrix[state->buffer[i] - offset] = false; } } } ; %% int main(void) { struct parser_state parser_state; for (int i = 0; i < BUFSIZE; i++) { parser_state.buffer[i] = 'a'; } parser_state.loc = 0; parser_state.packet_start = 0; parser_state.msg_start = 0; parser_state.found_start_of_packet = false; parser_state.found_start_of_msg = false; yyscan_t scanner; if (yylex_init(&scanner)) { fprintf(stderr, "\033[91m[error] Could not initialize lexer\033[0m\n"); return EXIT_FAILURE; } if (yyparse(&parser_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); printf("First start-of-packet marker detected at: %lu\n", parser_state.packet_start); printf("First start-of-message marker detected at: %lu\n", parser_state.msg_start); return 0; }