summaryrefslogblamecommitdiff
path: root/src/parser.mly
blob: c3e5be621a1d2e7f83e9dce5fdf075787bfd756c (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11






                                                                  



                







                                                                            






                      

                                
 
              


                                                         
               



                                                   

                                                                

 
                       






                   
            

                       
                         






                            
                              


            

                                       
                 

                                                                                         
                 
                                               

 



                           

 



                                               

 



                                


    


                                 

 




                      

 




















                                                                        


           
                      






                                                                  


                                          













                                                                    

 









                                                              
 
(*
	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 <int> INTVAL
%token <string> STRVAL
%token <string> IDENT
%token <string> 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 <Ast.program> 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) }
;