# TODO modularize when possible grammar Gobstones
# TOP RULE: program rule program definitions main_def space* <ProgramNode> end # DEFINITIONS: main, procedures, functions rule definitions (space* definition space*)* end rule definition procedure_def / function_def end rule main_def 'procedure' space+ 'Main' space* '(' space* ')' space* '{' space* commands ret:main_return? space* '}' <MainDefNode> end rule main_return 'return' space* var_tuple space* ';'? <MainReturnNode> end rule procedure_def 'procedure' space+ proc_name space* var_tuple space* cmd_block <ProcedureNode> end rule function_def 'function' space+ func_name space* var_tuple space* '{' space* commands func_return space* '}' <FunctionNode> end rule func_return 'return' space* gexp_tuple_1 space* ';'? <FuncReturnNode> end # COMMANDS rule commands (command space* ';'? space*)* end rule command simple_cmd / complex_cmd end rule simple_cmd skip_cmd / boom_cmd / poner_cmd / sacar_cmd / mover_cmd / ir_al_origen_cmd / vaciar_tablero_cmd / proc_call / cmd_block / single_assignment / multiple_assignment end rule skip_cmd 'Skip' <SkipCmdNode> end rule boom_cmd 'BOOM' space* '(' space* string space* ')' <BoomCmdNode> end rule poner_cmd 'Poner' space* '(' space* gexp space* ')' <PonerCmdNode> end rule sacar_cmd 'Sacar' space* '(' space* gexp space* ')' <SacarCmdNode> end rule mover_cmd 'Mover' space* '(' space* gexp space* ')' <MoverCmdNode> end rule ir_al_origen_cmd 'IrAlOrigen' space* '(' space* ')' <IrAlOrigenCmdNode> end rule vaciar_tablero_cmd 'VaciarTablero' space* '(' space* ')' <VaciarTableroCmdNode> end rule proc_call proc_name space* gexp_tuple <ProcCallNode> end rule cmd_block '{' space* commands space* '}' <CmdBlockNode> end rule single_assignment var_name space* ':=' space* gexp <SingleAssignmentNode> end rule multiple_assignment var_tuple space* ':=' space* gexp <MultipleAssignmentNode> end rule complex_cmd if_cmd / while_cmd / repeat_with_cmd # / case_cmd end rule if_cmd 'if' space* '(' space* gexp space* ')' space* then_block:cmd_block else_clause:(space* 'else' space* else_block:cmd_block)? <IfCmdNode> end rule while_cmd 'while' space* '(' space* gexp space* ')' space* cmd_block <WhileCmdNode> end rule repeat_with_cmd 'repeatWith' space+ var_name space+ 'in' space+ range_min:gexp space* '..' space* range_max:gexp space* cmd_block <RepeatWithCmdNode> end # TODO implement # rule case_cmd # end # EXPRESSIONS rule gexp bexp end rule bexp left:bterm space* '||' space* right:bexp <OrExprNode> / bterm end rule bterm left:bfact space* '&&' space* right:bterm <AndExprNode> / bfact end rule bfact 'not' space+ exp:batom <NotExprNode> / batom end rule batom left:nexp space* rop space* right:nexp <RopExprNode> / nexp end rule rop '==' / '/=' / '<=' / '>=' / '<' / '>' end rule nexp left:nterm sub_exps:(space* op:[+-] space* right:nterm)* <NopExprNode> end rule nterm left:nfactH sub_exps:(space* '*' space* right:nfactH)* <MulExprNode> end rule nfactH left:nfactL space+ op:mop space+ right:nfactL <DivModExprNode> / nfactL end rule mop 'div' / 'mod' end rule nfactL left:natom sub_exps:(space* '^' space* right:natom)* <PowExprNode> end rule natom literal / type_bound_func / primitive_func / paren_expr / func_call / var_name end rule type_bound_func bool_type_bound_func / color_type_bound_func / direction_type_bound_func end rule bool_type_bound_func 'minBool()' <MinBoolFuncNode> / 'maxBool()' <MaxBoolFuncNode> end rule color_type_bound_func 'minColor()' <MinColorFuncNode> / 'maxColor()' <MaxColorFuncNode> end rule direction_type_bound_func 'minDir()' <MinDirFuncNode> / 'maxDir()' <MaxDirFuncNode> end rule primitive_func nro_bolitas_func / hay_bolitas_func / puede_mover_func / siguiente_func / previo_func / opuesto_func end rule nro_bolitas_func 'nroBolitas' space* '(' space* gexp space* ')' <NroBolitasFuncNode> end rule hay_bolitas_func 'hayBolitas' space* '(' space* gexp space* ')' <HayBolitasFuncNode> end rule puede_mover_func 'puedeMover' space* '(' space* gexp space* ')' <PuedeMoverFuncNode> end rule siguiente_func 'siguiente' space* '(' space* gexp space* ')' <SiguienteFuncNode> end rule previo_func 'previo' space* '(' space* gexp space* ')' <PrevioFuncNode> end rule opuesto_func 'opuesto' space* '(' space* gexp space* ')' <OpuestoFuncNode> end rule paren_expr '(' space* gexp space* ')' <ParenthesesExprNode> end rule func_call func_name space* gexp_tuple <FuncCallNode> end rule var_name lower_id &{ |id| id[0].is_not_reserved } <VarNameNode> end # LITERALS rule literal number / boolean / color / direction end rule number '-'? [0-9] [0-9]* <IntegerLiteral> end rule boolean ('True' / 'False') <BooleanLiteral> end rule color ('Azul' / 'Negro' / 'Rojo' / 'Verde') <ColorLiteral> end rule direction ('Norte' / 'Este' / 'Sur' / 'Oeste') <DirectionLiteral> end # AUX DEFINITIONS: identifiers, tuples rule proc_name upper_id &{ |id| id[0].is_not_reserved } end rule func_name lower_id &{ |id| id[0].is_not_reserved } end rule var_tuple '(' space* vns:var_names? space* ')' <VarTupleNode> end rule var_names ((vn:var_name space* ',' space* vns:var_names) / var_name) <VarNamesNode> end rule gexp_tuple '(' space* exps:gexps? space* ')' <TupleExprNode> end rule gexp_tuple_1 '(' space* exps:gexps space* ')' <TupleExprNode> end rule gexps ((exp:gexp space* ',' space* exps:gexps) / gexp) <GexpsNode> end rule lower_id [a-z] char* { def is_not_reserved !Gobstones::Parser::RESERVED_IDS.include? text_value end } end rule upper_id [A-Z] char* { def is_not_reserved !Gobstones::Parser::RESERVED_IDS.include? text_value end } end rule char [a-zA-Z0-9'_] end rule string '"' ('\"' / !'"' .)* '"' end rule space [\s] end
end