-
Notifications
You must be signed in to change notification settings - Fork 0
/
desk_calc.peg
48 lines (44 loc) · 1.5 KB
/
desk_calc.peg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
%{
let printf = Printf.printf
let vars = Array.make 26 0
%}
stmt : - e=Expr EOL { printf "%d\n" e }
| ( !EOL . )* EOL { printf "error\n" }
;
Expr : i=ID ASSIGN s=Sum { vars.(i) <- s; s }
| s=Sum { s }
;
Sum : l=Product
rs=( PLUS r=Product { fun v -> v + r }
| MINUS r=Product { fun v -> v - r }
)* { List.fold_right (fun f v -> f v) rs l }
;
Product : l=Value
rs=( TIMES r=Value { fun v -> v * r }
| DIVIDE r=Value { fun v -> v / r }
)* { List.fold_right (fun f v -> f v) rs l }
;
Value : i=NUMBER { i }
| i=ID !ASSIGN { vars.(i) }
| OPEN i=Expr CLOSE { i }
;
NUMBER : < [0-9]+ > - { int_of_string yytext };
ID : < [a-z] > - { Char.(code yytext.[0] - code 'a') };
ASSIGN : '=' - ;
PLUS : '+' - ;
MINUS : '-' - ;
TIMES : '*' - ;
DIVIDE : '/' - ;
OPEN : '(' - ;
CLOSE : ')' - ;
- : [ \t]* ;
EOL : '\n' | '\r\n' | '\r' | ';' | !. {""};
%%
let () =
let rec loop () =
let input = input_line stdin in
let result = stmt (string_view_of_string input) in
match result with
| Ok _ -> flush stdout; loop ()
| Error msg -> Printf.eprintf "Error: %s\n" msg
in loop ()