Add day 1, task 1
This commit is contained in:
commit
196660ccb1
4 changed files with 233 additions and 0 deletions
54
day_1/Makefile
Normal file
54
day_1/Makefile
Normal 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
53
day_1/lexer.l
Normal 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
111
day_1/parser.y
Normal 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
15
day_1/state.c
Normal 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++;
|
||||
}
|
Loading…
Reference in a new issue