Prechádzať zdrojové kódy

Cleaned up the parser

Taddeus Kroes 12 rokov pred
rodič
commit
8873ae03c1
1 zmenil súbory, kde vykonal 179 pridanie a 113 odobranie
  1. 179 113
      parser.mly

+ 179 - 113
parser.mly

@@ -1,12 +1,18 @@
 %{
-open Lexing
-open Ast
+    (**
+     * Parser for the CiviC language.
+     *
+     * Note that some shift/reduce conflicts exist, but these need not be solved
+     * since menhir can automatically resolve them
+     *)
 
-let loc = Util.loc_from_lexpos
-%}
+    open Lexing
+    open Ast
 
-/* Tokens */
+    let loc = Util.loc_from_lexpos
+%}
 
+(* Tokens *)
 %token LPAREN RPAREN LBRACK RBRACK LBRACE RBRACE SEMICOL COMMA
 %token NOT ADD SUB MUL DIV MOD
 %token EQ NE LT LE GT GE
@@ -20,9 +26,8 @@ let loc = Util.loc_from_lexpos
 %token <int> INT_CONST
 %token <string> ID
 
-/* Precedence */
-
-%right ASSIGN
+(* Precedence *)
+(*%right ASSIGN*)
 %left OR
 %left AND
 %left EQ NE
@@ -34,115 +39,176 @@ let loc = Util.loc_from_lexpos
 %nonassoc IF
 %nonassoc ELSE
 
-/* Start symbol */
-
+(* Start symbol *)
 %type <Ast.node> program
 %start program
 
 %%
 
-basic_type : FLOAT      { Float }
-           | INT        { Int }
-           | BOOL       { Bool }
-
-program : decl*; EOF
-          { Program ($1, loc $startpos $endpos) }
-
-decl : EXTERN; fun_header; SEMICOL
-       { let (t, n, p) = $2 in FunDec(t, n, p, loc $startpos $endpos) }
-     | boption(EXPORT); fun_header; LBRACE; fun_body; RBRACE
-       { let (t, n, p) = $2 in FunDef ($1, t, n, p, Block $4, loc $startpos $endpos) }
-
-     | EXTERN; basic_type; ID; SEMICOL
-       { GlobalDec ($2, $3, loc $startpos $endpos) }
-     | EXTERN; t=basic_type; LBRACK; d=separated_list(COMMA, ID); RBRACK; n=ID; SEMICOL
-       { GlobalDec (ArrayDec (t, d), n, loc $startpos $endpos) }
-
-     | boption(EXPORT); basic_type; ID; SEMICOL
-       { GlobalDef ($1, $2, $3, None, loc $startpos $endpos) }
-     | boption(EXPORT); basic_type; ID; ASSIGN; expr; SEMICOL
-       { GlobalDef ($1, $2, $3, Some $5, loc $startpos $endpos) }
-
-     | e=boption(EXPORT); t=basic_type; LBRACK; d=separated_list(COMMA, expr);
-            RBRACK; n=ID; SEMICOL
-       { GlobalDef (e, ArrayDef (t, d), n, None, loc $startpos $endpos) }
-     | e=boption(EXPORT); t=basic_type; LBRACK; d=separated_list(COMMA, expr);
-            RBRACK; n=ID; ASSIGN; v=expr; SEMICOL
-       { GlobalDef (e, ArrayDef (t, d), n, Some v, loc $startpos $endpos) }
-
-fun_header : ret=basic_type; name=ID; LPAREN; params=separated_list(COMMA, param); RPAREN
-             { (ret, name, params) }
-           | VOID; name=ID; LPAREN; params=separated_list(COMMA, param); RPAREN
-             { (Void, name, params) }
-
-param : basic_type; ID  { Param ($1, $2, loc $startpos $endpos) }
-
-fun_body : var_dec* local_fun_dec* statement* loption(return_statement)
-           { $1 @ $2 @ $3 @ $4 }
-
-local_fun_dec : fun_header; LBRACE; fun_body; RBRACE
-                { let (t, n, p) = $1 in FunDef (false, t, n, p, Block $3, loc $startpos $endpos) }
-
-var_dec : basic_type; ID; SEMICOL
-          { VarDec ($1, $2, None, loc $startpos $endpos) }
-        | basic_type; ID; ASSIGN; expr; SEMICOL
-          { VarDec ($1, $2, Some $4, loc $startpos $endpos) }
-        | t=basic_type; LBRACK; d=separated_list(COMMA, expr); RBRACK; n=ID; SEMICOL
-          { VarDec (ArrayDef (t, d), n, None, loc $startpos $endpos) }
-        | t=basic_type; LBRACK; d=separated_list(COMMA, expr); RBRACK; n=ID; ASSIGN; v=expr; SEMICOL
-          { VarDec (ArrayDef (t, d), n, Some v, loc $startpos $endpos) }
-
-statement : ID; ASSIGN; expr; SEMICOL
-            { Assign ($1, $3, loc $startpos $endpos) }
-          | name=ID; LPAREN; params=separated_list(COMMA, expr); RPAREN; SEMICOL
-            { Expr (FunCall (name, params, loc $startpos $endpos)) }
-          | IF; LPAREN; expr; RPAREN; block
-            { If ($3, Block $5, loc $startpos $endpos) }                      %prec IF
-          | IF; LPAREN; expr; RPAREN; block; ELSE; block
-            { IfElse ($3, Block $5, Block $7, loc $startpos $endpos) }        %prec ELSE
-          | WHILE; LPAREN; expr; RPAREN; block
-            { While ($3, Block $5, loc $startpos $endpos) }
-          | DO; block; WHILE; LPAREN; expr; RPAREN; SEMICOL
-            { DoWhile ($5, Block $2, loc $startpos $endpos) }
-          | FOR; LPAREN; INT; id=ID; ASSIGN; start=expr; COMMA; stop=expr; RPAREN; body=block
-            { For (id, start, stop, IntConst (1, noloc), Block body, loc $startpos $endpos) }
-          | FOR; LPAREN; INT; id=ID; ASSIGN; start=expr; COMMA; stop=expr;
-                COMMA; step=expr; RPAREN; body=block
-            { For (id, start, stop, step, Block body, loc $startpos $endpos) }
-
-return_statement : RETURN; expr; SEMICOL  { [Return ($2, loc $startpos $endpos)] }
-
-block : LBRACE; statement*; RBRACE  { $2 }
-      | statement                   { [$1] }
-
-expr : LPAREN; expr; RPAREN                 { $2 }
-     | name=ID; LPAREN; params=separated_list(COMMA, expr); RPAREN
-       { FunCall (name, params, loc $startpos $endpos) }
-     | ID                                { Var ($1, loc $startpos $endpos) }
-     | l=expr; op=binop; r=expr          { Binop (op, l, r, loc $startpos $endpos) }
-     | SUB; expr                         { Monop (Neg, $2, loc $startpos $endpos) }    %prec NEG
-     | NOT; expr                         { Monop (Not, $2, loc $startpos $endpos) }
-     | LPAREN; basic_type; RPAREN; expr  { TypeCast ($2, $4, loc $startpos $endpos) }  %prec CAST
-     | FLOAT_CONST                       { FloatConst ($1, loc $startpos $endpos) }
-     | INT_CONST                         { IntConst ($1, loc $startpos $endpos) }
-     | BOOL_CONST                        { BoolConst ($1, loc $startpos $endpos) }
-     | ID; array_const                   { Deref ($1, $2, loc $startpos $endpos) }
-     | array_const                       { ArrayConst ($1, loc $startpos $endpos) }
-
-array_const : LBRACK; values=separated_list(COMMA, expr); RBRACK  { values }
-
-%inline binop : ADD { Add }
-              | SUB { Sub }
-              | MUL { Mul }
-              | DIV { Div }
-              | MOD { Mod }
-              | EQ  { Eq  }
-              | NE  { Ne  }
-              | LT  { Lt  }
-              | LE  { Le  }
-              | GT  { Gt  }
-              | GE  { Ge  }
-              | AND { And }
-              | OR  { Or  }
+basic_type:
+    | FLOAT { Float }
+    | INT   { Int }
+    | BOOL  { Bool }
+
+program:
+    decl*; EOF
+    { Program ($1, loc $startpos $endpos) }
+
+decl:
+    (* function: use location of function name *)
+    | EXTERN; hdr=fun_header; SEMICOL
+    { let (t, n, p, nameloc) = hdr in
+      FunDec(t, n, p, nameloc) }
+
+    | export=boption(EXPORT); hdr=fun_header; LBRACE; body=fun_body; RBRACE
+    { let (t, n, p, nameloc) = hdr in
+      FunDef (export, t, n, p, Block body, nameloc) }
+
+    (* global variable declaration: use location of variable name *)
+    | EXTERN; ctype=basic_type; name=ID; SEMICOL
+    { GlobalDec (ctype, name, loc $startpos $endpos) }
+
+    | EXTERN; ctype=basic_type;
+      LBRACK; dims=separated_list(COMMA, ID); RBRACK;
+      name=ID; SEMICOL
+    { let loc = loc $startpos(name) $endpos(name) in
+      GlobalDec (ArrayDec (ctype, dims), name, loc) }
+
+    | export=boption(EXPORT); ctype=basic_type; name=ID; SEMICOL
+    { let loc = loc $startpos(name) $endpos(name) in
+      GlobalDef (export, ctype, name, None, loc) }
+
+    | export=boption(EXPORT); ctype=basic_type; name=ID; ASSIGN; init=expr; SEMICOL
+    { let loc = loc $startpos(name) $endpos(name) in
+      GlobalDef (export, ctype, name, Some init, loc) }
+
+    | export=boption(EXPORT); ctype=basic_type;
+      LBRACK; dims=separated_list(COMMA, expr); RBRACK;
+      name=ID; SEMICOL
+    { let loc = loc $startpos(name) $endpos(name) in
+      GlobalDef (export, ArrayDef (ctype, dims), name, None, loc) }
+
+    | export=boption(EXPORT); ctype=basic_type;
+      LBRACK; dims=separated_list(COMMA, expr); RBRACK;
+      name=ID; ASSIGN; init=expr; SEMICOL
+    { let loc = loc $startpos(name) $endpos(name) in
+      GlobalDef (export, ArrayDef (ctype, dims), name, Some init, loc) }
+
+fun_header:
+    (* function header: use location of function name *)
+    | ret=basic_type; name=ID; LPAREN; params=separated_list(COMMA, param); RPAREN
+    { (ret, name, params, loc $startpos(name) $endpos(name)) }
+
+    | VOID; name=ID; LPAREN; params=separated_list(COMMA, param); RPAREN
+    { (Void, name, params, loc $startpos(name) $endpos(name)) }
+
+param:
+    (* parameter: use location of parameter name *)
+    ctype=basic_type; name=ID
+    { Param (ctype, name, loc $startpos(name) $endpos(name)) }
+
+fun_body:
+    var_dec* local_fun_dec* statement* loption(return_statement)
+    { $1 @ $2 @ $3 @ $4 }
+
+return_statement:
+    (* return statement: use location of return value *)
+    RETURN; value=expr; SEMICOL
+    { [Return (value, loc $startpos(value) $endpos(value))] }
+
+(* function: use location of function name *)
+local_fun_dec:
+    hdr=fun_header; LBRACE; body=fun_body; RBRACE
+    { let (t, n, p, nameloc) = hdr in
+      FunDef (false, t, n, p, Block body, nameloc) }
+
+var_dec:
+    (* variable declaration: use location of variable name *)
+    | ctype=basic_type; name=ID; SEMICOL
+    { VarDec (ctype, name, None, loc $startpos(name) $endpos(name)) }
+
+    | ctype=basic_type; name=ID; ASSIGN; init=expr; SEMICOL
+    { VarDec (ctype, name, Some init, loc $startpos(name) $endpos(name)) }
+
+    | ctype=basic_type; LBRACK; dims=separated_list(COMMA, expr); RBRACK;
+      name=ID; SEMICOL
+    { let loc = loc $startpos(name) $endpos(name) in
+      VarDec (ArrayDef (ctype, dims), name, None, loc) }
+
+    | ctype=basic_type; LBRACK; dims=separated_list(COMMA, expr); RBRACK;
+      name=ID; ASSIGN; init=expr; SEMICOL
+    { let loc = loc $startpos(name) $endpos(name) in
+      VarDec (ArrayDef (ctype, dims), name, Some init, loc) }
+
+statement:
+    (* assignment: use location of assigned variable name *)
+    | name=ID; ASSIGN; value=expr; SEMICOL
+    { Assign (name, value, loc $startpos(name) $endpos(name)) }
+
+    | name=ID; LPAREN; params=separated_list(COMMA, expr); RPAREN; SEMICOL
+    { Expr (FunCall (name, params, loc $startpos $endpos)) }
+
+    (* if-statements and (do-)while-loops: use location of condition *)
+    | IF; LPAREN; cond=expr; RPAREN; body=block
+    { If (cond, Block body, loc $startpos $endpos) }                %prec IF
+
+    | IF; LPAREN; c=expr; RPAREN; t=block; ELSE; f=block
+    { IfElse (c, Block t, Block f, loc $startpos(c) $endpos(c)) }   %prec ELSE
+
+    | WHILE; LPAREN; cond=expr; RPAREN; body=block
+    { While (cond, Block body, loc $startpos(cond) $endpos(cond)) }
+
+    | DO; body=block; WHILE; LPAREN; cond=expr; RPAREN; SEMICOL
+    { DoWhile (cond, Block body, loc $startpos(cond) $endpos(cond)) }
+
+    (* for-loop: use location of counter id *)
+    | FOR; LPAREN; INT; cnt=ID; ASSIGN; start=expr; COMMA; stop=expr; RPAREN;
+      body=block
+    { let loc = loc $startpos(cnt) $endpos(cnt) in
+      For (cnt, start, stop, IntConst (1, noloc), Block body, loc) }
+
+    | FOR; LPAREN; INT; cnt=ID; ASSIGN; start=expr; COMMA; stop=expr; COMMA;
+      step=expr; RPAREN; body=block
+    { let loc = loc $startpos(cnt) $endpos(cnt) in
+      For (cnt, start, stop, step, Block body, loc) }
+
+block:
+    | LBRACE; stats=statement*; RBRACE  { stats }
+    | stat=statement                    { [stat] }
+
+expr:
+    | name=ID; LPAREN; args=separated_list(COMMA, expr); RPAREN
+    { FunCall (name, args, loc $startpos $endpos) }
+
+    | LPAREN; expr; RPAREN              { $2 }
+    | ID                                { Var ($1, loc $startpos $endpos) }
+    | l=expr; op=binop; r=expr          { Binop (op, l, r, loc $startpos $endpos) }
+    | SUB; expr                         { Monop (Neg, $2, loc $startpos $endpos) }    %prec NEG
+    | NOT; expr                         { Monop (Not, $2, loc $startpos $endpos) }
+    | LPAREN; basic_type; RPAREN; expr  { TypeCast ($2, $4, loc $startpos $endpos) }  %prec CAST
+    | FLOAT_CONST                       { FloatConst ($1, loc $startpos $endpos) }
+    | INT_CONST                         { IntConst ($1, loc $startpos $endpos) }
+    | BOOL_CONST                        { BoolConst ($1, loc $startpos $endpos) }
+    | ID; array_const                   { Deref ($1, $2, loc $startpos $endpos) }
+    | array_const                       { ArrayConst ($1, loc $startpos $endpos) }
+
+%inline binop:
+    | ADD  { Add }
+    | SUB  { Sub }
+    | MUL  { Mul }
+    | DIV  { Div }
+    | MOD  { Mod }
+    | EQ   { Eq  }
+    | NE   { Ne  }
+    | LT   { Lt  }
+    | LE   { Le  }
+    | GT   { Gt  }
+    | GE   { Ge  }
+    | AND  { And }
+    | OR   { Or  }
+
+array_const:
+    LBRACK; values=separated_list(COMMA, expr); RBRACK
+    { values }
 
 %%