aoc-2022/day_6/parser.y

188 lines
6 KiB
Text
Raw Permalink Normal View History

2022-12-28 10:46:31 +00:00
/* 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 <stdbool.h>
2022-12-28 11:03:48 +00:00
#define BUFSIZE 14
2022-12-28 10:46:31 +00:00
typedef void* yyscan_t;
struct parser_state {
2022-12-28 11:03:48 +00:00
// for storing the most recently read 14 chars
char buffer[BUFSIZE];
2022-12-28 10:46:31 +00:00
// location tracker
unsigned long loc;
2022-12-28 11:03:48 +00:00
bool found_start_of_packet;
unsigned long packet_start;
bool found_start_of_msg;
unsigned long msg_start;
2022-12-28 10:46:31 +00:00
bool check_matrix[26];
};
}
// Code for the c file
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#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 <cval> CHAR
%term END_OF_FILE
%%
input
: msg blanks END_OF_FILE { return 0; }
;
blanks
: NEWLINE blanks
| NEWLINE
;
msg
: bit msg
| bit
;
bit
: CHAR {
2022-12-28 11:03:48 +00:00
if (!state->found_start_of_packet || !state->found_start_of_msg) {
2022-12-28 10:46:31 +00:00
state->loc++;
// left shift existing data
2022-12-28 11:03:48 +00:00
for (int i = 0; i < (BUFSIZE-1); i++) {
2022-12-28 10:46:31 +00:00
state->buffer[i] = state->buffer[i+1];
}
2022-12-28 11:03:48 +00:00
state->buffer[BUFSIZE-1] = $1;
2022-12-28 10:46:31 +00:00
// check whether condition is met
// offset array indices by the base -- 'a'
char offset = 'a';
2022-12-28 11:03:48 +00:00
// 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++) {
2022-12-28 10:46:31 +00:00
if (!state->check_matrix[state->buffer[i] - offset]) {
state->check_matrix[state->buffer[i] - offset] = true;
} else {
2022-12-28 11:03:48 +00:00
if (search_sop) {
state->found_start_of_packet = false;
}
if (search_som) {
state->found_start_of_msg = false;
}
2022-12-28 10:46:31 +00:00
break;
}
}
2022-12-28 11:03:48 +00:00
// 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;
}
2022-12-28 10:46:31 +00:00
// housekeeping; reset the fields to false
2022-12-28 11:03:48 +00:00
for (int i = 0; i < BUFSIZE; i++) {
2022-12-28 10:46:31 +00:00
state->check_matrix[state->buffer[i] - offset] = false;
}
}
}
;
%%
int main(void) {
struct parser_state parser_state;
2022-12-28 11:03:48 +00:00
for (int i = 0; i < BUFSIZE; i++) {
2022-12-28 10:46:31 +00:00
parser_state.buffer[i] = 'a';
}
parser_state.loc = 0;
2022-12-28 11:03:48 +00:00
parser_state.packet_start = 0;
parser_state.msg_start = 0;
parser_state.found_start_of_packet = false;
parser_state.found_start_of_msg = false;
2022-12-28 10:46:31 +00:00
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);
2022-12-28 11:03:48 +00:00
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);
2022-12-28 10:46:31 +00:00
return 0;
}