Add day 1, task 1

This commit is contained in:
Felix Suchert 2022-12-25 21:15:50 +01:00
commit 196660ccb1
Signed by: feliix42
GPG key ID: 24363525EA0E8A99
4 changed files with 233 additions and 0 deletions

54
day_1/Makefile Normal file
View file

@ -0,0 +1,54 @@
CC := clang
YACC := bison
LEX := flex
CFLAGS := -std=c17 -Wpedantic -Wall -Wextra
BUILD := ./build
INCLUDE := -I./
OBJ_DIR := $(BUILD)/objects
APP_DIR := $(BUILD)/bin
TARGET := day_1
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) --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: 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}

53
day_1/lexer.l Normal file
View file

@ -0,0 +1,53 @@
%{ /* -*- C -*- */
#include <stdio.h>
#include <stdlib.h>
#include "parser.h"
%}
%option warn nodefault
/* makes the scanner terminate after reaching <<EOF>> 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]
NUM [0-9]
%%
{NL} {
return NEWLINE;
}
{NUM}+ {
unsigned num = strtoul(yytext, NULL, 10);
printf("number: %d\n", num);
yylval->num = num;
return NUMBER;
}
<<EOF>> {
return END_OF_FILE;
}
. {
printf("[error] Encountered unexpected token %s\n", yytext);
return 0;
}
%%
/*int main() {*/
/*std::cout << "hello" << std::endl;*/
/*yyFlexLexer scanner;*/
/*scanner.yylex();*/
/*std::cout << "done" << std::endl;*/
/*return 0;*/
/*}*/

111
day_1/parser.y Normal file
View file

@ -0,0 +1,111 @@
/* Require bison minimal version */
%require "3.2"
/* write out a header file containing the token defines */
%header
// Code for the c file
%{
#include <stdio.h>
#include <stdlib.h>
#include "parser.h"
#include "lexer.h"
void push_value(struct parser_state* state) {
// TODO(feliix42): error handling here?
state->calorie_list = realloc(state->calorie_list, state->size+1);
state->calorie_list[state->size] = state->tmp_val;
state->tmp_val = 0;
state->size++;
}
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);
}
%}
// Code for the header file generated by bison
%code requires {
typedef void* yyscan_t;
struct parser_state {
unsigned tmp_val;
unsigned* calorie_list;
size_t size;
};
}
// 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 END_OF_FILE
%token <unsigned> NUMBER
%%
input
: line input
| END_OF_FILE { /* done. */ }
;
line
: NUMBER NEWLINE { state->tmp_val += yylval.num; }
| NEWLINE { push_value(state); }
;
%%
int main(int argc, char** argv) {
struct parser_state* parser_state = calloc(1, sizeof(struct parser_state));
if (!parser_state) {
fprintf(stderr, "[error] failed to allocate parser state\n");
return EXIT_FAILURE;
}
yyscan_t scanner;
/*YY_BUFFER_STATE state;*/
printf("Hello World\n");
if (yylex_init(&scanner)) {
fprintf(stderr, "\033[91m[error] Could not initialize lexer\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);
// task 1.1
unsigned max_val = 0;
for (int i = 0; i < parser_state->size; i++) {
if (parser_state->calorie_list[i] > max_val) {
max_val = parser_state->calorie_list[i];
}
}
printf("Largest individual calorie load: %d\n", max_val);
return 0;
}

15
day_1/state.c Normal file
View file

@ -0,0 +1,15 @@
#include <stdlib.h>
struct parser_state {
unsigned tmp_val;
unsigned* calorie_list;
size_t size;
};
void push_value(struct parser_state* state) {
// TODO(feliix42): error handling here?
state->calorie_list = realloc(state->calorie_list, state->size+1);
state->calorie_list[state->size] = state->tmp_val;
state->tmp_val = 0;
state->size++;
}