(** Parse Abstract Syntax Tree from input file content. *) (** This phase takes [FileContent] as input and outputs a corresponding [Ast]. Syntax errors are caught and transformed into {!Types.FatalError} with a [LocMsg], so that the error can be highlighted in the input file code. The global files [lexer.mll] and [parser.mly] implement the grammar specified by the CiviC language manual. This includes the extensions of nested functions and multi-dimensional arrays. The entire CiviC grammar implementation is summarized below. Note that Menhir parser syntax is used on some occasions. {v basic_type: | FLOAT | INT | BOOL program: | decl* EOF decl: | EXTERN fun_header SEMICOL | boption(EXPORT) fun_header LBRACE fun_body RBRACE | EXTERN basic_type ID SEMICOL | EXTERN basic_type LBRACK dimlist RBRACK ID SEMICOL | boption(EXPORT) basic_type ID SEMICOL | boption(EXPORT) basic_type ID ASSIGN expr SEMICOL | boption(EXPORT) basic_type LBRACK separated_list(COMMA, expr) RBRACK ID SEMICOL fun_header: | basic_type ID LPAREN separated_list(COMMA, param) RPAREN | VOID ID LPAREN separated_list(COMMA, param) RPAREN param: | basic_type ID | basic_type LBRACK dimlist RBRACK ID dimlist: | ID | dimlist COMMA ID fun_body: | var_dec* local_fun_dec* statement* loption(return_statement) return_statement: | RETURN expr SEMICOL local_fun_dec: | fun_header LBRACE fun_body RBRACE var_dec: | basic_type ID SEMICOL | basic_type ID ASSIGN expr SEMICOL | basic_type LBRACK separated_list(COMMA, expr) RBRACK ID SEMICOL | basic_type LBRACK separated_list(COMMA, expr) RBRACK ID ASSIGN expr SEMICOL statement: | ID ASSIGN expr SEMICOL | ID LBRACK separated_list(COMMA, expr) RBRACK ASSIGN expr SEMICOL | ID LPAREN separated_list(COMMA, expr) RPAREN SEMICOL | IF LPAREN expr RPAREN block %prec IF | IF LPAREN expr RPAREN block ELSE block %prec ELSE | WHILE LPAREN expr RPAREN block | DO block WHILE LPAREN expr RPAREN SEMICOL | FOR LPAREN INT ID ASSIGN expr COMMA expr RPAREN block | FOR LPAREN INT ID ASSIGN expr COMMA expr COMMA expr RPAREN block block: | LBRACE statement* RBRACE | statement expr: | ID LPAREN separated_list(COMMA, expr) RPAREN | LPAREN expr RPAREN | ID | expr ADD expr | expr SUB expr | expr MUL expr | expr DIV expr | expr MOD expr | expr EQ expr | expr NE expr | expr LT expr | expr LE expr | expr GT expr | expr GE expr | expr AND expr | expr OR expr | SUB expr %prec NEG | NOT expr | LPAREN basic_type RPAREN expr %prec CAST | FLOAT_CONST | INT_CONST | BOOL_CONST | ID array_const | array_const array_const: | LBRACK separated_list(COMMA, expr) RBRACK v} *) (** Main phase function, called by {!Main}. *) val phase : Main.phase_func