language: ocaml prompt: https://adventofcode.com/2020/day/18 learn: https://ocaml.org/learn/
solve.ml
open Printf;;
let lexed_file f =
Lexing.from_channel (open_in f)
;;
let rec eval lexbuf acc =
try
eval lexbuf (acc + (Parser.main Lexer.token lexbuf))
with Lexer.Eof ->
acc
;;
let lexbuf = lexed_file "./input" in
let final_sum = eval lexbuf 0 in
printf "Final result: %d\n" final_sum
lexer.mll
{
open Parser
exception Eof
}
rule token = parse
[' '] { token lexbuf }
| ['\n'] { EOL }
| ['0'-'9']+ as digits { INT(int_of_string digits) }
| '+' { PLUS }
| '*' { TIMES }
| '(' { LPAREN }
| ')' { RPAREN }
| eof { raise Eof }
parser-part1.mly
%token <int> INT
%token PLUS TIMES
%token LPAREN RPAREN
%token EOL
%left PLUS TIMES
%start main
%type <int> main
%%
main:
expr EOL {$1}
;
expr:
INT {$1}
| LPAREN expr RPAREN {$2}
| expr PLUS expr {$1 + $3}
| expr TIMES expr {$1 * $3}
| EOL {0}
;
parser-part2.mly
%token <int> INT
%token PLUS TIMES
%token LPAREN RPAREN
%token EOL
%left TIMES /* Only these */
%left PLUS /* lines change. */
%start main
%type <int> main
%%
main:
expr EOL {$1}
;
expr:
INT {$1}
| LPAREN expr RPAREN {$2}
| expr PLUS expr {$1 + $3}
| expr TIMES expr {$1 * $3}
| EOL {0}
;
run
#!/bin/bash
# Update based on part to solve:
#ln -sf parser-part1.mly parser.mly
ln -sf parser-part2.mly parser.mly
ocamllex lexer.mll \
&& ocamlyacc parser.mly \
&& ocamlc -c parser.mli \
&& ocamlc -c lexer.ml \
&& ocamlc -c parser.ml \
&& ocamlc -c solve.ml \
&& ocamlc lexer.cmo parser.cmo solve.cmo -o solve \
&& ./solve
See also: