-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathExample.v
More file actions
257 lines (212 loc) · 7.37 KB
/
Example.v
File metadata and controls
257 lines (212 loc) · 7.37 KB
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
Require Import String.
Require Import Grammar.
Require Import Main.
Open Scope string_scope.
(* This file gives an example of how to use Vermillion.
The example is based on Grammar 3.11 from Appel's
"Modern Compiler Implementation in ML":
S -> if E then S else S
S -> begin S L
S -> print E
L -> end
L -> ; S L
E -> num = num
*)
(* Abstract syntax for the language that Grammar 3.11 represents.
The values that our parser produces will be ASTs with these types. *)
Inductive exp :=
| Cmp_exp : nat -> nat -> exp.
Inductive stmt :=
| If_stmt : exp -> stmt -> stmt -> stmt
| Begin_stmt : list stmt -> stmt
| Print_stmt : exp -> stmt.
(* First, we provide the types of grammar symbols
and their decidable equalities. *)
Module G311_Types <: SYMBOL_TYPES.
Inductive terminal' :=
| If | Then | Else | Begin | Print | End | Semi | Num | Eq.
Definition terminal := terminal'.
Inductive nonterminal' :=
| S | L | E.
Definition nonterminal := nonterminal'.
Lemma t_eq_dec : forall (t t' : terminal),
{t = t'} + {t <> t'}.
Proof. decide equality. Defined.
Lemma nt_eq_dec : forall (nt nt' : nonterminal),
{nt = nt'} + {nt <> nt'}.
Proof. decide equality. Defined.
Definition showT (a : terminal) : string :=
match a with
| If => "If"
| Then => "Then"
| Else => "Else"
| Begin => "Begin"
| Print => "Print"
| End => "End"
| Semi => ";"
| Num => "Num"
| Eq => "="
end.
Definition showNT (x : nonterminal) : string :=
match x with
| S => "S"
| L => "L"
| E => "E"
end.
(* A Num token carries a natural number -- no other token
carries a meaningful semantic value. *)
Definition t_semty (a : terminal) : Type :=
match a with
| Num => nat
| _ => unit
end.
Definition nt_semty (x : nonterminal) : Type :=
match x with
| S => stmt
| L => list stmt
| E => exp
end.
End G311_Types.
(* Next, we generate grammar definitions for those types,
and we package the types and their accompanying defs
into a single module *)
Module Export G <: Grammar.T.
Module Export SymTy := G311_Types.
Module Export Defs := DefsFn SymTy.
End G.
(* Now we can represent the grammar from the textbook
as a record with "start" and "prods" fields. *)
Definition g311 : grammar :=
{| start := S ;
prods := [existT action_ty
(S, [T If; NT E; T Then; NT S; T Else; NT S])
(fun tup =>
match tup with
| (_, (e, (_, (s1, (_, (s2, _)))))) =>
If_stmt e s1 s2
end);
existT action_ty
(S, [T Begin; NT S; NT L])
(fun tup =>
match tup with
| (_, (s, (ss, _))) =>
Begin_stmt (s :: ss)
end);
existT action_ty
(S, [T Print; NT E])
(fun tup =>
match tup with
| (_, (e, _)) =>
Print_stmt e
end);
existT action_ty
(L, [T End])
(fun _ => []);
existT action_ty
(L, [T Semi; NT S; NT L])
(fun tup =>
match tup with
| (_, (s, (ss, _))) =>
s :: ss
end);
existT action_ty
(E, [T Num; T Eq; T Num])
(fun tup =>
match tup with
| (n1, (_, (n2, _))) =>
Cmp_exp n1 n2
end)]
|}.
(* Now we create a module that gives us access to
the top-level parser generator functions:
parseTableOf : grammar -> option parse_table
parse : parse_table -> symbol -> list terminal ->
sum parse_failure (tree * list terminal) *)
Module Import PG := Make G.
Definition tok (a : terminal) (v : t_semty a) : token :=
existT _ a v.
(* Example input to the parser:
if 2 = 5 then
print 2 = 5
else
print 42 = 42
*)
Definition example_prog : list token :=
[tok If tt; tok Num 2; tok Eq tt; tok Num 5; tok Then tt;
tok Print tt; tok Num 2; tok Eq tt; tok Num 5;
tok Else tt;
tok Print tt; tok Num 42; tok Eq tt; tok Num 42].
(* Now we can generate an LL(1) parse table for the grammar
and use it to parse the example input. *)
Compute (match parseTableOf g311 with
| inl msg => inl msg
| inr tbl => inr (parse tbl (NT S) example_prog)
end).
(* Malformed input -- missing an equals sign operand *)
Definition buggy_prog : list token :=
[tok If tt; tok Num 2; tok Eq tt; tok Num 5; tok Then tt;
tok Print tt; tok Num 2; tok Eq tt;
tok Else tt;
tok Print tt; tok Num 42; tok Eq tt; tok Num 42].
Compute (match parseTableOf g311 with
| inl msg => inl msg
| inr tbl => inr (parse tbl (NT S) buggy_prog)
end).
Definition duplicate_redundant_grammar : grammar :=
{| start := S ;
prods := [existT action_ty
(S, [T Print; NT E])
(fun tup =>
match tup with
| (_, (e, _)) =>
Print_stmt e
end);
(* This production appears twice,
with the same semantic action *)
existT action_ty
(E, [T Num; T Eq; T Num])
(fun tup =>
match tup with
| (n1, (_, (n2, _))) =>
Cmp_exp n1 n2
end);
existT action_ty
(E, [T Num; T Eq; T Num])
(fun tup =>
match tup with
| (n1, (_, (n2, _))) =>
Cmp_exp n1 n2
end)]
|}.
Compute (match parseTableOf duplicate_redundant_grammar with
| inl msg => inl msg
| inr tbl => inr (parse tbl (NT S) example_prog)
end).
Definition non_LL1_grammar : grammar :=
{| start := S ;
prods := [existT action_ty
(S, [T Print; NT E])
(fun tup =>
match tup with
| (_, (e, _)) =>
Print_stmt e
end);
existT action_ty
(S, [T Print; NT E; T Semi])
(fun tup =>
match tup with
| (_, (e, (s, _))) =>
Print_stmt e
end);
existT action_ty
(E, [T Num; T Eq; T Num])
(fun tup =>
match tup with
| (n1, (_, (n2, _))) =>
Cmp_exp n1 n2
end)]
|}.
Compute (match parseTableOf non_LL1_grammar with
| inl msg => inl msg
| inr tbl => inr (parse tbl (NT S) example_prog)
end).