]>
Commit | Line | Data |
---|---|---|
1 | (* L1 Compiler | |
2 | * L1 grammar | |
3 | * Author: Kaustuv Chaudhuri <kaustuv+@cs.cmu.edu> | |
4 | * Modified: Frank Pfenning <fp@cs.cmu.edu> | |
5 | *) | |
6 | ||
7 | structure A = Ast | |
8 | ||
9 | (* for simplicity, we only mark expressions, not statements *) | |
10 | ||
11 | (* mark e with region (left, right) in source file *) | |
12 | fun mark (e, (left, right)) = A.Marked (Mark.mark' (e, ParseState.ext (left, right))) | |
13 | ||
14 | (* create lval from expression; here just an id *) | |
15 | (* generates error if not an identifier *) | |
16 | fun make_lval (A.Var(id)) ext = id | |
17 | | make_lval (A.Marked(marked_exp)) ext = | |
18 | make_lval (Mark.data marked_exp) (Mark.ext marked_exp) | |
19 | | make_lval _ ext = ( ErrorMsg.error ext "not a variable" ; | |
20 | Symbol.bogus ) | |
21 | ||
22 | (* expand_asnop (exp1, "op=", exp2) region = "exp1 = exp1 op exps" | |
23 | * or = "exp1 = exp2" if asnop is "=" | |
24 | * generates error if exp1 is an lval (identifier) | |
25 | * syntactically expands a compound assignment operator | |
26 | *) | |
27 | fun expand_asnop (exp1, NONE, exp2) (left, right) = | |
28 | A.Assign(make_lval exp1 NONE, exp2) | |
29 | | expand_asnop (exp1, SOME(oper), exp2) (left, right) = | |
30 | A.Assign(make_lval exp1 NONE, | |
31 | mark(A.OpExp(oper, [exp1, exp2]), (left, right))) | |
32 | ||
33 | %% | |
34 | %header (functor L1LrValsFn (structure Token : TOKEN)) | |
35 | ||
36 | %term | |
37 | EOF | |
38 | | SEMI | |
39 | | INTNUM of Word32.word | |
40 | | IDENT of Symbol.symbol | |
41 | | RETURN | |
42 | | PLUS | MINUS | STAR | SLASH | PERCENT | |
43 | | ASSIGN | PLUSEQ | MINUSEQ | STAREQ | SLASHEQ | PERCENTEQ | |
44 | | LBRACE | RBRACE | |
45 | | LPAREN | RPAREN | |
46 | | UNARY | ASNOP (* dummy *) | |
47 | ||
48 | %nonterm | |
49 | program of A.program | |
50 | | stms of A.stm list | |
51 | | stm of A.stm | |
52 | | simp of A.stm | |
53 | | return of A.stm | |
54 | | exp of A.exp | |
55 | | asnop of A.oper option | |
56 | ||
57 | %verbose (* print summary of errors *) | |
58 | %pos int (* positions *) | |
59 | %start program | |
60 | %eop EOF | |
61 | %noshift EOF | |
62 | ||
63 | %name L1 | |
64 | ||
65 | %left PLUS MINUS | |
66 | %left STAR SLASH PERCENT | |
67 | %right UNARY | |
68 | %left LPAREN | |
69 | ||
70 | %% | |
71 | ||
72 | program : LBRACE stms return RBRACE | |
73 | (stms@[return]) | |
74 | ||
75 | return : RETURN exp SEMI (A.Return exp) | |
76 | ||
77 | stms : ([]) | |
78 | | stm stms (stm :: stms) | |
79 | ||
80 | stm : simp SEMI (simp) | |
81 | simp : exp asnop exp %prec ASNOP | |
82 | (expand_asnop (exp1, asnop, exp2) (exp1left, exp2right)) | |
83 | ||
84 | exp : LPAREN exp RPAREN (exp) | |
85 | | INTNUM (mark (A.ConstExp(INTNUM),(INTNUMleft,INTNUMright))) | |
86 | | IDENT (mark (A.Var(IDENT), (IDENTleft,IDENTright))) | |
87 | | exp PLUS exp (mark (A.OpExp (A.PLUS, [exp1,exp2]), (exp1left,exp2right))) | |
88 | | exp MINUS exp (mark (A.OpExp (A.MINUS, [exp1,exp2]), (exp1left,exp2right))) | |
89 | | exp STAR exp (mark (A.OpExp (A.TIMES, [exp1,exp2]), (exp1left,exp2right))) | |
90 | | exp SLASH exp (mark (A.OpExp (A.DIVIDEDBY, [exp1,exp2]), (exp1left,exp2right))) | |
91 | | exp PERCENT exp (mark (A.OpExp (A.MODULO, [exp1,exp2]), (exp1left,exp2right))) | |
92 | | MINUS exp %prec UNARY (mark (A.OpExp (A.NEGATIVE, [exp]), (MINUSleft,expright))) | |
93 | ||
94 | asnop : ASSIGN (NONE) | |
95 | | PLUSEQ (SOME(A.PLUS)) | |
96 | | MINUSEQ (SOME(A.MINUS)) | |
97 | | STAREQ (SOME(A.TIMES)) | |
98 | | SLASHEQ (SOME(A.DIVIDEDBY)) | |
99 | | PERCENTEQ (SOME(A.MODULO)) |