diff --git a/day_6/Makefile b/day_6/Makefile new file mode 100644 index 0000000..81b7c3f --- /dev/null +++ b/day_6/Makefile @@ -0,0 +1,56 @@ +CC := clang +YACC := bison +LEX := flex +CFLAGS := -std=c17 -Wpedantic -Wall -Wextra +BISONFLAGS := +BUILD := ./build +INCLUDE := -I./ +OBJ_DIR := $(BUILD)/objects +APP_DIR := $(BUILD)/bin +TARGET := day_6 + +SRC := $(wildcard ./*.cpp) lexer.c parser.c + +OBJECTS := $(SRC:%.c=$(OBJ_DIR)/%.o) + +# targets +all: build $(APP_DIR)/$(TARGET) + +run: all + $(APP_DIR)/$(TARGET) + +flex: + $(LEX) --outfile=lexer.c --header-file=lexer.h lexer.l + +bison: + $(YACC) $(BISONFLAGS) --output=parser.c parser.y + +generate: flex bison + +$(OBJ_DIR)/%.o: %.c + @mkdir -p $(@D) + $(CC) $(CFLAGS) $(INCLUDE) -o $@ -c $< + +$(APP_DIR)/$(TARGET): flex bison $(OBJECTS) + @mkdir -p $(@D) + $(CC) $(CFLAGS) $(INCLUDE) $(LDFLAGS) -o $(APP_DIR)/$(TARGET) $(OBJECTS) + +.PHONY: all build clean debug release + +build: + @mkdir -p $(APP_DIR) + @mkdir -p $(OBJ_DIR) + +debug: CFLAGS += -DDEBUG -g +debug: BISONFLAGS += -Wcounterexamples +debug: all + +sanitize: CFLAGS += -DDEBUG -g -fsanitize=address +sanitize: all + +release: CFLAGS += -O2 +release: all + +clean: + -@rm -rvf $(BUILD) + -@rm -rvf {lexer.c,parser.c} {lexer.h,parser.h} diff --git a/day_6/input.txt b/day_6/input.txt new file mode 100644 index 0000000..65120b7 --- /dev/null +++ b/day_6/input.txt @@ -0,0 +1,2 @@ +hrbbjllllspssblslvvrdrbbpbbmcccfppvbbwvbbmrmjrjrfrgfgbffgfqfqlltlwttscsncscchssrppffvwwvvpnnwwwpvwvhhnvhhbttvzzdlzdlzzwmmjhhznnjdnnnqddbtdbdbsdsmdsdrrdpdwpdppgcgqgcctftsfszslljbljbjwbwbnwnqqrnnztntmtrmmzwzdwzwgwwwjhjsjgjtjjhpjhhppqzqdqffrvrtvvsmmgwmgwgbbclltctptzpzhpzptzppcfpcfftflfzftztddzgzmmfsmsrmmsstttvbvmbvvsmsqmqlldjdtthwtwbwggrzzjrzrcctffsshqshhpthhlnhlhqhdqqrwrmmcttpfttzfzgzdgdzzwrrtsrrsnrnccrbbsssbpbjjvzzwlwtwjwsjwjggzqgzzrsszzjnzjzwjzzcrzczncnqqztzfzhfhvvtjvjdvjjmrjrppvzppczpczcggshghvhnhhsrsnsdszzdpzpzlpzzhwwmnwmwmcwwfnwfwjjcbcncllcsllqdqzzhqhmqmbbjvjjwwcjjpnpllzfzddtmtccqrcrtrwrpphpmpplslmltthnnvhhvrvbblhhrrdqqmbqqgtqggdgcdcvvsbsswvvpggbbtftlflglzlmlbbfhhrshswhshffhhdnnrfrvrmrnrprrmfmpmnpnfnggvvcncdcrczrzccpmmssrbbdjdtdrdwrrwhrrvrtvvszvvwvzzmhhjhhwlhlqlvlttzftztdtstftrfrdddmtmzzsqzqvvpdpdcpcncnrrtntznzrzgznztnznhhsqqnrqrhhlzhzthhfddrzdrrqmqggcmmllnjjvwwjccfjfqfcfzccwvcwvcvjcjtjtnnqsqmqrmrzrszrszzfwfggnmmcdmdjmmhwwgfwfnwnlwwcffsrffvnvbvnvwnwgnwnmmbzbmbpplmplpspzpmzpzdzgzrzrtrjrbbppwvwgwmggqwgghqqshhcwcqwcqcfcbbnsnrrtztzrtrvtvhthzhmmrqqrwqqsjqjcctgtwthhqmmnffmgmdgdlgljjhwjwggrqqfrqqjvqvhqqgsqsgsttmrrbprbppmjppslpsllvlfvlvrvhvtqmrjcdzwsbzfmgmwmwqwhztqrsdzhqjqvbjbntnbndflthljcczdmmhszfgsplrtlqnfzbrlqngwdqtfwcmrdjrsmdpmjmqwrbwfjzwnvqhfmlqtvvnlfzbfccwslqpbzzjccbvrzhghqwtvqgwrmsfzqnmnqqjsjtpcmngpqgllfsnpqtjjbqcdppnsmtwrslnrbqtwvnbctzvwfmgctscmzjbqqgqdwbpzmrdwgfcjzftzgmfcjhchbnmnqnrgtqngwrmncjvptqqdtjtgtpzzdrfsdgmwlwrjnqldbwrqjrhwcczlzvlhpgrnwzhbwjnpthggczfgtrjnzvnlfdfbwcnzfbwlwlmgnnjnpvhbhqgnzhqsnmvbcftsmrcgpvnnnmgnrvpbzlpwnbwpzmwpgqvbfgjwfrjqnvvgmqwwcfddqmdznmfhpjcfgptqdqwmplrglbwlmsqzjshrlhflcjvptgrcfhjfgqmlfzrtphpbvcqzwpcnwljjdlmqzhcctqshdngrgtlfsrfccdtlvmqcdgnpcvphdsrpzfzwclvsqcpzqlfvvqzggdhpfzdvhshglvfzfmcllrdfjfsjtngjgddcpqnlmrnplwtlvwdvzftltnsnspcdztgqhlhvvbnwvnmhscfnqbngpvprzfrjcmfpfzfftrlnwgllhnjndpjdrwcgqpcgcqngnbfzlvzvhnqdjthflmwvppmbdssddmgsbgrqnpjzrjpzdddqgsdlmwnhhpjbthclvqhgrsnrbqgtnsjhncnzbhrdgftvbptrqssvsqfpqnddhmgwcrfqndqjsqgffmhdvqhjrdlmrlcqctqccprwlbqgqrwmtfhwmfjfqzdqbsdsjbtsvfvgbsrvqwnqqqqthpsqgcfslsqtnjwtsrcdcctggdghrjwpbfccrtwgszwbrsjswmjmjbcqrsgbcfsdjzsbjnnssnddnnvwgftlrqvphnqcgjszscrlhhjnljlqcjqtqfwbmdmrgdlcqqwmbsmsdhpplvlfglqwspbfptlbzqjwhqmfvzvsvpjclcdzsbvntmhdqdvhghcmmflpjbglsghbswdshtsbdrgpsrsclrmfwwqbrgdjsqztgttqpwhnfhszlgbfpzhczsnwqflmshlgbrpmdzgpqwtsbssgfjbtrwbmztlwwfmsdgpgfgdjfdccwlfgztbcbqjvjtvslmddjplrswwcszspgplsrhrnwnmrrfbcgdmntcrlvnfqtwwcczsglrhtrfqnmhvgzjpmlplqvqhmnfgvzqcmzhqszgslvndqtqhvrbvbmclbcbjdswvcjrzgfdmdwnnlzlzqcffsrqdfmmpzfnmdsnqlpcrhzsdnsflblcjsfsgcnsspftjrlmdjsmfpqtmlgfvnlfnjscsgwzwvpjrvvclhsbqldlnmtglhbjfwlzmvrbvgtprfjbjhhnlqnbrswwlqtcgrjrltdrnfrjhrntllptlsbhqrwvdsfrlghtfcndznzjwcgmtdvffltgrdmljlqhdtmdvnfsfsrvdpmhlrrsttvqlwfptddwbpfrbclwwzmfpttmrmmqzjnbbnnfvzwmmcfshvrlbdbjzprftbqvdsghnnzwbjccpthdsvsdlgvphsgjdqjwsgmzqnqpqvgqjvwgjtzpmqqwnlwrwhqqjjclcbhjgpwhqdclwmqfmwbwmwwvcbhfznfhcfbprfcdqlbcttnvgnjwswcmpbrghtzgdbppbprffzjgvddzpwmdctrhnrfzdfhtmnfrsfdqvzcnrtncflhvldcndwqtvbggmwlzhchlcwtcbqcvlfhdwljgddwpvcfczvfqmphgtdsnsqwdpvvmwnwqjbrjwbdhhgtffphsdrvspsbgmfrmwmhnrgqdfppzgfpgmqjcsnglczgwhjthfhztzrlpgzjhcfrjpjvtjptptbvflftjtcfhmbwlhlbhvnjnbfmwjrgbvvhmdlncdgncgfjcnnpdljfcjsmsfscqpwsgcmlhhqmldsnjfrrqpghwncmgwgnjsdtvbhrbbnmpqjrrctqqnqzztmbqmdsgdvmmlwmbvprllzgntnmttrlzrttmjjlrwpwmtfznmwnsjmjhjdnsppfhcrjpzhjqzdtdbsjshfzzvrwvjbjbgtsfpgggbdztczwlhpmthfjdgsbrvlwmlrvgdrpjzccwmgpcnqqzmqdjqmwsrzwsmtmdjdhmjrwfwnzlmfnqtcgtslwtlnwhvmqntmglhntnsjlnmzfvfdztcfwmpchsrsdmqvqcwljzrmmssjvbmvvnmqlbsdwnrbmqctdtmfzlgfzpmjcnftgftvjpfbwwmzfdrrwjwcfwfcfmzbbnppgjrmbcvmvnjpdrzmvndvddtvshlnjjwgtsvnwtwnhcbfpnthpjlrhgrqccdgppjvdqjwqrfrrgnvhfwvjhnwhntnpmghphrtgqhwtbrqhqljfdjbgnlgmqqgfcqpqfhcpgspdbvlbfjvlrgmtjztwdzlrhqwwtcpdvsqgssjbjjgqlwbcctzzqvvmdzpfrmspmqhtzwgcfsslpnhpjfwqrrfbwbndrvhnnsjnlvlvqdsgwzjsrprhgtvsfbhbcpljdczbtdwzcnhzntrwcrjctmhtjfdlthznzmqblppzcqgpjhlzjrmcvpptfjjzltdhmvwphwlccscwrwfcqpqwwrzcmnltzdcfvtjrcvsqwtchrmdfzjmzjfhppjzbhglwqggzqqnspfmzrfwrqdqdrsdbsdhcgdqrrnjlwrqhfhpzjhrvjndqphndnnnbwhrjvqrrbvlhhbljjcwmfpvnhcszfshlsnczgtcfhjslbhzczdqdmdnvqdzhbmbpcnbntwgllfscrcwhfrgtfvftmwhbgfhjzjrbvvwc + diff --git a/day_6/lexer.l b/day_6/lexer.l new file mode 100644 index 0000000..0bc05d7 --- /dev/null +++ b/day_6/lexer.l @@ -0,0 +1,41 @@ +%{ +#include +#include +#include "parser.h" +%} + +%option warn nodefault + +/* makes the scanner terminate after reaching <> instead of assuming a new input was provided */ +%option noyywrap +/* disable some unused functionality, add scanner tracking */ +%option nounput noinput batch debug + +/* gimme a reentrant parser (overkill but more pure) */ +%option reentrant + +%option bison-bridge + + +NL [\n] +CHAR [a-z] + + +%% + +{NL} { + return NEWLINE; + } +{CHAR} { + yylval->cval = yytext[0]; + return CHAR; + } +<> { + return END_OF_FILE; + } +. { + printf("[error] Encountered unexpected token %s\n", yytext); + return 0; + } + +%% diff --git a/day_6/parser.y b/day_6/parser.y new file mode 100644 index 0000000..6a9be01 --- /dev/null +++ b/day_6/parser.y @@ -0,0 +1,139 @@ +/* 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 + + typedef void* yyscan_t; + + struct parser_state { + // for storing the most recently read 4 chars + char buffer[4]; + // location tracker + unsigned long loc; + bool found_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) { + state->loc++; + + // left shift existing data + for (int i = 0; i < 3; i++) { + state->buffer[i] = state->buffer[i+1]; + } + + state->buffer[3] = $1; + + // check whether condition is met + // offset array indices by the base -- 'a' + char offset = 'a'; + + state->found_start = true; + for (int i = 0; i < 4; i++) { + if (!state->check_matrix[state->buffer[i] - offset]) { + state->check_matrix[state->buffer[i] - offset] = true; + } else { + state->found_start = false; + break; + } + } + + // housekeeping; reset the fields to false + for (int i = 0; i < 4; i++) { + state->check_matrix[state->buffer[i] - offset] = false; + } + } + } + ; + + +%% + +int main(void) { + struct parser_state parser_state; + for (int i = 0; i < 4; i++) { + parser_state.buffer[i] = 'a'; + } + parser_state.loc = 0; + parser_state.found_start = 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.loc); + + return 0; +}