(* * Menhir wygeneruje funkcję o nazwie file *) %start file %{ open Xi_lib open Ast open Parser_utils (* Generator znaczników *) let mkTag = let i = ref 0 in fun () -> let tag = !i in incr i; NodeTag tag (* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv * Miejsce na twój kod w Ocamlu *) (* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----------------------------------------------------------------------------- *) %} (* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv * Miejsce na dyrektywy *) %token EOF %token COMMA %token LPAREN %token RPAREN %token LBRACKET %token RBRACKET %token LSBRACKET %token RSBRACKET %token COLON %token OP_PLUS %token OP_MINUS %token OP_MULT %token OP_DIV %token OP_REM %token OP_AND %token OP_OR %token OP_EQ %token OP_NEQ %token OP_LE %token OP_GE %token OP_LT %token OP_GT %token OP_NOT %token ASSIGN %token IF %token ELSE %token WHILE %token RETURN %token LENGTH %token INT %token IDENTIFIER %token STRING %token CHAR %token BOOL %token T_BOOL %token T_INT (* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----------------------------------------------------------------------------- *) %% (* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv * Miejsce na gramatykę *) (* Obecnie potrafimy sparsować tylko pusty plik (wymagamy od razu tokena EOF) *) file: | declarations= list(func) EOF { ModuleDefinition {global_declarations=declarations } } | EOF { ModuleDefinition {global_declarations=[] } } func: | id=identifier LPAREN parameters=separated_list(COMMA,var_decl) RPAREN return=return_type body=option(statement_block) { GDECL_Function { loc=mkLocation $startpos; id=id;formal_parameters=parameters; return_types=return;body=body} } var_decl: | id = identifier COLON t=typ { VarDecl {loc=mkLocation $startpos;id=id;tp=t} } return_type: | return = option(preceded(COLON,separated_list(COMMA,typ) ) ) { match return with | None -> [] | Some l -> l } typ: | t=base_type { t } | t=typ LSBRACKET dim=option(expression) RSBRACKET { TEXPR_Array { loc=mkLocation $startpos; sub=t;dim=dim } } base_type: | T_INT {TEXPR_Int {loc=mkLocation $startpos} } | T_BOOL {TEXPR_Bool {loc=mkLocation $startpos} } op_unary: | OP_MINUS { UNOP_Neg } | OP_NOT { UNOP_Not } op_mult_prec: | OP_MULT {BINOP_Mult} | OP_DIV {BINOP_Div} | OP_REM {BINOP_Rem} op_add_prec: | OP_PLUS {BINOP_Add} | OP_MINUS {BINOP_Sub} op_cmp_prec: | OP_LE {RELOP_Le} | OP_LT {RELOP_Lt} | OP_GE {RELOP_Ge} | OP_GT {RELOP_Gt} op_eq_prec: | OP_EQ {RELOP_Eq} | OP_NEQ {RELOP_Ne} expression: | node=expression_or {node} expression_or: | node=expression_and {node} | left=expression_or OP_OR right=expression_and {EXPR_Binop {tag=mkTag ();loc=mkLocation $startpos; op=BINOP_Or;lhs=left;rhs=right } } expression_and: | node=expression_eq {node} | left=expression_and OP_AND right=expression_eq {EXPR_Binop {tag=mkTag ();loc=mkLocation $startpos; op=BINOP_And;lhs=left;rhs=right } } expression_eq: | node=expression_cmp {node} | left=expression_eq op=op_eq_prec right=expression_cmp {EXPR_Relation {tag=mkTag ();loc=mkLocation $startpos; op=op;lhs=left;rhs=right } } expression_cmp: | node=expression_add {node} | left=expression_cmp op=op_cmp_prec right=expression_add {EXPR_Relation {tag=mkTag ();loc=mkLocation $startpos; op=op;lhs=left;rhs=right } } expression_add: | node=expression_mult { node } | left=expression_add op=op_add_prec right=expression_mult {EXPR_Binop {tag=mkTag ();loc=mkLocation $startpos; op=op;lhs=left;rhs=right } } expression_mult: | node=expression_unary { node } | left=expression_mult op=op_mult_prec right=expression_unary {EXPR_Binop {tag=mkTag ();loc=mkLocation $startpos; op=op;lhs=left;rhs=right } } expression_unary: | node=expression_highest_prec { node } | op=op_unary right=expression_unary {EXPR_Unop {tag=mkTag ();loc=mkLocation $startpos; op=op;sub=right } } expression_highest_prec: | node=expression_base { node } | node=expression_call { node } | node=expression_length { node } expression_base: | node=expression_integer { node } | node=expression_identifier { node } | node=expression_string { node } | LPAREN node=expression RPAREN { node } (* TODO Add calls and arrays and other constants *) expression_integer: | value=INT { EXPR_Int {tag= mkTag ();loc=mkLocation $startpos; value=Int32.of_int value} } expression_identifier: | id=identifier { EXPR_Id {tag= mkTag ();loc=mkLocation $startpos; id=id} } expression_string: | value=str { EXPR_String {tag= mkTag ();loc=mkLocation $startpos; value=value} } expression_call: | value=call { EXPR_Call value } expression_length: | LENGTH LPAREN argument=expression RPAREN { EXPR_Length { tag=mkTag (); loc=mkLocation $startpos; arg=argument } } statement_block: | LBRACKET body=list(statement) RBRACKET { STMTBlock { loc=mkLocation $startpos;body=body } } statement: | left=lvalue ASSIGN right=expression { STMT_Assign {loc=mkLocation $startpos; lhs=left;rhs=right} } | block=statement_block {STMT_Block block } | call=call {STMT_Call call } | var=var_decl init=option(preceded(ASSIGN,expression)) {STMT_VarDecl { var=var;init=init } } | WHILE cond=expression body=statement { STMT_While {loc=mkLocation $startpos;cond=cond;body=body } } | IF cond=expression then_branch=statement else_branch=option(preceded(ELSE,statement)) { STMT_If {loc=mkLocation $startpos;cond=cond;then_branch=then_branch; else_branch=else_branch } } | RETURN values=separated_list(COMMA,expression) { STMT_Return {loc=mkLocation $startpos;values=values } } call: | callee=identifier LPAREN arguments=separated_list(COMMA,expression) RPAREN { Call { tag=mkTag (); loc=mkLocation $startpos; callee=callee; arguments=arguments } } (* TODO Add other statements *) lvalue: | id=identifier {LVALUE_Id {loc=mkLocation $startpos;id=id} } (* TODO lvalue index *) identifier: | IDENTIFIER { Identifier $1 } str: | STRING { $1 } (* ** przykład użycia mkLocation use_declaration: | USE suffix(identifier, opt(SEMICOLON)) { GDECL_Use {loc=mkLocation $startpos; id=$2} } ** przykład użycia mkTag atomic_expression: | identifier { EXPR_Id {loc=mkLocation $startpos; id=$1; tag=mkTag ()} } *) (* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----------------------------------------------------------------------------- *)