-
Notifications
You must be signed in to change notification settings - Fork 1
/
parser.mly
109 lines (88 loc) · 2.5 KB
/
parser.mly
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
%{
open Ast
let magnitude_of_bits =
let rec helper value accm bits =
match bits with
| [] -> accm
| h::t -> helper (value * 2) (accm + h * value) t in
helper 1 0
let value_of_number (sign, bits) =
sign * magnitude_of_bits bits
let string_of_label =
let split_first_n list n =
let rec split_helper list accm n =
match n with
| 0 -> (List.rev accm, list)
| _ -> match list with
| [] -> (List.rev accm, [])
| h::t -> split_helper t (h::accm) (n-1) in
split_helper list [] n in
let rec string_of_label_helper accm bits =
let (h, t) = split_first_n bits 8 in
let value = magnitude_of_bits h in
let result = (Printf.sprintf "%c%s" (Char.chr value) accm) in
match t with
| [] -> String.escaped result
| _ -> string_of_label_helper (Printf.sprintf "%c%s" (Char.chr value) accm) t
in string_of_label_helper ""
%}
%token SPACE
%token TAB
%token LINEFEED
%token EOF
%type <Ast.program> program
%start program
%%
program:
| stmt_list EOF { $1 }
stmt_list:
| stmt stmt_list { $1 :: $2 }
| { [] }
stmt:
| stack_manipulation_stmt { $1 }
| arithmetic_stmt { $1 }
| heap_access_stmt { $1 }
| flow_controll_stmt { $1 }
| io_stmt { $1 }
stack_manipulation_stmt:
| SPACE SPACE number { Push $3 }
| SPACE LINEFEED SPACE { Duplicate }
| SPACE TAB SPACE number { Copy $4 }
| SPACE LINEFEED TAB { Swap }
| SPACE LINEFEED LINEFEED { Discard }
| SPACE TAB LINEFEED number { Slide $4 }
arithmetic_stmt:
| TAB SPACE SPACE SPACE { Add }
| TAB SPACE SPACE TAB { Subtract }
| TAB SPACE SPACE LINEFEED { Multiply }
| TAB SPACE TAB SPACE { Divide }
| TAB SPACE TAB TAB { Modulo }
heap_access_stmt:
| TAB TAB SPACE { Store }
| TAB TAB TAB { Retrieve }
flow_controll_stmt:
| LINEFEED SPACE SPACE label { Mark $4 }
| LINEFEED SPACE TAB label { Call $4 }
| LINEFEED SPACE LINEFEED label { Jump $4 }
| LINEFEED TAB SPACE label { JumpIfZero $4 }
| LINEFEED TAB TAB label { JumpIfNegative $4 }
| LINEFEED TAB LINEFEED { EndSubroutine }
| LINEFEED LINEFEED LINEFEED { EndProgram }
io_stmt:
| TAB LINEFEED SPACE SPACE { OutputCharacter }
| TAB LINEFEED SPACE TAB { OutputNumber }
| TAB LINEFEED TAB SPACE { ReadCharacter }
| TAB LINEFEED TAB TAB { ReadNumber }
number:
| sign bits LINEFEED { value_of_number ($1, $2) }
label:
| bits LINEFEED { string_of_label $1 }
sign:
| SPACE { 1 }
| TAB { -1 }
bits:
| bits bit { $2 :: $1 }
| { [] }
bit:
| SPACE { 0 }
| TAB { 1 }