-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathparser.mly
148 lines (121 loc) · 3.91 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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
%{
open Printf
open Lexing
open Ast
(* get meta / save meta *)
let get_meta n =
let p = Parsing.rhs_start_pos n in
let lnum = p.pos_lnum in
(* let col = p.pos_cnum - p.pos_bol in *)
{lnum=lnum}
let wrap node =
let meta = get_meta 1 in
{n=node; m=meta}
let only_small l =
let p x = x>255 in
try let _ = List.find p l in false with Not_found -> true
let unescape s =
Scanf.sscanf ("\"" ^ s ^ "\"") "%S" (fun u -> u)
let explode s =
let rec exp i l =
if i < 0 then l else exp (i - 1) (s.[i] :: l) in
exp (String.length s - 1) ['\x00']
let str_to_byte_list s =
let s = unescape s in
let l = explode s in
let l = List.map (fun c -> Char.code c) l in
l
let assign_tab id l =
if only_small l then
let s = AssignTab(id, l) in
s
else failwith "Only byte values (0-255) allowed in tabs"
%}
/* Ocamlyacc Declarations */
%token NEWLINE EOF
%token EQ COMMA BANG
%token LPAREN RPAREN
%token LCURLY RCURLY
%token LBRACKET RBRACKET
%token <int> NUM
%token <string> LABEL
%token <string> BRANCH
%token DOLLAR AT
%token PLUS MINUS MUL DIV XOR OR AND
%token NOT
%token <string> STR
%token <string> ID
%token <float->float> FNCT
%token FUN CMP
%left MUL DIV
%left PLUS MINUS
%left XOR OR AND
%left NOT /* negation -- unary minus */
%start input
%type <Ast.program'> input
/* Grammar follows */
%%
exp:
| NUM { let e = Const($1) in e }
| ID { let e = Var($1) in e }
| AT ID { let e = Ref($2) in e }
| exp PLUS exp { let e = BinOp($1, Add, $3) in e }
| exp MINUS exp { let e = BinOp($1, Sub, $3) in e }
| exp MUL exp { let e = BinOp($1, Mul, $3) in e }
| exp DIV exp { let e = BinOp($1, Div, $3) in e }
| exp XOR exp { let e = BinOp($1, Xor, $3) in e }
| exp OR exp { let e = BinOp($1, Or, $3) in e }
| exp AND exp { let e = BinOp($1, And, $3) in e }
| LBRACKET ID RBRACKET { let e = ReadMem($2) in e }
| NOT exp { let e = UnOp(Not, $2) in e}
| MINUS exp { let e = UnOp(Sub, $2) in e}
| LPAREN exp RPAREN { let e = $2 in e }
;
num_list:
| num_list COMMA NUM { $3::$1 }
| NUM { [$1] }
;
stmt:
| ID EQ STR { let l = str_to_byte_list $3 in
let s = assign_tab $1 l in
wrap s
}
| ID EQ LBRACKET num_list RBRACKET { let s = assign_tab $1 (List.rev $4) in wrap s }
| ID EQ exp { let s = Assign($1,$3) in wrap s }
| DOLLAR ID EQ exp { let s = DerefAssign($2,$4) in wrap s }
| LABEL { let s = Label($1) in wrap s }
| BRANCH ID { let cond = Ast.str_to_cond $1 in let s = Branch(cond, $2) in wrap s }
| CMP exp COMMA exp { let s = Cmp($2, $4) in wrap s }
| LBRACKET ID RBRACKET EQ exp { let s = WriteMem($2, $5) in wrap s }
| ID exp_args { let s = Call($1, $2) in wrap s }
| BANG ID exp_args { let s = ExtCall($2, $3) in wrap s }
;
stmt_list:
| stmt_list stmt { $2::$1 }
| stmt { [$1] }
;
args_list:
| args_list COMMA ID { $3::$1 }
| ID { [$1] }
| { [] }
;
exp_args_list:
| exp_args_list COMMA exp { $3::$1 }
| exp { [$1] }
| { [] }
;
args: LPAREN args_list RPAREN { Args(List.rev $2) };
exp_args: LPAREN exp_args_list RPAREN { ExpArgs(List.rev $2) };
func_body:
| LCURLY stmt_list RCURLY { FunBody'(List.rev $2) };
func:
| FUN ID args func_body { let f = Fun'($2, $3, $4) in wrap f }
;
func_list:
| func_list func { $2::$1 }
| func { [$1] }
;
input: EOF { Prog'([]) }
| func_list { Prog'(List.rev $1) }
;
%%