annotate lab4/parser.mly @ 0:bfdcc3820b32

Basis
author Mike Spivey <mike@cs.ox.ac.uk>
date Thu, 05 Oct 2017 08:04:15 +0100
parents
children
rev   line source
mike@0 1 /* lab4/parser.mly */
mike@0 2 /* Copyright (c) 2017 J. M. Spivey */
mike@0 3
mike@0 4 %{
mike@0 5 open Optree
mike@0 6 open Dict
mike@0 7 open Tree
mike@0 8 %}
mike@0 9
mike@0 10 %token <Dict.ident> IDENT
mike@0 11 %token <Optree.op> MULOP ADDOP RELOP
mike@0 12 %token <int> NUMBER
mike@0 13 %token <char> CHAR
mike@0 14 %token <Optree.symbol * int> STRING
mike@0 15
mike@0 16 /* punctuation */
mike@0 17 %token SEMI DOT COLON LPAR RPAR COMMA SUB BUS
mike@0 18 %token EQUAL MINUS ASSIGN VBAR ARROW
mike@0 19 %token BADTOK IMPOSSIBLE
mike@0 20
mike@0 21 /* keywords */
mike@0 22 %token ARRAY BEGIN CONST DO ELSE END IF OF
mike@0 23 %token PROC RECORD RETURN THEN TO TYPE
mike@0 24 %token VAR WHILE NOT POINTER NIL
mike@0 25 %token REPEAT UNTIL FOR ELSIF CASE
mike@0 26
mike@0 27 %type <Tree.program> program
mike@0 28 %start program
mike@0 29
mike@0 30 %{
mike@0 31 let const n t = makeExpr (Constant (n, t))
mike@0 32 %}
mike@0 33
mike@0 34 %%
mike@0 35
mike@0 36 program :
mike@0 37 block DOT { Prog ($1, ref []) } ;
mike@0 38
mike@0 39 block :
mike@0 40 decl_list BEGIN stmts END { makeBlock ($1, $3) } ;
mike@0 41
mike@0 42 decl_list :
mike@0 43 /* empty */ { [] }
mike@0 44 | decl decl_list { $1 @ $2 } ;
mike@0 45
mike@0 46 decl :
mike@0 47 CONST const_decls { $2 }
mike@0 48 | VAR var_decls { $2 }
mike@0 49 | proc_decl { [$1] }
mike@0 50 | TYPE type_decls { [TypeDecl $2] } ;
mike@0 51
mike@0 52 const_decls :
mike@0 53 const_decl { [$1] }
mike@0 54 | const_decl const_decls { $1 :: $2 } ;
mike@0 55
mike@0 56 const_decl :
mike@0 57 IDENT EQUAL expr SEMI { ConstDecl ($1, $3) } ;
mike@0 58
mike@0 59 type_decls :
mike@0 60 type_decl { [$1] }
mike@0 61 | type_decl type_decls { $1 :: $2 } ;
mike@0 62
mike@0 63 type_decl :
mike@0 64 IDENT EQUAL typexpr SEMI { ($1, $3) } ;
mike@0 65
mike@0 66 var_decls :
mike@0 67 var_decl { [$1] }
mike@0 68 | var_decl var_decls { $1 :: $2 } ;
mike@0 69
mike@0 70 var_decl :
mike@0 71 ident_list COLON typexpr SEMI { VarDecl (VarDef, $1, $3) } ;
mike@0 72
mike@0 73 proc_decl :
mike@0 74 proc_heading SEMI block SEMI { ProcDecl ($1, $3) } ;
mike@0 75
mike@0 76 proc_heading :
mike@0 77 PROC name params return_type { Heading ($2, $3, $4) } ;
mike@0 78
mike@0 79 params :
mike@0 80 LPAR RPAR { [] }
mike@0 81 | LPAR formal_decls RPAR { $2 } ;
mike@0 82
mike@0 83 formal_decls :
mike@0 84 formal_decl { [$1] }
mike@0 85 | formal_decl SEMI formal_decls { $1 :: $3 } ;
mike@0 86
mike@0 87 formal_decl :
mike@0 88 ident_list COLON typexpr { VarDecl (CParamDef, $1, $3) }
mike@0 89 | VAR ident_list COLON typexpr { VarDecl (VParamDef, $2, $4) }
mike@0 90 | proc_heading { PParamDecl $1 } ;
mike@0 91
mike@0 92 return_type :
mike@0 93 /* empty */ { None }
mike@0 94 | COLON typexpr { Some $2 } ;
mike@0 95
mike@0 96 stmts :
mike@0 97 stmt_list { match $1 with [x] -> x
mike@0 98 | xs -> makeStmt (Seq $1, 0) } ;
mike@0 99
mike@0 100 stmt_list :
mike@0 101 stmt { [$1] }
mike@0 102 | stmt SEMI stmt_list { $1 :: $3 } ;
mike@0 103
mike@0 104 stmt :
mike@0 105 line stmt1 { makeStmt ($2, $1) }
mike@0 106 | /* A trick to force the right line number */
mike@0 107 IMPOSSIBLE { failwith "impossible" } ;
mike@0 108
mike@0 109 line :
mike@0 110 /* empty */ { !Lexer.lineno } ;
mike@0 111
mike@0 112 stmt1 :
mike@0 113 /* empty */ { Skip }
mike@0 114 | variable ASSIGN expr { Assign ($1, $3) }
mike@0 115 | name actuals { ProcCall ($1, $2) }
mike@0 116 | RETURN expr_opt { Return $2 }
mike@0 117 | IF expr THEN stmts elses END { IfStmt ($2, $4, $5) }
mike@0 118 | WHILE expr DO stmts END { WhileStmt ($2, $4) }
mike@0 119 | REPEAT stmts UNTIL expr { RepeatStmt ($2, $4) }
mike@0 120 | FOR name ASSIGN expr TO expr DO stmts END
mike@0 121 { let v = makeExpr (Variable $2) in
mike@0 122 ForStmt (v, $4, $6, $8, ref None) }
mike@0 123 | CASE expr OF arms else_part END { CaseStmt ($2, $4, $5) } ;
mike@0 124
mike@0 125 elses :
mike@0 126 /* empty */ { makeStmt (Skip, 0) }
mike@0 127 | ELSE stmts { $2 }
mike@0 128 | ELSIF line expr THEN stmts elses { makeStmt (IfStmt ($3, $5, $6), $2) } ;
mike@0 129
mike@0 130 arms :
mike@0 131 arm { [$1] }
mike@0 132 | arm VBAR arms { $1 :: $3 } ;
mike@0 133
mike@0 134 arm :
mike@0 135 expr COLON stmts { ($1, $3) };
mike@0 136
mike@0 137 else_part :
mike@0 138 /* empty */ { makeStmt (Skip, 0) }
mike@0 139 | ELSE stmts { $2 } ;
mike@0 140
mike@0 141 ident_list :
mike@0 142 IDENT { [$1] }
mike@0 143 | IDENT COMMA ident_list { $1 :: $3 } ;
mike@0 144
mike@0 145 expr_opt :
mike@0 146 /* empty */ { None }
mike@0 147 | expr { Some $1 } ;
mike@0 148
mike@0 149 expr :
mike@0 150 simple { $1 }
mike@0 151 | expr RELOP simple { makeExpr (Binop ($2, $1, $3)) }
mike@0 152 | expr EQUAL simple { makeExpr (Binop (Eq, $1, $3)) } ;
mike@0 153
mike@0 154 simple :
mike@0 155 term { $1 }
mike@0 156 | simple ADDOP term { makeExpr (Binop ($2, $1, $3)) }
mike@0 157 | simple MINUS term { makeExpr (Binop (Minus, $1, $3)) } ;
mike@0 158
mike@0 159 term :
mike@0 160 factor { $1 }
mike@0 161 | term MULOP factor { makeExpr (Binop ($2, $1, $3)) } ;
mike@0 162
mike@0 163 factor :
mike@0 164 variable { $1 }
mike@0 165 | NUMBER { const $1 integer }
mike@0 166 | STRING { let (lab, len) = $1 in
mike@0 167 makeExpr (String (lab, len)) }
mike@0 168 | CHAR { const (int_of_char $1) character }
mike@0 169 | NIL { makeExpr Nil }
mike@0 170 | name actuals { makeExpr (FuncCall ($1, $2)) }
mike@0 171 | NOT factor { makeExpr (Monop (Not, $2)) }
mike@0 172 | MINUS factor { makeExpr (Monop (Uminus, $2)) }
mike@0 173 | LPAR expr RPAR { $2 } ;
mike@0 174
mike@0 175 actuals :
mike@0 176 LPAR RPAR { [] }
mike@0 177 | LPAR expr_list RPAR { $2 } ;
mike@0 178
mike@0 179 expr_list :
mike@0 180 expr { [$1] }
mike@0 181 | expr COMMA expr_list { $1 :: $3 } ;
mike@0 182
mike@0 183 variable :
mike@0 184 name { makeExpr (Variable $1) }
mike@0 185 | variable SUB expr BUS { makeExpr (Sub ($1, $3)) }
mike@0 186 | variable DOT name { makeExpr (Select ($1, $3)) }
mike@0 187 | variable ARROW { makeExpr (Deref $1) } ;
mike@0 188
mike@0 189 typexpr :
mike@0 190 name { TypeName $1 }
mike@0 191 | ARRAY expr OF typexpr { Array ($2, $4) }
mike@0 192 | RECORD fields END { Record $2 }
mike@0 193 | POINTER TO typexpr { Pointer $3 } ;
mike@0 194
mike@0 195 fields :
mike@0 196 field_decl opt_semi { [$1] }
mike@0 197 | field_decl SEMI fields { $1 :: $3 } ;
mike@0 198
mike@0 199 field_decl :
mike@0 200 ident_list COLON typexpr { VarDecl (FieldDef, $1, $3) } ;
mike@0 201
mike@0 202 opt_semi :
mike@0 203 SEMI { () }
mike@0 204 | /* empty */ { () } ;
mike@0 205
mike@0 206 name :
mike@0 207 IDENT { makeName ($1, !Lexer.lineno) } ;