(* Langages de Programmation et Compilation (J.-C. Filliatre) 2013-2014 Alex AUVOLAT Parser for Mini-C++ *) %{ open Ast type var = | VId of ident | VPtr of var | VRef of var let rec reverse_var bt v = match v with | VId(i) -> i, bt | VPtr(vv) -> let id, ty = reverse_var bt vv in id, TPtr(ty) | VRef(vv) -> let id, ty = reverse_var bt vv in id, TRef(ty) %} %token INTVAL %token STRVAL %token IDENT %token TIDENT (* this is stupid *) %token INCLUDE_IOSTREAM STD_COUT (* keywords *) %token CLASS ELSE FALSE FOR IF INT NEW NULL PUBLIC RETURN %token THIS TRUE VIRTUAL VOID WHILE (* operators *) %token ASSIGN LOR LAND EQ NE LT LE GT GE PLUS MINUS %token TIMES DIV MOD NOT INCR DECR REF %token LPAREN RPAREN RARROW DOT (* other symbols *) %token SEMICOLON COLON DOUBLECOLON LFLOW LBRACE RBRACE COMMA EOF (* operator priority *) %right ASSIGN %left LOR %left LAND %left EQ NE %left LT LE GT GE %left PLUS MINUS %left TIMES DIV MOD %right UNARY %left RARROW DOT LPAREN %start prog %% prog: INCLUDE_IOSTREAM? decls = declaration* EOF { List.flatten decls } ; declaration: | ident = typed_var LPAREN args = typed_var* RPAREN b = block { [ DFunction({p_ret_type = snd ident; p_name = fst ident; p_args = args}, b) ] } | vars = typed_vars SEMICOLON { List.map (fun k -> DGlobal(k)) vars } ; typed_var: | b = base_type x = var { reverse_var b x } ; typed_vars: | b = base_type x = separated_nonempty_list(COMMA, var) { List.map (reverse_var b) x } ; base_type: | VOID { TVoid } | INT { TInt } | t = TIDENT { TIdent(t) } ; var: | t = IDENT { VId(t) } | TIMES v = var { VPtr(v) } | REF v = var { VRef(v) } ; block: | LBRACE i = statement* RBRACE { i } ; statement: | SEMICOLON { SEmpty } | e = expression SEMICOLON { SExpr(e) } | IF LPAREN c = expression RPAREN s = statement { SIf(c, s, SEmpty) } | IF LPAREN c = expression RPAREN s = statement ELSE t = statement { SIf(c, s, t) } | WHILE LPAREN c = expression RPAREN s = statement { SWhile(c, s) } | FOR LPAREN k = separated_list(COMMA, expression) SEMICOLON c = expression? SEMICOLON r = separated_list(COMMA, expression) RPAREN b = statement { SFor(k, c, r, b) } | b = block { SBlock (b) } | RETURN e = expression? SEMICOLON { SReturn (e) } | k = typed_var v = preceded(ASSIGN, expression)? SEMICOLON { SDeclare(fst k, snd k, v) } ; expression: | NULL { ENull } | i = INTVAL { EInt(i) } | TRUE { EBool(true) } | FALSE { EBool(false) } | i = IDENT { EIdent(i) } | e1 = expression ASSIGN e2 = expression { EAssign(e1, e2) } | b = binop { b } | a = unop { a } | LPAREN e = expression RPAREN { e } ; binop: | a = expression EQ b = expression { EBinary(a, Equal, b) } | a = expression NE b = expression { EBinary(a, NotEqual, b) } | a = expression LAND b = expression { EBinary(a, Land, b) } | a = expression LOR b = expression { EBinary(a, Lor, b) } | a = expression GT b = expression { EBinary(a, Gt, b) } | a = expression GE b = expression { EBinary(a, Ge, b) } | a = expression LT b = expression { EBinary(a, Lt, b) } | a = expression LE b = expression { EBinary(a, Le, b) } | a = expression PLUS b = expression { EBinary(a, Add, b) } | a = expression MINUS b = expression { EBinary(a, Sub, b) } | a = expression TIMES b = expression { EBinary(a, Mul, b) } | a = expression DIV b = expression { EBinary(a, Div, b) } | a = expression MOD b = expression { EBinary(a, Modulo, b) } ; unop: | NOT e = expression { EUnary(Not, e) } %prec UNARY | MINUS e = expression { EUnary(Minus, e) } %prec UNARY | PLUS e = expression { EUnary(Plus, e) } %prec UNARY | REF e = expression { EUnary(Ref, e) } %prec UNARY | TIMES e = expression { EUnary(Deref, e) } %prec UNARY | INCR e = expression { EUnary(PreIncr, e) } %prec UNARY | e = expression INCR { EUnary(PostIncr, e) } | DECR e = expression { EUnary(PreDecr, e) } %prec UNARY | e = expression DECR { EUnary(PostDecr, e) } ;