2022-12-25 20:15:50 +00:00
|
|
|
/* Require bison minimal version */
|
|
|
|
%require "3.2"
|
|
|
|
|
|
|
|
/* write out a header file containing the token defines */
|
|
|
|
%header
|
|
|
|
|
2022-12-25 22:09:12 +00:00
|
|
|
// Code for the header file generated by bison
|
|
|
|
%code requires {
|
|
|
|
typedef void* yyscan_t;
|
|
|
|
|
|
|
|
struct parser_state {
|
|
|
|
unsigned long tmp_val;
|
|
|
|
unsigned long* calorie_list;
|
|
|
|
unsigned long size;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-12-25 20:15:50 +00:00
|
|
|
// 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?
|
2022-12-25 22:09:12 +00:00
|
|
|
state->calorie_list = realloc(state->calorie_list, (state->size+1) * sizeof(unsigned long));
|
2022-12-25 20:15:50 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
%}
|
|
|
|
|
|
|
|
// 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
|
2022-12-25 22:09:12 +00:00
|
|
|
%token NEWLINE
|
|
|
|
%token <num> NUMBER
|
|
|
|
%term END_OF_FILE
|
2022-12-25 20:15:50 +00:00
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
input
|
|
|
|
: line input
|
2022-12-25 22:09:12 +00:00
|
|
|
| END_OF_FILE { if (state->tmp_val != 0) { push_value(state); } return 0; }
|
2022-12-25 20:15:50 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
line
|
2022-12-25 22:09:12 +00:00
|
|
|
: NUMBER NEWLINE { state->tmp_val += $1; }
|
2022-12-25 20:15:50 +00:00
|
|
|
| NEWLINE { push_value(state); }
|
|
|
|
;
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
2022-12-25 22:09:12 +00:00
|
|
|
int main(void) {
|
2022-12-25 20:15:50 +00:00
|
|
|
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;*/
|
|
|
|
|
|
|
|
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
|
2022-12-25 22:09:12 +00:00
|
|
|
unsigned long max_val = 0;
|
|
|
|
for (unsigned long i = 0; i < parser_state->size; i++) {
|
2022-12-25 20:15:50 +00:00
|
|
|
if (parser_state->calorie_list[i] > max_val) {
|
|
|
|
max_val = parser_state->calorie_list[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-25 22:09:12 +00:00
|
|
|
printf("Largest individual calorie load: %lu\n", max_val);
|
2022-12-25 20:15:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|