class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", "IFX"), ("nonassoc", "ELSE"), ("right", "="), ("left", "OR"), ("left", "AND"), ("left", "|"), ("left", "^"), ("left", "&"), ("nonassoc", "<", ">", "EQ", "NEQ", "LE", "GE"), ("left", "SHL", "SHR"), ("left", "+", "-"), ("left", "*", "/", "%"), ) def p_error(self, p): if not p: print("Syntax error at end of input") else: pass def handle_error(self, type, p): print( "Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format( p.lineno, self.scanner.find_tok_column(p), p.type, p.value ) ) def p_program(self, p): """program : declarations fundefs_opt instructions_opt""" p[0] = Program(p[1], p[2], p[3]) # declarations def p_declarations(self, p): """declarations : declarations declaration""" if p[2]: p[0] = DeclarationList(p[1].dec_list + [p[2]]) else: p[0] = p[1] def p_no_declarations(self, p): """declarations : """ p[0] = DeclarationList([]) # END declarations # declaration def p_declaration(self, p): """declaration : TYPE inits ';'""" p[0] = Declaration(p[1], p[2]) def p_error_declaration(self, p): """declaration : error ';'""" self.handle_error("declaration", p[1]) # END declaration # inits def p_inits(self, p): """inits : inits ',' init""" p[0] = InitList(p[1].init_list + [p[3]]) def p_single_init(self, p): """inits : init """ p[0] = InitList([p[1]]) # END inits def p_init(self, p): """init : ID '=' expression """ p[0] = Init(p[1], p[3]) # instructions_opt def p_instructions_opt(self, p): """instructions_opt : instructions""" p[0] = p[1] def p_empty_instructions_opt(self, p): """instructions_opt : """ p[0] = InstructionList([]) # END instructions_opt # instructions def p_instructions(self, p): """instructions : instructions instruction""" p[0] = InstructionList(p[1].instr_list + [p[2]]) def p_sinle_instruction(self, p): """instructions : instruction """ p[0] = InstructionList([p[1]]) # END instructions def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] # print_instr def p_print_instr(self, p): """print_instr : PRINT expr_list ';'""" p[0] = PrintInstr(p[2]) def p_print_instr_err(self, p): """print_instr : PRINT error ';' """ self.handle_error("print", p[2]) # END print_instr def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = Labeled_instr(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = Assignment(p[1], p[3]) # choice_instr def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX """ p[0] = ChoiceInstr(p[3], p[5]) def p_choice_instr_with_else(self, p): """choice_instr : IF '(' condition ')' instruction ELSE instruction """ p[0] = ChoiceInstr(p[3], p[5], p[7]) def p_error_choice_instr(self, p): """choice_instr : IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ self.handle_error("IF", p[3]) # END choice)instr # while_instr def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction """ p[0] = WhileInstr(p[3], p[5]) def p_error_while_instr(self, p): """while_instr : WHILE '(' error ')' instruction """ self.handle_error("while", p[3]) # END while_instr def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = RepeatInstr(p[4], p[2]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = Return(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = KeyWord("continue") def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = KeyWord("break") def p_compound_instr(self, p): """compound_instr : '{' declarations instructions_opt '}' """ p[0] = Compound_instr(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = Condition(p[1]) def p_const_I(self, p): """const : INTEGER""" p[0] = Integer(p[1]) def p_const_F(self, p): """const : FLOAT""" p[0] = Float(p[1]) def p_const_S(self, p): """const : STRING""" p[0] = String(p[1]) # expression def p_expression(self, p): """expression : ID '(' expr_list_or_empty ')' """ p[0] = ExpressionIdWithList(p[1], p[3]) def p_expression_const(self, p): """expression : const """ p[0] = p[1] def p_expression_id(self, p): """expression : ID """ p[0] = Id(p[1]) def p_expression_with_par(self, p): """expression : '(' expression ')' """ p[0] = p[2] def p_expression_two_exprs(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression """ p[0] = BinExpr(p[2], p[1], p[3]) def p_expression_err(self, p): """expression : ID '(' error ')' | '(' error ')'""" self.handle_error("Expr", p[2]) # END expression # expr_list_or_empty def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list""" p[0] = p[1] def p_empty_expr_list(self, p): """expr_list_or_empty : """ p[0] = ExprList([]) # END expr_list_or_empty # expr_list def p_expr_list(self, p): """expr_list : expr_list ',' expression""" p[0] = ExprList(p[1].expr_list + [p[3]]) def p_single_expr(self, p): """expr_list : expression """ p[0] = ExprList([p[1]]) # END expr_list # fundefs_opt def p_fundefs_opt(self, p): """fundefs_opt : fundefs""" p[0] = p[1] def p_empty_fundefs_opt(self, p): """fundefs_opt : """ p[0] = FunctionList([]) # END fundefs_opt # fundefs def p_fundefs(self, p): """fundefs : fundefs fundef""" p[0] = FunctionList(p[1].fun_list + [p[2]]) def p_single_fundef(self, p): """fundefs : fundef """ p[0] = FunctionList([p[1]]) # END fundefs def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = Function(p[1], p[2], p[4], p[6]) # args_list_or_empty def p_args_list_or_empty(self, p): """args_list_or_empty : args_list""" p[0] = p[1] def p_empty_args_list(self, p): """args_list_or_empty : """ p[0] = ArgsList([]) # END args_list_or_empty # args_list def p_args_list(self, p): """args_list : args_list ',' arg""" p[0] = ArgsList(p[1].args_list + [p[3]]) def p_single_arg_list(self, p): """args_list : arg """ p[0] = ArgsList([p[1]]) # END args_list def p_arg(self, p): """arg : TYPE ID """ p[0] = Arg(p[1], p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() self.errors = False tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): self.errors = True err_format = "Syntax error at line {0}, column {1}: LexToken({2}, '{3}')" if p: print( err_format.format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" # ^ ^ ^ ^ # p[0] p[1] p[2] p[3] program = AST.Program(p[1], p[2], p[3]) p[0] = program def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: # occurs when declarations -> declarations declaration p[1].declarations.append(p[2]) p[0] = p[1] else: # occurs when declarations -> epsilon p[0] = AST.Declarations() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 3: # occurs when error p[0] = p[1] else: p[0] = AST.Declaration(p[1], p[2]) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: # occurs when inits -> inits, init p[0] = p[1] p[0].inits.append(p[3]) else: # occurs when inits -> init p[0] = AST.Inits() p[0].inits.append(p[1]) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3], p.lineno(1)) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: # occurs when instructions -> instructions instruction p[1].instructions.append(p[2]) p[0] = p[1] else: # occurs when instructions -> instruction p[0] = AST.Instructions() p[0].instructions.append(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.PrintInstr(p[2], p.lineno(1)) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstruction(p[1], p[3], p.lineno(1)) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3], p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 8: p[0] = AST.IfElseInstr(p[3], p[5], p[7]) else: p[0] = AST.IfInstr(p[3], p[5]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p[4], p[2]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstr(p[2], p.lineno(1)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstr(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" lineno = p.lineno(1) try: int(p[1]) p[0] = AST.Integer(p[1], lineno) except ValueError: try: float(p[1]) p[0] = AST.Float(p[1], lineno) except ValueError: p[0] = AST.String(p[1], lineno) def p_id_expr(self, p): """expression : ID""" p[0] = AST.Variable(p[1], p.lineno(1)) def p_const_expr(self, p): """expression : const""" p[0] = p[1] def p_paren_expression(self, p): """expression : '(' expression ')' | '(' error ')'""" p[0] = AST.ParenExpr(p[2]) def p_funcall(self, p): """expression : ID '(' expr_list_or_empty ')' | ID '(' error ')' """ p[0] = AST.Funcall(p[1], p[3], p.lineno(1)) def p_bin_expression(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression""" p[0] = AST.BinExpr(p[2], p[1], p[3], p.lineno(2)) # operator pierwszy def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ p[0] = None if len(p) == 1 else p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ p[0] = AST.ExprList() if len(p) == 4: p[0].cons_expr(p[1].expr_list, p[3]) else: p[0].append_expr(p[1]) def p_fundefs(self, p): """fundefs : fundef fundefs | """ p[0] = AST.FundefList() if len(p) == 3: p[0].cons_fun(p[2].fundef_list, p[1]) elif len(p) == 2: p[0].append_fun(p[1]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.Fundef(p[1], p[2], p[4], p[6], p.lineno(1)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.ArgList() # empty def p_args_list(self, p): """args_list : args_list ',' arg | arg """ p[0] = AST.ArgList() if len(p) == 4: p[0].cons_arg(p[1].arg_list, p[3]) else: p[0].append_arg(p[1]) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p[1], p[2], p.lineno(1))
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : blocks""" p[0] = AST.Program(p[1]) # p[0] = ('PROGRAM',p[1], p[2], p[3]) def p_blocks(self, p): """blocks : blocks block |""" if len(p) == 3: p[0] = p[1] p[0].addArgument(p[2]) else: p[0] = AST.BlockList() def p_block(self, p): """block : declaration | fundef | instruction""" p[0] = AST.Block(p[1]) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: p[0] = p[1] p[0].addArgument(p[2]) else: p[0] = AST.DeclarationList() # else: # p[0] = AST.Declarations(p[1], p[2]) # if len(p) == 2: # p[0] = ("DECLARATIONS", p[1]) # elif len(p) == 3: # p[0] = ("DECLARATIONS", p[1], p[2]) # else: # p[0] = ("DECLARATIONS") def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ p[0] = AST.Declaration(p[1], p[2]) # p[0] = ("DECLARATION",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[0] = AST.InitList() if p[1] is None else p[1] p[0].addArgument(p[3]) else: p[0] = AST.InitList() p[0].addArgument(p[1]) # p[0] = ("INITS", p[1]) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[2], p[3], p.lineno(1)) # p[0] = ("INIT", p[1], p[2], p[3]) # # def p_instructions_opt(self, p): # """instructions_opt : instructions # | """ # if len(p) == 2: # p[0] = AST.Instructions(p[1], None) # else: # p[0] = AST.Instructions(None, None) # # else: # # p[0] = AST.Instructions(p[1], p[2]) # # # # # # p[0] = ("INSTRUCTIONS_OPT", p[1]) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[0] = AST.InstructionList() if p[1] is None else p[1] p[0].addArgument(p[2]) else: p[0] = AST.InstructionList() p[0].addArgument(p[1]) # p[0] = ("INSTRUCTIONS", p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ # for i in (0, len(p)): # print(str(i) + " " + str(p[i])) p[0] = p[1] # p[0] = ("INSTRUCTION", p[1]) def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.PrintInstruction(p[1], p[2], p.lineno(1)) # p[0] = ("PRINT_INSTR", p[1], p[2], p[3]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstr(p[1], p[3], p.lineno(1)) # p[0] = ("LABELED_INSTR", p[1], p[2], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[2], p[3], p.lineno(1)) # p[0] = ("ASSIGNMENT", p[1], p[2], p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ # for i in range(0, len(p)): # print(str(i) + " " + str(p[i])) if len(p) > 7: p[0] = AST.ChoiceInstr(p[3], p[5], p[7], p.lineno(1)) else: p[0] = AST.ChoiceInstr(p[3], p[5], None, p.lineno(1)) # p[0] = ("CHOICE_INSTR", p[1], p[3], p[5]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p[3], p[5], p.lineno(1)) # p[0] = ("WHILE_INSTR", p[1], p[3], p[5], ) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p[2], p[4], p.lineno(1)) # p[0] = ("REPEAt_INSTR", p[1], p[2], p[3]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.Return_instr(p[2], p.lineno(1)) # p[0] = ("REPEAT_INSTR", p[1], p[2], p[3]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr(p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr(p.lineno(1)) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstr(p[2], p[3]) # p[0] = ("COMPOUND_INSTR", p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" # p[0] = AST.Const(p.slice[1].type) p[0] = { 'INTEGER': lambda : AST.Integer(p[1]), 'FLOAT': lambda : AST.Float(p[1]), 'STRING': lambda : AST.String(p[1]) }[p.slice[1].type]() # p[0] = ("CONST", p[1]) def p_expression_id(self, p): """expression : ID""" p[0] = AST.Variable(p[1], p.lineno(1)) def p_expression(self, p): """expression : const | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ # for i in range(0, len(p)): # print(str(i) + " " + str(p[i])) # # if len(p) == 2: # p[0] = AST.BinExpr(None,p[1],None) # # else: # p[0] = AST.BinExpr(p[2],p[1],p[3]) if len(p) == 2: p[0] = p[1] elif len(p) == 4 and p[1] != '(': p[0] = AST.BinExpr(p[2],p[1],p[3], p.lineno(2)) elif len(p) == 4: p[0] = AST.UnaryExpr(p[2]) elif len(p) == 5: p[0] = AST.FunctionExpression(p[1], p[3], p.lineno(1)) # # # if len(p) == 2: # p[0] = AST.BinExpr(None,p[1],None) # elif len(p) == 4 and p[1] != '(': # p[0] = p[0] = AST.BinExpr(p[2],p[1],p[3]) # elif len(p) == 4: # p[0] = AST.BinExpr(None,p[2],None) # elif len(p) == 5: # p[0] = AST.BinExpr(None, p[1], p[3]) # p[0] = ("EXPRESSIONxD" + str(len(p)),) # for i in range(1, len(p)): # p[0] += (p[i],) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = None # p[0] = ("EXPRESSION_LIST_OR_EMPTY",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = AST.ExpressionList() if p[1] is None else p[1] p[0].addArgument(p[3]) else: p[0] = AST.ExpressionList() p[0].addArgument(p[1]) # p[0] = ("EXPRESSION_LIST",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.Fundef( p[1], p[2], p[4], p[6], p.lineno(1)) # p[0] = ("FUNDEF",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = None # p[0] = ("ARGS_LIST_OR_EMPTY",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = AST.ArgList() if p[1] is None else p[1] p[0].addArgument(p[3]) else: p[0] = AST.ArgList() p[0].addArgument(p[1]) # p[0] = ("ARGS_LIST",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p[1], p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() self.no_error = True tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): self.no_error = False if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : blocks""" p[0] = AST.Program(p[1]) p[0].line = self.scanner.lexer.lineno if self.no_error: # p[0].print_tree(0) pass def p_blocks(self, p): """blocks : blocks block | block """ if len(p) > 2: p[0] = AST.Blocks(p[2], p[1]) else: p[0] = AST.Blocks(p[1], None) p[0].line = self.scanner.lexer.lineno def p_block(self, p): """block : fundef | instruction | declaration """ p[0] = p[1] p[0].line = self.scanner.lexer.lineno # def p_declarations(self, p): # """declarations : declarations declaration # | """ # if self.no_error: # if len(p) > 1: # p[0] = AST.Declarations(p[1], p[2]) # else: # p[0] = AST.Declarations(None, None) # p[0].line = self.scanner.lexer.lineno def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) > 3: p[0] = AST.Declaration(p[1], p[2], None) else: p[0] = AST.Declaration(None, None, p[1]) p[0].line = self.scanner.lexer.lineno def p_inits(self, p): """inits : inits ',' init | init """ if len(p) > 2: p[0] = AST.Inits(p[1], p[3]) else: p[0] = AST.Inits(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) > 2: p[0] = AST.Instructions(p[1], p[2]) else: p[0] = AST.Instructions(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] p[0].line = self.scanner.lexer.lineno def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ if isinstance(p[2], AST.Expression): p[0] = AST.Print(p[2], None) else: p[0] = AST.Print(None, p[2]) p[0].line = self.scanner.lexer.lineno def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.Labeled(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if isinstance(p[3], AST.Condition): if len(p) == 8 and p[6].lower() == "else": if_node = AST.If(p[3], p[5], None) if_node.line = self.scanner.lexer.lineno else_node = AST.Else(p[7]) else_node.line = self.scanner.lexer.lineno p[0] = AST.Choice(if_node, else_node) else: if_node = AST.If(p[3], p[5], None) if_node.line = self.scanner.lexer.lineno p[0] = AST.Choice(if_node, None) else: if len(p) == 8 and p[6].lower() == "else": if_node = AST.If(None, p[5], p[3]) if_node.line = self.scanner.lexer.lineno else_node = AST.Else(p[7]) else_node.line = self.scanner.lexer.lineno p[0] = AST.Choice(if_node, else_node) else: if_node = AST.If(None, p[5], p[3]) if_node.line = self.scanner.lexer.lineno p[0] = AST.Choice(if_node, None) p[0].line = self.scanner.lexer.lineno def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ if isinstance(p[3], AST.Condition): p[0] = AST.While(p[3], p[5], None) else: p[0] = AST.While(None, p[5], p[3]) p[0].line = self.scanner.lexer.lineno def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatUntil(p[2], p[4]) p[0].line = self.scanner.lexer.lineno def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.Return(p[2]) p[0].line = self.scanner.lexer.lineno def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.Continue() p[0].line = self.scanner.lexer.lineno def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.Break() p[0].line = self.scanner.lexer.lineno def p_compound_instr(self, p): """compound_instr : '{' blocks '}' """ p[0] = AST.Compound(p[2]) p[0].line = self.scanner.lexer.lineno def p_condition(self, p): """condition : expression""" p[0] = p[1] p[0].line = self.scanner.lexer.lineno def p_const(self, p): """const : INTEGER | FLOAT | STRING""" p[0] = AST.Const(p[1]) p[0].line = self.scanner.lexer.lineno def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: if isinstance(p[1], AST.Const): p[0] = p[1] else: p[0] = AST.Id(p[1]) elif len(p) == 4: if p[1] == "(": if isinstance(p[2], AST.Expression): p[0] = AST.ExpressionInPar(p[2], None) else: p[0] = AST.ExpressionInPar(None, p[2]) else: p[0] = AST.BinExpr(p[1], p[2], p[3]) else: if isinstance(p[3], AST.ExpressionList): p[0] = AST.IdWithPar(p[1], p[3], None) else: p[0] = AST.IdWithPar(p[1], None, p[3]) p[0].line = self.scanner.lexer.lineno def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) > 1: p[0] = AST.ExpressionList(p[1], None) else: p[0] = AST.ExpressionList(None, None) p[0].line = self.scanner.lexer.lineno def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) > 2: p[0] = AST.ExpressionList(p[1], p[3]) else: p[0] = AST.ExpressionList(None, p[1]) p[0].line = self.scanner.lexer.lineno #def p_fundefs_opt(self, p): # """fundefs_opt : fundefs # | """ # def p_fundefs(self, p): # """fundefs : fundefs fundef # | fundef """ # if len(p) > 2: # p[0] = AST.FunctionDefinitions(p[2], p[1]) # else: # p[0] = AST.FunctionDefinitions(p[1], None) # p[0].line = self.scanner.lexer.lineno def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunctionDefinition(p[1],p[2],p[4],p[6]) p[0].line = self.scanner.lexer.lineno def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) > 1: p[0] = AST.ArgumentList(p[1], None) else: p[0] = AST.ArgumentList(None, None) p[0].line = self.scanner.lexer.lineno def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) > 2: p[0] = AST.ArgumentList(p[1], p[3]) else: p[0] = AST.ArgumentList(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Argument(p[1], p[2]) p[0].line = self.scanner.lexer.lineno
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : blocks""" p[0] = AST.Program(p[1]) # p[0] = ('PROGRAM',p[1], p[2], p[3]) def p_blocks(self, p): """blocks : blocks block |""" if len(p) == 3: p[0] = AST.Blocks(p[1], p[2]) else: p[0] = AST.Blocks(None, None) def p_block(self, p): """block : declaration | fundef | instruction""" p[0] = AST.Block(p[1]) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: p[0] = AST.Declarations(p[1], p[2]) else: p[0] = AST.Declarations(None, None) # else: # p[0] = AST.Declarations(p[1], p[2]) # if len(p) == 2: # p[0] = ("DECLARATIONS", p[1]) # elif len(p) == 3: # p[0] = ("DECLARATIONS", p[1], p[2]) # else: # p[0] = ("DECLARATIONS") def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ p[0] = AST.Declaration(p[1], p[2]) # p[0] = ("DECLARATION",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 2: p[0] = AST.Inits(None, p[1]) else: p[0] = AST.Inits(p[1], p[3]) # p[0] = ("INITS", p[1]) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[2], p[3]) # p[0] = ("INIT", p[1], p[2], p[3]) def p_instructions_opt(self, p): """instructions_opt : instructions | """ if len(p) == 2: p[0] = AST.Instructions(p[1], None) else: p[0] = AST.Instructions(None, None) # else: # p[0] = AST.Instructions(p[1], p[2]) # # # p[0] = ("INSTRUCTIONS_OPT", p[1]) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 2: p[0] = AST.Instructions(p[1], None) else: p[0] = AST.Instructions(p[1], p[2]) # p[0] = ("INSTRUCTIONS", p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ # for i in (0, len(p)): # print(str(i) + " " + str(p[i])) p[0] = AST.Instruction(p[1]) # p[0] = ("INSTRUCTION", p[1]) def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ p[0] = AST.PrintInstruction(p[1], p[2]) # p[0] = ("PRINT_INSTR", p[1], p[2], p[3]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstr(p[1], p[3]) # p[0] = ("LABELED_INSTR", p[1], p[2], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[2], p[3]) # p[0] = ("ASSIGNMENT", p[1], p[2], p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ # for i in range(0, len(p)): # print(str(i) + " " + str(p[i])) p[0] = AST.ChoiceInstr(p[3], p[5], p[7]) # p[0] = ("CHOICE_INSTR", p[1], p[3], p[5]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p[3], p[5]) # p[0] = ("WHILE_INSTR", p[1], p[3], p[5], ) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p[2], p[4]) # p[0] = ("REPEAt_INSTR", p[1], p[2], p[3]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.Return_instr(p[2]) # p[0] = ("REPEAT_INSTR", p[1], p[2], p[3]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions_opt '}' """ p[0] = AST.CompoundInstr(p[2], p[3]) # p[0] = ("COMPOUND_INSTR", p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = AST.Condition(p[1]) def p_const(self, p): """const : INTEGER | FLOAT | STRING""" p[0] = AST.Const(p[1]) # p[0] = ("CONST", p[1]) def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ # for i in range(0, len(p)): # print(str(i) + " " + str(p[i])) # # if len(p) == 2: # p[0] = AST.BinExpr(None,p[1],None) # # else: # p[0] = AST.BinExpr(p[2],p[1],p[3]) if len(p) == 2: p[0] = AST.BinExpr(None, p[1], None) elif len(p) == 4 and p[1] != '(': p[0] = p[0] = AST.BinExpr(p[2], p[1], p[3]) elif len(p) == 4: p[0] = AST.BinExpr(None, p[2], None) elif len(p) == 5: p[0] = AST.BinExpr(None, p[1], p[3]) # p[0] = ("EXPRESSIONxD" + str(len(p)),) # for i in range(1, len(p)): # p[0] += (p[i],) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = AST.FunDefs(p[1], None) else: p[0] = AST.FunDefs(p[1], p[2]) # p[0] = ("EXPRESSION_LIST_OR_EMPTY",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 2: p[0] = AST.ExpressionList(p[1], None) else: p[0] = AST.ExpressionList(p[1], p[3]) # p[0] = ("EXPRESSION_LIST",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.Fundef(p[1], p[2], p[4], p[6]) # p[0] = ("FUNDEF",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = AST.ArgList(p[1], None) # p[0] = ("ARGS_LIST_OR_EMPTY",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 2: p[0] = AST.ArgList(p[1], None) else: p[0] = AST.ArgList(p[1], p[3]) # p[0] = ("ARGS_LIST",) # # for i in range(1, len(p)): # p[0] += (p[i],) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p[1], p[2])
class Parser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" p[0] = AST.Program(AST.Declarations.mapTypedDeclarations(p[1]), utils.flatten(p[2]), AST.Instructions(utils.flatten(p[3]))) p[0].set_parents() p[0].set_scope() p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) > 1: p[0] = [p[1], p[2]] else: p[0] = [] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ p[0] = AST.TypedDeclarations(p[1], utils.flatten(p[2])) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) > 2: p[0] = [p[1], p[3]] else: p[0] = [p[1]] def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Declaration(p[1], p[3]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) > 2: p[0] = [p[1], p[2]] else: p[0] = [p[1]] def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.PrintInstruction(p[2]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstruction(p[1], p[3]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.AssignmentInstruction(p[1], p[3]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) > 6: p[0] = AST.ChoiceElseInstruction(p[3], p[5], p[7]) else: p[0] = AST.ChoiceInstruction(p[3], p[5]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstruction(p[3], p[5]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstruction(AST.Instructions(p[2]), p[4]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstruction(p[2]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstruction() p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstruction() p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstructions(AST.Declarations.mapTypedDeclarations(p[2]), AST.Instructions(utils.flatten(p[3]))) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" p[0] = p[1] def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: p[0] = p[1] return if p[1] == '(': p[0] = AST.GroupingOperator(p[2]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) return if p[2] == '(': p[0] = AST.FunctionCallOperator(p[1], p[3]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) return if p[2] == "+": p[0] = AST.SumOperator(p[1], p[3]) if p[2] == "-": p[0] = AST.DifferenceOperator(p[1], p[3]) if p[2] == "*": p[0] = AST.MultiplyOperator(p[1], p[3]) if p[2] == "/": p[0] = AST.DivOperator(p[1], p[3]) if p[2] == "%": p[0] = AST.ModuloOperator(p[1], p[3]) if p[2] == "^": p[0] = AST.BitXorOperator(p[1], p[3]) if p[2] == "&": p[0] = AST.BitAndOperator(p[1], p[3]) if p[2] == "|": p[0] = AST.BitOrOperator(p[1], p[3]) if p[2] == "<<": p[0] = AST.ShiftLeftOperator(p[1], p[3]) if p[2] == ">>": p[0] = AST.ShiftRightOperator(p[1], p[3]) if p[2] == "||": p[0] = AST.LogicalOrOperator(p[1], p[3]) if p[2] == "&&": p[0] = AST.LogicalAndOperator(p[1], p[3]) if p[2] == "==": p[0] = AST.EqualOperator(p[1], p[3]) if p[2] == "!=": p[0] = AST.NotEqualOperator(p[1], p[3]) if p[2] == ">": p[0] = AST.GreaterThanOperator(p[1], p[3]) if p[2] == ">=": p[0] = AST.GreaterEqualOperator(p[1], p[3]) if p[2] == "<": p[0] = AST.LowerThanOperator(p[1], p[3]) if p[2] == "<=": p[0] = AST.LowerEqualOperator(p[1], p[3]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) > 1: p[0] = utils.flatten(p[1]) else: p[0] = [] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) > 2: p[0] = [p[1], p[3]] else: p[0] = [p[1]] def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) > 1: p[0] = [p[1], p[2]] else: p[0] = [] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunDef(p[1], p[2], p[4], p[6]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) > 1: p[0] = utils.flatten(p[1]) else: p[0] = [] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) > 2: p[0] = [p[1], p[3]] else: p[0] = [p[1]] def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p[1], p[2]) p[0].set_position(p.lexer.lexer.lineno, p.lexer.lexer.lexpos)
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input\nMost likely you haven\'t included a single instruction') def p_program(self, p): """program : declarations fundefs instructions""" p[0] = AST.AST(p[1], p[2], p[3]) def p_declarations(self, p): """declarations : declarations declaration | """ try: p[0] = p[1] + [p[2]] except IndexError: p[0] = [] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ try: p[3] p[0] = AST.Declaration(p[1], p[2]) except IndexError: p[0] = AST.Error(p[1]) def p_inits(self, p): """inits : inits ',' init | init """ try: p[0] = p[1] + [p[3]] except IndexError: p[0] = [p[1]] def p_init(self, p): """init : ID '=' expression """ p[0] = self.add_pos(AST.Init(self.add_pos(AST.Variable(p[1]), p), p[3]), p) def p_instructions(self, p): """instructions : instructions instruction | instruction """ try: p[0] = p[1] + [p[2]] except IndexError: p[0] = [p[1]] def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.Print(p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstr(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(self.add_pos(AST.Variable(p[1]), p), p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ try: p[0] = AST.If(p[3], p[5], p[7]) except IndexError: p[0] = AST.If(p[3], p[5], None) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.While(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instruction UNTIL condition ';' """ p[0] = AST.Repeat(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = self.add_pos(AST.Return(p[2]), p) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = self.add_pos(AST.Continue(), p) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = self.add_pos(AST.Break(), p) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstruction(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const_int(self, p): """const : INTEGER""" p[0] = self.add_pos(AST.Integer(p[1]), p) def p_const_float(self, p): """const : FLOAT""" p[0] = self.add_pos(AST.Float(p[1]), p) def p_const_string(self, p): """const : STRING""" p[0] = self.add_pos(AST.String(p[1]), p) def p_expression_simple(self, p): """expression : const | '(' expression ')' """ try: p[0] = p[2] except IndexError: p[0] = p[1] def p_expression_id(self, p): """expression : ID """ p[0] = self.add_pos(AST.Variable(p[1]), p) def p_expression_binexpr(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression """ p[0] = self.add_pos(AST.BinExpr(p[1], p[2], p[3]), p) def p_expression_funcall(self, p): """expression : ID '(' expr_list_or_empty ')' """ p[0] = self.add_pos(AST.Funcall(self.add_pos(AST.Variable(p[1]), p), p[3]), p) def p_expression_error(self, p): """expression : '(' error ')' | ID '(' error ')' """ pos = self.get_pos(p, 1) try: p[4] p[0] = AST.Error("Malformed function call {0}({1}) at line:{2} column:{3}".format(p[1], p[3], pos[0], pos[1])) except IndexError: p[0] = AST.Error("Malformed braced expression ({0}) at line:{1} column:{2}".format(p[2], pos[0], pos[1])) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ try: p[0] = p[1] except IndexError: p[0] = [] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ try: p[0] = p[1] + [p[3]] except IndexError: p[0] = [p[1]] def p_fundefs(self, p): """fundefs : fundef fundefs | """ try: p[0] = [p[1]] + p[2] except IndexError: p[0] = [] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = self.add_pos(AST.Fundef(p[2], p[1], p[4], p[6]), p) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ try: p[0] = p[1] except IndexError: p[0] = [] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ try: p[0] = p[1] + [p[3]] except IndexError: p[0] = [p[1]] def p_arg(self, p): """arg : TYPE ID """ p[0] = self.add_pos(AST.Arg(p[1], p[2]), p) def add_pos(self, el, p, i = 1): el.pos = self.get_pos(p, i) return el def get_pos(self, p, i = 1): def find_column(input,token): last_cr = input.rfind('\n',0,token) if last_cr < 0: last_cr = 0 column = (token - last_cr) return column try: out = p[i].pos except AttributeError: out = (p.lineno(i), find_column(self.scanner.lexer.lexdata, p.lexpos(i))) # print("{}:{} -> {}:{}".format(p.slice, i, out[0], out[1])) return out
# object oriented version import sys from scanner import Scanner # Scanner needs to be provided manually if __name__ == '__main__': try: filename = sys.argv[1] if len(sys.argv) > 1 else "example.txt" file = open(filename, "r") except IOError: print(f"Cannot open {filename} file") sys.exit(0) text = file.read() lexer = Scanner() lexer.build() # Give the lexer some input lexer.input(text) # Tokenize while True: tok = lexer.token() if not tok: break # No more input line_number, token_type, token_value = tok.lineno, tok.type, tok.value print(f"({line_number}): {token_type}({token_value})")
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" p[0] = AST.Program(p.lineno(1), p[1], p[2], p[3]) print(p[0]) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: p[0] = AST.Declarations(p.lineno(1), p[1], p[2]) else: p[0] = AST.Epsilon(p.lineno(0)) def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: p[0] = AST.Declaration(p.lineno(1), p[2], p[1]) else: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) sys.exit(-1) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 2: p[0] = AST.Inits(p.lineno(1), p[1]) else: p[0] = AST.Inits(p.lineno(1), p[1], p[3]) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p.lineno(1), p[1], p[3]) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[0] = AST.Instructions(p.lineno(1), p[1], p[2]) else: p[0] = AST.Instructions(p.lineno(1), p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ if isinstance(p[2], AST.Expr): p[0] = AST.PrintInstr(p.lineno(1), p[2]) else: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) sys.exit(-1) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstr(p.lineno(1), p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p.lineno(1), p[1], p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 6: if isinstance(p[3], AST.Condition): p[0] = AST.IfInstr(p.lineno(1), p[3], p[5]) else: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) sys.exit(-1) else: if isinstance(p[3], AST.Condition): p[0] = AST.IfElseInstr(p.lineno(1), p[3], p[5], p[7]) else: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) sys.exit(-1) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ if isinstance(p[3], AST.Condition): p[0] = AST.WhileInstr(p.lineno(1), p[3], p[5]) else: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) sys.exit(-1) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p.lineno(1), p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstr(p.lineno(1), p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr(p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr(p.lineno(1)) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstr(p.lineno(1), p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = AST.Condition(p.lineno(1), p[1]) def p_const(self, p): """const : INTEGER | FLOAT | STRING""" if (p[1].isdigit()): if "." in p[1]: p[0] = AST.Float(p.lineno(1), p[1]) else: p[0] = AST.Integer(p.lineno(1), p[1]) else: p[0] = AST.String(p.lineno(1), p[1]) def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: p[0] = AST.UnExpr(p.lineno(1), p[1]) elif len(p) == 4: if p[1] == '(': if isinstance(p[2], AST.Expr): p[0] = AST.BrackExpr(p.lineno(1), p[2]) else: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) sys.exit(-1) else: p[0] = AST.BinExpr(p.lineno(1), p[2], p[1], p[3]) else: if isinstance(p[3], AST.ExprList) or isinstance(p[3], AST.Epsilon): p[0] = AST.FunCall(p.lineno(1), p[1], p[3]) else: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) sys.exit(-1) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.Epsilon(p.lineno(0)) def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = AST.ExprList(p.lineno(1), p[1], p[3]) else: p[0] = AST.ExprList(p.lineno(1), p[1]) def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) == 3: p[0] = AST.FunDefs(p.lineno(1), p[1], p[2]) else: p[0] = AST.Epsilon(p.lineno(0)) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunDef(p.lineno(1), p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.Epsilon(p.lineno(0)) def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = AST.ArgsList(p.lineno(1), p[1], p[3]) else: p[0] = AST.ArgsList(p.lineno(1), p[1]) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p.lineno(1), p[2], p[1])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() self.symbol_table = SymbolTable.SymbolTable("main_table") tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) operation_results = { #~ ARITHMETIC OPERATORS ---------------------- "+": { "int": { "int": "int", "float": "float", "string": None, "bool": None }, "float": { "int": "float", "float": "float", "string": None, "bool": None }, "string": { "int": None, "float": None, "string": "string", "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } }, "-": { "int": { "int": "int", "float": "float", "string": None, "bool": None }, "float": { "int": "float", "float": "float", "string": None, "bool": None }, "string": { "int": None, "float": None, "string": None, "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } }, "*": { "int": { "int": "int", "float": "int", "string": None, "bool": None }, "float": { "int": "float", "float": "float", "string": None, "bool": None }, "string": { "int": "string", "float": None, "string": None, "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } }, "/": { "int": { "int": "int", "float": "float", "string": None, "bool": None }, "float": { "int": "float", "float": "float", "string": None, "bool": None }, "string": { "int": None, "float": None, "string": None, "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } }, "%": { "int": { "int": "int", "float": None, "string": None, "bool": None }, "float": { "int": None, "float": None, "string": None, "bool": None }, "string": { "int": None, "float": None, "string": None, "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } }, #~ COMPARISON OPERATORS ---------------------- "<": { "int": { "int": "bool", "float": "bool", "string": None, "bool": None }, "float": { "int": "bool", "float": "bool", "string": None, "bool": None }, "string": { "int": None, "float": None, "string": "bool", "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } }, "<=": { "int": { "int": "bool", "float": "bool", "string": None, "bool": None }, "float": { "int": "bool", "float": "bool", "string": None, "bool": None }, "string": { "int": None, "float": None, "string": "bool", "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } }, ">=": { "int": { "int": "bool", "float": "bool", "string": None, "bool": None }, "float": { "int": "bool", "float": "bool", "string": None, "bool": None }, "string": { "int": None, "float": None, "string": "bool", "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } }, ">": { "int": { "int": "bool", "float": "bool", "string": None, "bool": None }, "float": { "int": "bool", "float": "bool", "string": None, "bool": None }, "string": { "int": None, "float": None, "string": "bool", "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } }, "==": { "int": { "int": "bool", "float": "bool", "string": None, "bool": None }, "float": { "int": "bool", "float": "bool", "string": None, "bool": None }, "string": { "int": None, "float": None, "string": "bool", "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": "bool" } }, "!=": { "int": { "int": "bool", "float": "bool", "string": None, "bool": None }, "float": { "int": "bool", "float": "bool", "string": None, "bool": None }, "string": { "int": None, "float": None, "string": "bool", "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": "bool" } }, #~ LOGICAL OPERATORS ---------------------- "&&": { "int": { "int": None, "float": None, "string": None, "bool": None }, "float": { "int": None, "float": None, "string": None, "bool": None }, "string": { "int": None, "float": None, "string": None, "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": "bool" } }, "\|\|": { "int": { "int": None, "float": None, "string": None, "bool": None }, "float": { "int": None, "float": None, "string": None, "bool": None }, "string": { "int": None, "float": None, "string": None, "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": "bool" } }, #~ BITWISE OPERATORS ---------------------- ">>": { "int": { "int": "int", "float": None, "string": None, "bool": None }, "float": { "int": None, "float": None, "string": None, "bool": None }, "string": { "int": None, "float": None, "string": None, "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } }, "<<": { "int": { "int": "int", "float": None, "string": None, "bool": None }, "float": { "int": None, "float": None, "string": None, "bool": None }, "string": { "int": None, "float": None, "string": None, "bool": None }, "bool": { "int": None, "float": None, "string": None, "bool": None } } } def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : blocks""" program = AST.Program(p[1]) p[0] = program def p_blocks(self, p): """blocks : blocks block | block""" if(len(p) > 2): if(isinstance(p[2], list)): p[1].extend(p[2]) else: p[1].append(p[2]) p[0] = p[1] else: if(isinstance(p[1], list)): p[0] = p[1] else: p[0] = [p[1]] def p_block(self, p): """block : declaration | fundef | instruction""" p[0] = p[1] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if(len(p) > 2): p[0] = p[2] declared_type = p[1] #~ print("Adding new variable declarations...") #~ for i in range(len(p[0])): #~ declaration = p[0][i] #~ id = declaration.left #~ name = id.name #~ #~ if(id.type != declared_type): #~ if(declared_type == "int" and id.type == "float"): #~ print("Line [" + str(p.lineno(1)) + "]: Warning! Implicit cast from float to int!") #~ elif(declared_type != "float" or id.type != "int"): #~ print("Line [" + str(p.lineno(1)) + "]: Invalid declaration type!") #~ #~ if(not self.symbol_table.put(name, SymbolTable.VariableSymbol(declared_type, name))): #~ print("Line [" + str(p.lineno(1)) + "]: Multiple variable declarations in the same scope!") else: p[0] = p[1] def p_inits(self, p): """inits : inits ',' init | init """ if(len(p) > 3): p[1].append(p[3]) p[0] = p[1] else: p[0] = [p[1]] def p_init(self, p): """init : ID '=' expression """ decl = AST.Declaration(AST.Id(p[3].type, p[1], p.lineno(1)), p[3], p.lineno(1)) p[0] = decl def p_instructions(self, p): """instructions : instructions instruction | instruction """ if(len(p) > 2): if(isinstance(p[2], list)): p[1].extend(p[2]) else: p[1].append(p[2]) p[0] = p[1] else: if(isinstance(p[1], list)): p[0] = p[1] else: p[0] = [p[1]] def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ instruction = AST.PrintInstr(p[2], p.lineno(1)) p[0] = instruction def p_return_instr(self, p): """return_instr : RETURN expression ';' """ instruction = AST.ReturnInstr(p[2], p.lineno(1)) p[0] = instruction def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if(len(p) > 7): instruction = AST.IfInstr(p[3], p[5], p.lineno(1), p[7]) p[0] = instruction elif(len(p) > 5): instruction = AST.IfInstr(p[3], p[5], p.lineno(1)) p[0] = instruction def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ instruction = AST.WhileInstr(p[3], p[5], p.lineno(1)) p[0] = instruction def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ instruction = AST.RepeatUntilInstr(p[4], p[2], p.lineno(1)) p[0] = instruction def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ instruction = AST.ContinueInstr("CONTINUE", p.lineno(1)) p[0] = instruction def p_break_instr(self, p): """break_instr : BREAK ';' """ instruction = AST.BreakInstr("BREAK", p.lineno(1)) p[0] = instruction def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = p[3] def p_assignment(self, p): """assignment : ID '=' expression ';' """ declared_var = self.symbol_table.get(p[1]) actual_type = p[3].type #~ if(declared_var is not None): #~ declared_type = declared_var.type #~ else: #~ declared_type = "__UNKNOWN__" #~ #~ if(declared_type != actual_type): #~ if(declared_type == "int" and actual_type == "float"): #~ print("Line [" + str(p.lineno(1)) + "]: Warning! Implicit type convertion (float -> int)!") #~ elif(declared_type != "float" or actual_type != "int"): #~ if(declared_type == "__UNKNOWN__"): #~ print("Line [" + str(p.lineno(1)) + "]: Variable has not been declared!") #~ else: #~ print("Line [" + str(p.lineno(1)) + "]: Assignment type mismatch!") #~ expr = AST.AssignInstr(actual_type, AST.Id(actual_type, p[1], p.lineno(1)), p[3], p.lineno(1)) p[0] = expr def p_compound_instr(self, p): """compound_instr : '{' blocks '}' """ p[0] = p[2] def p_condition(self, p): """condition : expression""" if(p[1].type != "bool"): print("Line [" + str(p.lineno(p[1]) + "]: Condition should be of type BOOL!")) condition = AST.Condition(p[1], p.lineno(1)) p[0] = condition def p_bin_expression(self, p): """bin_expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression """ left_expr = p[1] op = p[2] right_expr = p[3] result_type = self.operation_results[op][left_expr.type][right_expr.type] expr = AST.BinExpr(result_type, op, left_expr, right_expr, p.lineno(1)) #~ result_type = self.operation_results[op][left_expr.type][right_expr.type] #~ #~ if(result_type is not None): #~ expr = AST.BinExpr(result_type, op, left_expr, right_expr, p.lineno(1)) #~ else: #~ expr = AST.BinExpr("__UNKNOWN__", op, left_expr, right_expr, p.lineno(1)) #~ print("Line [" + str(p.lineno(2)) + "]: Invalid binary expression!") #~ p[0] = expr def p_const_int(self, p): """const : INTEGER """ const = AST.Const("int", p[1], p.lineno(1)) p[0] = const def p_const_float(self, p): """const : FLOAT """ const = AST.Const("float", p[1], p.lineno(1)) p[0] = const def p_const_string(self, p): """const : STRING """ const = AST.Const("string", p[1], p.lineno(1)) p[0] = const def p_id(self, p): """id : ID""" identifier = AST.Id("?", p[1], p.lineno(1)) p[0] = identifier def p_expression(self, p): """expression : id | const | bin_expression | paren_expression | funcall""" p[0] = p[1] def p_paren_expression(self, p): """paren_expression : '(' expression ')' | '(' error ')' """ p[0] = p[2] def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if(len(p) > 1): p[0] = p[1] else: p[0] = [] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if(len(p) > 3): p[1].append(p[3]) p[0] = p[1] else: p[0] = [p[1]] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ return_type = p[1] fun_name = p[2] fun_id = AST.Id(p[1], p[2], p.lineno(1)) args = p[4] fundef = AST.FunDefinition(return_type, fun_id, args, p.lineno(1), p[6]) p[0] = fundef def p_funcall(self, p): """funcall : ID '(' expr_list_or_empty ')' | ID '(' error ')' """ funcall = AST.FunCall(AST.Id("?", p[1], p.lineno(1)), p[3], p.lineno(1)) p[0] = funcall def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if(len(p) > 1): p[0] = p[1] else: p[0] = [] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if(len(p) > 3): p[1].append(p[3]) p[0] = p[1] else: p[0] = [p[1]] def p_arg(self, p): """arg : TYPE ID """ arg = AST.FunArg(p[1], p[2], p.lineno(1)) p[0] = arg
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() self.errorsOccured = False tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') self.errorsOccured = True def p_program(self, p): """program : classdefs declarations fundefs instructions""" p[0] = AST.Program(p[1], p[2], p[3], p[4]) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) > 1: p[1].list.append(p[2]) p[0] = p[1] else: p[0] = AST.Declarations() def p_declaration(self, p): """declaration : TYPE inits ';' | id classinits ';' | error ';' """ if len(p) > 2: p[0] = AST.Declaration(p[1], p[2]) else: p[0] = p[1] def p_inits(self, p): """inits : inits ',' init | init """ if len(p) > 2: p[1].list.append(p[3]) p[0] = p[1] else: inits = AST.Inits() inits.list.append(p[1]) p[0] = inits def p_init(self, p): """init : id '=' expression """ p[0] = AST.Init(p[1], p[3]) def p_classinits(self, p): """classinits : classinits ',' classinit | classinit """ if len(p) > 2: p[1].list.append(p[3]) p[0] = p[1] else: classinits = AST.Classinits() classinits.list.append(p[1]) p[0] = classinits def p_classinit(self, p): """classinit : id """ p[0] = AST.Classinit(p[1]) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 2: instructions = AST.Instructions() instructions.list.append(p[1]) p[0] = instructions else: p[1].list.append(p[2]) p[0] = p[1] def p_instruction(self, p): """instruction : expression ';' | print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.PrintInstr(p[2]) def p_labeled_instr(self, p): """labeled_instr : id ':' instruction """ p[0] = AST.LabeledInstr(p[1], p[3]) def p_assignment(self, p): """assignment : access '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3]) def p_access(self, p): """access : id | id '.' id """ if len(p) == 2: access = AST.Access(p.lineno(1)) access.list.append(p[1]) p[0] = access else: access = AST.Access(p.lineno(1)) access.list.append(p[1]) access.list.append(p[3]) p[0] = access def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 6: p[0] = AST.ChoiceInstr(p[3], p[5], None) else: p[0] = AST.ChoiceInstr(p[3], p[5], p[7]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstr(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.Continue() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.Break() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}'""" p[0] = AST.CompoundInstr(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = AST.Condition(p[1]) def p_const(self, p): """const : integer | float | string""" p[0] = p[1] def p_integer(self, p): """integer : INTEGER""" p[0] = AST.Integer(p[1], p.lineno(1)) def p_float(self, p): """float : FLOAT""" p[0] = AST.Float(p[1], p.lineno(1)) def p_string(self, p): """string : STRING""" p[0] = AST.String(p[1][1:-1], p.lineno(1)) def p_id(self, p): """id : ID""" p[0] = AST.Id(p[1], p.lineno(1)) def p_expression(self, p): """expression : const | access | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | access '(' expr_list_or_empty ')' | access '(' error ')' """ if len(p) == 2: p[0] = p[1] elif p[1] == '(': p[0] = AST.ParExpr(p[2]) elif len(p) == 4: p[0] = AST.BinExpr(p[1], p[2], p[3]) else: p[0] = AST.FunExpr(p[1], p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 1: p[0] = AST.ExprList() else: p[0] = p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[1].list.append(p[3]) p[0] = p[1] else: toReturn = AST.ExprList() toReturn.list.append(p[1]) p[0] = toReturn def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) == 3: p[2].list.reverse() p[2].list.append(p[1]) p[2].list.reverse() p[0] = p[2] else: p[0] = AST.FunDefs() def p_fundef(self, p): """fundef : TYPE id '(' args_list_or_empty ')' compound_instr | id id '(' args_list_or_empty ')' compound_instr""" p[0] = AST.FunDef(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 1: p[0] = AST.ArgList() else: p[0] = p[1] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 2: argList = AST.ArgList() argList.list.append(p[1]) p[0] = argList else: p[1].list.append(p[3]) p[0] = p[1] def p_arg(self, p): """arg : TYPE id | id id""" p[0] = AST.Arg(p[1], p[2]) def p_classdefs(self, p): """classdefs : classdef classdefs | """ if len(p) == 3: p[2].list.reverse() p[2].list.append(p[1]) p[2].list.reverse() p[0] = p[2] else: p[0] = AST.ClassDefs() def p_classdef(self, p): """classdef : accessmodificator CLASS id classcontent | accessmodificator CLASS id EXTENDS id classcontent""" if len(p) < 7: p[0] = AST.ClassDef(p[1], p[3], None, p[4]) else: p[0] = AST.ClassDef(p[1], p[3], p[5], p[6]) def p_classcontent(self, p): """classcontent : '{' fielddefs ';' methoddefs '}' """ p[0] = AST.Classcontent(p[2], p[4]) def p_fielddefs(self, p): """fielddefs : fielddef fielddefs | """ if len(p) == 3: p[2].list.reverse() p[2].list.append(p[1]) p[2].list.reverse() p[0] = p[2] else: p[0] = AST.Fielddefs() def p_fielddef(self, p): """fielddef : accessmodificator declaration """ p[0] = AST.Fielddef(p[1], p[2]) def p_methoddefs(self, p): """methoddefs : methoddef methoddefs | """ if len(p) == 3: p[2].list.reverse() p[2].list.append(p[1]) p[2].list.reverse() p[0] = p[2] else: p[0] = AST.Methoddefs() def p_methoddef(self, p): """methoddef : accessmodificator fundef""" p[0] = AST.Methoddef(p[1], p[2]) def p_accessmodificator(self, p): """accessmodificator : PRIVATE | PROTECTED | PUBLIC""" p[0] = p[1]
class Mparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() self.args = {} self.const = {} tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("nonassoc", 'LT', 'GT', 'EQ', 'NE', 'LE', 'GE'), ("left", '+', '-'), ("left", '*', '/'), ("left", 'DOTADD', 'DOTSUB'), ("left", 'DOTMUL', 'DOTDIV'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : instructions""" p[0] = AST.Program(p[1]) print(p[0]) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[1].instrs.append(p[2]) p[0] = p[1] else: p[0] = AST.Instructions(p[1]) def p_instruction(self, p): """instruction : print_instr | assignment | choice_instr | while_instr | for_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ p[0] = AST.Print(p[2]) def p_assignment(self, p): """assignment : id assign_operator expression ';' | ref assign_operator expression ';' """ p[0] = AST.Assignment(p[1], p[2], p[3]) def p_ref(self, p): """ref : id '[' expr_list ']' """ p[0] = AST.Ref(p[1], p[3]) def p_assign_operator(self, p): """assign_operator : '=' | ADDASSIGN | SUBASSIGN | MULASSIGN | DIVASSIGN""" p[0] = AST.Assign_operator(p[1]) def p_vector(self, p): """vector : '[' expressions ']' """ p[0] = AST.Vector(p[2]) def p_expressions_or_vectors(self, p): """expressions : expression | expressions ',' expression """ if len(p) == 4: p[1].exprs.append(p[3]) p[0] = p[1] else: p[0] = AST.Expressions(p[1]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 6: p[0] = AST.Choice(p[3], p[5]) else: p[0] = AST.Choice(p[3], p[5], p[7]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.While(p[3], p[5]) def p_for_instr(self, p): """for_instr : FOR id '=' range instruction""" p[0] = AST.For(p[2], p[4], p[5]) def p_range(self, p): """range : expression ':' expression""" p[0] = AST.Range(p[1], p[3]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.Return(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.Continue() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.Break() def p_compound_instr(self, p): """compound_instr : '{' instructions '}' """ p[0] = AST.ComInstructions(p[2]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTNUM | FLOATNUM | STRING""" p[0] = AST.Const(p[1]) def p_expression(self, p): """expression : const | id | ref | vector | matrix_operation | matrix_function | minus_matrix | matrix_transposed | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression EQ expression | expression NE expression | expression LT expression | expression GT expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')'""" if len(p) == 2: p[0] = p[1] elif len(p) == 4: if p[1] == '(': p[0] = p[2] else: if p[2] in ['+', '-', '*', '/']: p[0] = AST.BinExpr(p[1], p[2], p[3]) else: p[0] = AST.Condition(p[1], p[2], p[3]) def p_id(self, p): """id : ID""" p[0] = AST.Variable(p[1], 0) def p_matrix_operation(self, p): """matrix_operation : matrix dot_operation matrix""" p[0] = AST.Matrix_operation(p[1], p[2], p[3]) def p_dot_operation(self, p): """dot_operation : DOTADD | DOTSUB | DOTMUL | DOTDIV""" p[0] = AST.Dot_operation(p[1]) def p_matrix(self, p): """matrix : id | minus_matrix | matrix_transposed""" p[0] = AST.Matrix(p[1]) def p_matrix_transposed(self, p): """matrix_transposed : matrix "'" """ p[0] = AST.Matrix_transposed(p[1]) def p_minus_matrix(self, p): """minus_matrix : "-" matrix """ p[0] = AST.Minus_matrix(p[2]) def p_matrix_function(self, p): """matrix_function : ZEROS '(' expressions ')' | ONES '(' expressions ')' | EYE '(' expressions ')' """ p[0] = AST.Matrix_function(p[1], p[3]) def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[1].exprs.append(p[3]) p[0] = p[1] else: p[0] = AST.Expressions(p[1])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : blocks""" p[0] = AST.Program(p[1]) TreePrinter() print p[0] def p_blocks(self, p): """blocks : blocks block | """ if len(p) == 3: p[0] = p[1] + [p[2]] else: p[0] = [] def p_block(self, p): """block : declaration | instruction | fundef""" p[0] = AST.Block(p[1]) def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) > 3: p[0] = AST.Declaration(p[2]) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[0] = p[1] + [p[3]] else: p[0] = [p[1]] def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Variable(p[1], p[3]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ if len(p) == 2: p[0] = p[1] else: p[0] = [p[1]] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ p[0] = [AST.Instruction(p[1], p[2])] def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = [AST.Instruction(p[2], [p[1], p[3]])] def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = [AST.Instruction(p[2], [p[1], p[3]])] def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 6: p[0] = [AST.Instruction(p[1], [p[3], p[5]]) ] #Instruction(IF, [condition, instruction]) elif len(p) == 8: p[0] = [ AST.Instruction(p[1], [p[3], p[5]]), AST.Instruction(p[6], [p[7]]) ] #Instruction(IF, [condition, instruction]) #Instruction(ELSE, [instruction]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = [AST.Instruction(p[1], [p[3], p[5]])] def p_repeat_instr(self, p): """repeat_instr : REPEAT instruction UNTIL condition ';' """ p[0] = [AST.Instruction(p[1], [p[2]]), AST.Instruction(p[3], [p[4]])] def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = [AST.Instruction(p[1], [p[2]])] def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = [AST.Instruction(p[1], [])] def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = [AST.Instruction(p[1], [])] def p_compound_instr(self, p): """compound_instr : '{' comp_instr_blocks '}' """ p[0] = p[2] def p_comp_instr_blocks(self, p): """comp_instr_blocks : comp_instr_blocks comp_instr_block | """ if len(p) == 3: p[0] = p[1] + [p[2]] else: p[0] = [] def p_comp_instr_block(self, p): """comp_instr_block : declaration | instruction""" p[0] = AST.Block(p[1]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" if type(p[1]) == int: p[0] = AST.Const(AST.Integer(p[1])) elif type(p[1]) == float: p[0] = AST.Const(AST.Float(p[1])) elif type(p[1]) == str: p[0] = AST.Const(AST.String(p[1])) def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: p[0] = p[1] elif len(p) == 4: if (p[1] == '('): p[0] = p[2] else: p[0] = AST.BinExpr(p[2], p[1], p[3]) elif len(p) == 5: p[0] = AST.Instruction('FUNCALL', [p[1], p[3]]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = [] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = p[1] + [p[3]] else: p[0] = [p[1]] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.Fundef(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = [] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = p[1] + [p[3]] else: p[0] = [p[1]] def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p[1], p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def handle_error(self, where, p): print("Syntax error in %s at line %d, column %d, at token LexToken(%s, '%s')" %\ (where, p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) def p_error(self, p): if not p: print 'Unexpected end of input' else: # let the productions handle the error on their own pass def p_program(self, p): """program : ext_declarations fundefs instructions""" p[0] = Program(p[1], p[2], p[3], pos(p)) p[0].printTree(0) def p_ext_declarations(self, p): """ext_declarations : declarations""" p[0] = p[1] def p_declarations(self, p): """declarations : declarations declaration""" if p[2]: p[0] = DeclarationList(p[1].decls + [p[2]]) else: # error p[0] = p[1] def p_declarations_single(self, p): """declarations : declaration""" if p[1]: p[0] = DeclarationList([p[1]]) else: # error p[0] = DeclarationList([]) def p_declaration_blank(self, p): """declarations : """ p[0] = DeclarationList([]) def p_declaration_fundef(self, p): """declaration : fundefs""" p[0] = p[1] def p_declaration(self, p): """declaration : TYPE inits ';' """ p[0] = Declaration(p[1], p[2], pos(p)) def p_declaration_error(self, p): """declaration : error ';' """ self.handle_error('declaration', p[1]) def p_inits(self, p): """inits : inits ',' init""" p[0] = InitList(p[1].inits + [p[3]]) def p_inits_single(self, p): """inits : init""" p[0] = InitList([p[1]]) def p_init(self, p): """init : ID '=' expression """ p[0] = Init(p[1], p[3]) def p_instructions(self, p): """instructions : instructions instruction""" if p[2]: p[0] = InstructionList(p[1].instrs + [p[2]]) else: p[0] = p[1] def p_instructions_single(self, p): """instructions : instruction """ if p[1]: p[0] = InstructionList([p[1]]) else: p[0] = InstructionList([]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' """ p[0] = PrintInstruction(p[2]) def p_print_error(self, p): """print_instr : PRINT error ';' """ self.handle_error('print instruction', p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = LabeledInstruction(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ if p[3]: p[0] = Assignment(p[1], p[3], pos(p)) else: # error pass def p_assignment_error(self, p): """assignment : ID '=' error ';' """ self.handle_error('assignment', p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX""" p[0] = ChoiceInstruction(p[3], p[5]) def p_choice_instr_else(self, p): """choice_instr : IF '(' condition ')' instruction ELSE instruction""" p[0] = ChoiceInstruction(p[3], p[5], p[7]) def p_choice_instr_error(self, p): """choice_instr : IF '(' error ')' instruction %prec IFX""" self.handle_error('if condition', p[3]) def p_choice_instr_else_error(self, p): """choice_instr : IF '(' error ')' instruction ELSE instruction""" self.handle_error('if condition', p[3]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction""" p[0] = WhileInstruction(p[1], p[3], p[5]) def p_while_error(self, p): """while_instr : WHILE '(' error ')' instruction """ self.handle_error('while instruction', p[3]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = RepeatInstruction(p[1], p[2], p[3], p[4]) def p_repeat_error(self, p): """repeat_instr : REPEAT instructions UNTIL error ';' """ self.handle_error('repeat instruction', p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = ReturnInstruction(p[2], pos(p)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = ContinueInstruction() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = BreakInstruction() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = CompoundInstructions(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const_integer(self, p): """const : INTEGER""" p[0] = Integer(p[1]) def p_const_float(self, p): """const : FLOAT""" p[0] = Float(p[1]) def p_const_string(self, p): """const : STRING""" p[0] = String(p[1]) def p_expression_const(self, p): """expression : const""" p[0] = p[1] def p_expression_id(self, p): "expression : ID" p[0] = Variable(p[1], pos(p)) def p_expression_brackets(self, p): "expression : '(' expression ')'" p[0] = p[2] def p_expression_brackets_error(self, p): "expression : '(' error ')'" self.handle_error("expression (bracket)", p[2]) def p_expression_fun_call(self, p): "expression : ID '(' expr_list_or_empty ')'" p[0] = FunctionCall(p[1], p[3], pos(p)) def p_expression_fun_call_error(self, p): "expression : ID '(' error ')'" self.handle_error('function call', p[3]) def p_expression_binary_op(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression""" p[0] = BinExpr(p[1], p[2], p[3], pos(p)) def p_expr_list_non_empty(self, p): """expr_list_or_empty : expr_list""" p[0] = p[1] def p_expr_list_empty(self, p): """expr_list_or_empty : """ p[0] = ExprList([]) def p_expr_list(self, p): """expr_list : expr_list ',' expression""" p[0] = ExprList(p[1].exprs + [p[3]]) def p_expr_list_single(self, p): """expr_list : expression""" p[0] = ExprList([p[1]]) # def p_fundefs(self, p): # """fundefs : fundefs fundef # | fundef """ # if p[2]: # p[0] = FunctionDefList(p[1].fundefs + [ p[2] ]) # else: # p[0] = FunctionDefList([ p[1] ]) def p_fundefs(self, p): """fundefs : fundefs fundef""" p[0] = FunctionDefList(p[1].fundefs + [p[2]]) def p_fundefs_single(self, p): """fundefs : fundef""" p[0] = FunctionDefList([p[1]]) def p_fundefs_empty(self, p): """fundefs : """ p[0] = FunctionDefList([]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = FunctionDef(p[1], p[2], p[4], p[6], pos(p)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if p[1]: p[0] = p[1] else: p[0] = ArgsList([]) # def p_args_list(self, p): # """args_list : args_list ',' arg # | arg """ # if p[3]: # p[0] = ArgsList(p[1].args + [ p[3] ]) # else: # p[0] = ArgsList([ p[1] ]) def p_args_list(self, p): """args_list : args_list ',' arg""" p[0] = ArgsList(p[1].args + [p[3]]) def p_args_list_single(self, p): """args_list : arg""" p[0] = ArgsList([p[1]]) def p_arg(self, p): """arg : TYPE ID """ p[0] = Arg(p[1], p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() self.error = False tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: self.error = True print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) while 1: tok = yacc.token() if not tok or tok.type == 'RBRACE': break yacc.restart() else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" p[0] = AST.Program(p[1], p[2], p[3], p.lineno(1)) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) > 2: p[0] = p[1] p[1].append(p[2]) else: p[0] = [] def p_declaration(self, p): """declaration : TYPE inits ';'""" if len(p) > 3: p[0] = AST.Variable(p[1], p[2], p.lineno(1)) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) > 2: p[0] = p[1] p[1].append(p[3]) else: p[0] = [p[1]] def p_init(self, p): """init : ID '=' expression | ID """ if len(p) > 3: p[0] = AST.Declaration(p[1], p[2], p[3], p.lineno(1)) else: p[0] = AST.Declaration(p[1], None, None, p.lineno(1)) def p_instructions(self, p): """instructions : instructions instruction | instruction | """ if len(p) > 2: p[0] = p[1] p[1].append(p[2]) elif len(p) == 2: p[0] = [p[1]] else: p[0] = [] def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | funcall""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.Print(p[2], p.lineno(1)) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.Label(p[1], p[3], p.lineno(1)) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[2], p[3], p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) > 6: p[0] = AST.ChoiceInstructionWithElse(p[3], p[5], p[7], p.lineno(1)) else: p[0] = AST.ChoiceInstruction(p[3], p[5], p.lineno(1)) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileLoop(p[3], p[5], p.lineno(1)) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatUntilLoop(p[2], p[4], p.lineno(1)) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.Return(p[2], p.lineno(1)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.Continue(p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.Break(p.lineno(1)) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstruction(p[2], p[3], p.lineno(1)) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const_int(self, p): """const : INTEGER""" p[0] = AST.Integer(p[1], p.lineno(1)) def p_const_float(self, p): """const : FLOAT""" p[0] = AST.Float(p[1], p.lineno(1)) def p_const_char(self, p): """const : CHAR""" p[0] = AST.Char(p[1], p.lineno(1)) def p_expression(self, p): """expression : const | ID""" p[0] = p[1] def p_expression_function(self, p): """expression : ID '(' expr_list_or_empty ')' | ID '(' error ')' """ p[0] = AST.FunctionCall(p[1], p[3], p.lineno(1)) def p_expression_binop(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression""" p[0] = AST.BinExpr(p[1], p[2], p[3], p.lineno(2)) def p_expression_relop(self, p): """expression : expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression""" p[0] = AST.RelExpr(p[1], p[2], p[3], p.lineno(2)) def p_expression_group(self, p): """expression : '(' expression ')' | '(' error ')'""" p[0] = p[2] def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = [] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) > 2: p[0] = p[1] p[1].append(p[3]) else: p[0] = [p[1]] def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) > 2: p[0] = p[2] p[2].append(p[1]) else: p[0] = [] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunctionDefinition(p[1], p[2], p[4], p[6], p.lineno(1)) def p_funcall(self, p): """funcall : ID '(' expr_list_or_empty ')' ';' | ID '(' error ')' ';'""" p[0] = AST.FunctionCall(p[1], p[3], p.lineno(1)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = [] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) > 2: p[0] = p[1] p[1].append(p[3]) else: p[0] = [p[1]] def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Argument(p[1], p[2], p.lineno(2))
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" p[0] = AST.Main(p.lineno(1), p[1], p[2], p[3]) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) != 1: p[0] = AST.DeclarationsMany(p.lineno(1), p[1], p[2]) else: p[0] = AST.DeclarationsNone(p.lineno(0)) def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) != 3: p[0] = AST.DeclarationMany(p.lineno(1), p[1], p[2]) else: p[0] = AST.DeclarationSingle(p.lineno(1), p[1]) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) != 2: p[0] = AST.InitsMany(p.lineno(1), p[3], p[1]) else: p[0] = AST.InitsSingle(p.lineno(1), p[1]) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p.lineno(1), p[1], p[3]) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) != 2: p[0] = AST.InstructionsMany(p.lineno(1), p[2], p[1]) else: p[0] = AST.InstructionsSingle(p.lineno(1), p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = AST.Instruction(p.lineno(1), p[1]) def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.Print_instr(p.lineno(1), p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.Labeled_instr(p.lineno(1), p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p.lineno(1), p[1], p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) != 8: p[0] = AST.Choice_instr(p.lineno(1), p[3], p[5]) else: p[0] = AST.Choice_instr_with_else(p.lineno(1), p[3], p[5], p[7]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.While_instr(p.lineno(1), p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.Repeat_instr(p.lineno(1), p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.Return_instr(p.lineno(1), p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.Continue_instr() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.Break_instr() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.Compound_instr(p.lineno(1), p[2], p[3]) def p_condition(self, p): """condition : expression""" #p[0] = AST.Condition(p.lineno(1), p[1]) p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" (value, types) = p[1] if types == "int": p[0] = AST.Integer(p.lineno(1), p[1]) elif types == "float": p[0] = AST.Float(p.lineno(1), p[1]) else: p[0] = AST.String(p.lineno(1), p[1]) def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: if isinstance(p[1], str): p[0] = AST.ExpressionSimple(p.lineno(1), p[1]) else: #p[0] = AST.ExpressionSimple(p[1].lineno, p[1]) p[0] = p[1] else: if p[1] == '(' and p[3] == ')': p[0] = AST.ExprInBrackets(p.lineno(1), p[2]) else: if p[2] == '(' and p[4] == ')': p[0] = AST.Funcalls(p.lineno(1), p[1], p[3]) else: p[0] = AST.BinExpr(p.lineno(2), p[1], p[2], p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ p[0] = None if len(p) == 1 else p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = AST.ExpressionList() if p[1] is None else p[1] p[0].addExpression(p[3]) else: p[0] = AST.ExpressionList() p[0].addExpression(p[1]) def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) != 1: p[0] = AST.Fundefs_many(p.lineno(1), p[1], p[2]) else: p[0] = AST.Fundefs(p.lineno(0)) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.Fundef(p.lineno(1), p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ p[0] = None if len(p) == 1 else p[1] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = AST.ArgumentList() if p[1] is None else p[1] p[0].addArgument(p[3]) else: p[0] = AST.ArgumentList() p[0].addArgument(p[1]) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p.lineno(1), p[1], p[2])
def testFile(fname): lex = Scanner() lex.build() readFile(fname, lex.Lexer)
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : toplevel_statements """ p[0] = p[1] def p_toplevel_statements(self, p): """toplevel_statements : toplevel_statements toplevel_statement | """ if len(p) == 3: p[1].toplevel_statements.append(p[2]) p[0] = p[1] return p[0] = AST.ToplevelStatements() def p_toplevel_statement(self, p): """toplevel_statement : declaration | instruction | fundef """ p[0] = p[1] def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: p[1].declarations.append(p[2]) p[0] = p[1] return p[0] = AST.Declarations() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: p[0] = AST.Declaration(p[1], p[2]) else: p[0] = p[1] def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[1].inits.append(p[3]) p[0] = p[1] return p[0] = AST.Inits() p[0].inits.append(p[1]) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3]) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[1].instructions.append(p[2]) p[0] = p[1] return p[0] = AST.Instructions() p[0].instructions.append(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ if len(p) == 4: p[0] = AST.PrintStatement(p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstruction(p[1],p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Init(p[1], p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 8: p[0] = AST.IfStatement(p[3], p[5], p[7]) return p[0] = AST.IfStatement(p[3], p[5]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileLoop(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatLoop(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnValue(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstruction(p[2]) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstruction(p[2], p[4]) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstruction(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" if p[1].isdigit(): if isinstance(num(p[1]), int): p[0] = AST.Integer(num(p[1])) return if isinstance(num(p[1]), float): p[0] = AST.Float(num(p[1])) return p[0] = AST.String(p[1]) def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: if isinstance(p[1], AST.Const): p[0] = AST.Const(p[1]) return id = AST.String(p[1]) p[0] = AST.Const(id) return if isinstance(p[1], AST.Expression) & isinstance(p[3], AST.Expression): p[0] = AST.BinExpr(p[2], p[1], p[3]) return if p[1] == '(': p[0] = p[2] return if p[2] == '(': p[0] = AST.FunCall(p[1], p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] return p[0] = AST.Expressions() def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[1].expression_list.append(p[3]) p[0] = p[1] return p[0] = AST.Expressions() p[0].expression_list.append(p[1]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunDef(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] return p[0] = AST.ArgumentList() def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[1].argument_list.append(p[3]) p[0] = p[1] return p[0] = AST.ArgumentList() p[0].argument_list.append(p[1]) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Argument(p[1], p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IF'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '^'), ("nonassoc", '<', '>', '=', 'NEQ', 'LE', 'GE'), ("left", '+', '-'), ("left", '*', '/', 'MOD', 'DIV'), ) error_encountered = False def convert_from_string(self, value, lineno): try: return Integer(int(value), lineno) except ValueError: try: return Float(float(value), lineno) except ValueError: return String(value, lineno) def p_error(self, p): self.error_encountered = True if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : program_header declarations compound_statement '.'""" p[0] = Program(p[1], p[2], p[3]) def p_program_header(self, p): """program_header : PROGRAM_LITERAL ID ';' | PROGRAM_LITERAL ID '(' id_list ')' ';' """ if len(p) == 4: p[0] = ProgramHeader(p[2]) else: p[0] = ProgramHeader(p[2], p[4]) def p_declarations(self, p): """declarations : constant_definitions type_definitions variable_declarations procedure_declarations""" p[0] = Declarations(p[1], p[2], p[3], p[4]) def p_constant_definitions(self, p): """constant_definitions : CONST constant_definition_list | """ if len(p) == 1: p[0] = list() else: p[0] = p[2] def p_constant_definition_list(self, p): """constant_definition_list : constant_definition_list const_def | const_def """ if len(p) == 2: p[0] = list() p[0].append(p[1]) else: p[1].append(p[2]) p[0] = p[1] def p_const_def(self, p): """const_def : ID '=' CONSTANT ';'""" const_value = self.convert_from_string(p[3], p.lineno(1)) p[0] = ConstDef(const_value, p[1], p.lineno(1)) def p_type_definitions(self, p): """type_definitions : TYPE type_definition_list | """ if len(p) == 1: p[0] = list() else: p[0] = p[2] def p_type_definition_list(self, p): """type_definition_list : type_definition_list type_def | type_def""" if len(p) == 2: p[0] = list() p[0].append(p[1]) else: p[1].append(p[2]) p[0] = p[1] def p_type_def(self, p): """type_def : ID '=' type_specifier ';'""" pass def p_variable_declarations(self, p): """variable_declarations : VAR variable_declaration_list | """ if len(p) == 1: p[0] = list() else: p[0] = p[2] def p_variable_declaration_list(self, p): """variable_declaration_list : variable_declaration_list var_dec | var_dec""" if len(p) == 2: p[0] = list() p[0].append(p[1]) else: p[1].append(p[2]) p[0] = p[1] # def p_variable_declaration_list_error(self, p): # """variable_declaration_list : error""" # print "Bad declaration at line ", p.lineno(1) # self.error_encountered = True def p_var_dec(self, p): """var_dec : id_list ':' type_specifier ';' """ p[0] = VarDec(p[3], p[1], p.lineno(3)) def p_procedure_declarations(self, p): """procedure_declarations : procedure_declarations proc_dec | """ if len(p) == 1: p[0] = list() else: p[1].append(p[2]) p[0] = p[1] def p_proc_dec(self, p): """proc_dec : proc_header declarations compound_statement ';' | func_header declarations compound_statement ';' """ if len(p) == 5: p[0] = ProcDec(p[1], p[2], p[3]) def p_proc_header(self, p): """proc_header : PROCEDURE ID arguments ';' """ p[0] = ProcHeader(p[2], p[3], p.lineno(1)) def p_func_header(self, p): """func_header : FUNCTION ID arguments ':' type_specifier ';' """ if p[5] == "integer": p[0] = FuncHeader(p[2], p[3], "int", p.lineno(1)) else: p[0] = FuncHeader(p[2], p[3], p[5], p.lineno(1)) def p_arguments(self, p): """arguments : '(' argument_list ')' | """ if len(p) == 4: p[0] = p[2] else: p[0] = list() def p_argument_list(self, p): """argument_list : argument_list ';' arg | arg """ if len(p) == 4: p[1].extend(p[3]) p[0] = p[1] else: p[0] = p[1] # def p_argument_list_error(self, p): # """argument_list : error""" # print "Syntax error in argument at line ", p.lineno(1) # self.error_encountered = True def p_arg(self, p): """arg : id_list ':' type_specifier """ id_list = None type_specifier = None result = list() id_list = p[1] type_specifier = p[3] if type_specifier == "integer": type_specifier = "int" elif type_specifier == "real": type_specifier = "float" for id in id_list: #print id result.append(Argument(id, type_specifier, p.lineno(1))) p[0] = result def p_compound_statement(self, p): """compound_statement : BEGIN statement_list END""" p[0] = CompoundStatement(p[2]) def p_compound_statement_error(self, p): """compound_statement : BEGIN error END""" print "Linia: %d. Blad syntaktyczny w instrukcji zlozonej." % p.lineno(1) self.error_encountered = True def p_statement_list(self, p): """statement_list : statement_list ';' statement | statement """ if len(p) == 2: p[0] = list() p[0].append(p[1]) else: p[1].append(p[3]) p[0] = p[1] def p_statement(self, p): """statement : compound_statement | assignment_statement | procedure_call | for_statement | while_statement | if_statement | case_statement | repeat_statement | """ p[0] = p[1] def p_assignment_statement(self, p): """assignment_statement : variable ASSIGN expression""" p[0] = AssignmentStatement(p[1], p[3], p.lineno(2)) def p_procedure_call(self, p): """procedure_call : ID actuals""" p[0] = ProcedureCall(p[1], p[2], p.lineno(1)) def p_for_statement(self, p): """for_statement : FOR ID ASSIGN expression TO expression DO statement | FOR ID ASSIGN expression DOWNTO expression DO statement""" pass def p_while_statement(self, p): """while_statement : WHILE expression DO statement""" p[0] = WhileStatement(p[2], p[4], p.lineno(1)) def p_while_statement_error(self, p): """while_statement : WHILE error DO statement""" print "Linia: %d. Blad syntaktyczny w w warunku petli while." % p.lineno(1) self.error_encountered = True def p_if_statement(self, p): """if_statement : IF expression THEN statement | IF expression THEN statement ELSE statement""" if len(p) == 5: p[0] = IfStatement(p.lineno(1), p[2], p[4]) else: p[0] = IfStatement(p.lineno(1), p[2], p[4], p[6]) def p_if_statement_error(self, p): """if_statement : IF error THEN statement | IF error THEN statement ELSE statement""" print "Linia: %d. Blad syntaktyczny w warunku instrukcji warunkowej." % p.lineno(1) self.error_encountered = True def p_repeat_statement(self, p): """repeat_statement : REPEAT statement_list UNTIL expression""" p[0] = RepeatStatement(p[2], p[4], p.lineno(1)) def p_repeat_statement_error(self, p): """repeat_statement : REPEAT error UNTIL expression""" print "Linia: %d. Blad syntaktyczny w ciele instrukcji repeat." % p.lineno(1) self.error_encountered = True def p_case_statement(self, p): """case_statement : CASE expression OF case_list END""" pass def p_case_list(self, p): """case_list : case_list ';' case | case""" pass def p_case(self, p): """case : constant_list ':' statement""" pass def p_constant_list(self, p): """constant_list : constant_list ',' CONSTANT | CONSTANT""" pass def p_expression(self, p): """expression : simple_expression | simple_expression '=' simple_expression | simple_expression NEQ simple_expression | simple_expression '<' simple_expression | simple_expression LE simple_expression | simple_expression '>' simple_expression | simple_expression GE simple_expression """ if len(p) == 2: p[0] = p[1] else: p[0] = BinaryExpression(p[1], p[2], p[3], p.lineno(2)) def p_simple_expression(self, p): """simple_expression : term | simple_expression '+' term | simple_expression '-' term | simple_expression OR term """ if len(p) == 2: p[0] = p[1] else: p[0] = BinaryExpression(p[1], p[2], p[3], p.lineno(1)) def p_term(self, p): """term : factor | term '*' factor | term '/' factor | term DIV factor | term MOD factor | term AND factor """ if len(p) == 2: p[0] = p[1] else: p[0] = BinaryExpression(p[1], p[2], p[3], p.lineno(1)) def p_factor(self, p): """factor : '(' expression ')' | '+' factor | '-' factor | NOT factor | function_call | CONSTANT | variable """ if len(p) == 4: p[0] = p[2] elif len(p) == 3: p[0] = UnaryExpression(p[2, p[1]]) elif isinstance(p[1], ProcedureCall) or isinstance(p[1], Variable) or isinstance(p[1], FunctionCall): p[0] = p[1] else: p[0] = self.convert_from_string(p[1], p.lineno(1)) def p_function_call(self, p): """function_call : ID actuals""" p[0] = FunctionCall(p[1], p[2], p.lineno(1)) def p_actuals(self, p): """actuals : '(' expression_list ')' | '(' ')'""" if len(p) == 4: p[0] = p[2] else: p[0] = list() for i in p[0]: if isinstance(i, str): print i def p_actuals_error(self, p): """actuals : '(' error ')' """ print "Linia: %d. Blad w liscie argumentow." % (p.lineno(1)) def p_expression_list(self, p): """expression_list : expression_list ',' expression | expression""" if len(p) == 2: p[0] = list() p[0].append(p[1]) else: p[1].append(p[3]) p[0] = p[1] def p_variable(self, p): """variable : ID | variable '.' ID | variable '^' | variable '[' expression_list ']' """ if len(p) == 2: p[0] = Variable(p[1], p.lineno(1)) # TODO: other types of variables def p_type_specifier(self, p): """type_specifier : TYPE | '^' type_specifier | '(' id_list ')' | CONSTANT DOUBLE_DOT CONSTANT | ARRAY '[' dimension_list ']' OF type_specifier | RECORD field_list END | FILE OF type_specifier """ if len(p) == 2: p[0] = p[1] def p_dimension_list(self, p): """dimension_list : dimension_list ',' dimension | dimension""" pass def p_dimension(self, p): """dimension : CONSTANT DOUBLE_DOT CONSTANT | ID""" pass def p_field_list(self, p): """field_list : field_list ';' field | field""" pass def p_field(self, p): """field : id_list ':' type_specifier""" pass def p_id_list(self, p): """id_list : id_list ',' ID | ID""" if len(p) == 2: p[0] = list() p[0].append(p[1]) else: p[1].append(p[3]) p[0] = p[1]
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") # DONE def p_program(self, p): """program : declarations fundefs_opt instructions_opt""" declarations = p[1] fundefs_opt = p[2] instructions_opt = p[3] p[0] = AST.Program(declarations, fundefs_opt, instructions_opt) p[0].lineno = self.scanner.lexer.lineno # DONE def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: if p[1] is None: p[0] = AST.DeclarationsList() else: p[0] = p[1] p[0].addDecl(p[2]) else: p[0] = AST.DeclarationsList() p[0].lineno = self.scanner.lexer.lineno # DONE def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: type = p[1] inits = p[2] p[0] = AST.Declaration(type, inits) p[0].lineno = self.scanner.lexer.lineno # DONE def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: if p[1] is None: p[0] = AST.Inits() else: p[0] = p[1] p[0].addInit(p[3]) else: p[0] = AST.Inits() p[0].addInit(p[1]) p[0].lineno = self.scanner.lexer.lineno # DONE def p_init(self, p): """init : ID '=' expression """ id = p[1] expression = p[3] p[0] = AST.Init(id, expression) p[0].lineno = self.scanner.lexer.lineno # DONE def p_instructions_opt(self, p): """instructions_opt : instructions | """ if p[1] is not None: p[0] = AST.Instructions_opt(p[1]) p[0].lineno = self.scanner.lexer.lineno # DONE def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: if p[1] is None: p[0] = AST.InstructionsList() else: p[0] = p[1] p[0].addInstr(p[2]) else: p[0] = AST.InstructionsList() p[0].addInstr(p[1]) p[0].lineno = self.scanner.lexer.lineno # DONE def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] p[0].lineno = self.scanner.lexer.lineno # DONE def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ expr_list = p[2] p[0] = AST.PrintInstruction(expr_list) p[0].lineno = self.scanner.lexer.lineno # DONE def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ id = p[1] instruction = p[3] p[0] = AST.LabeledInstruction(id, instruction) p[0].lineno = self.scanner.lexer.lineno # DONE def p_assignment(self, p): """assignment : ID '=' expression ';' """ id = p[1] expression = p[3] p[0] = AST.Assigment(id, expression) p[0].lineno = self.scanner.lexer.lineno # ? def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ condition = p[3] instruction = p[5] if len(p) == 8: alternativeInstruction = p[7] else: alternativeInstruction = None p[0] = AST.ChoiceInstruction(condition, instruction, alternativeInstruction) p[0].lineno = self.scanner.lexer.lineno # DONE def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ condition = p[3] instruction = p[5] p[0] = AST.WhileInstruction(condition, instruction) p[0].lineno = self.scanner.lexer.lineno # ? def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ instructions = p[2] condition = p[4] p[0] = AST.RepeatInstruction(instructions, condition) p[0].lineno = self.scanner.lexer.lineno # DONE def p_return_instr(self, p): """return_instr : RETURN expression ';' """ expression = p[2] p[0] = AST.ReturnInstruction(expression) p[0].lineno = self.scanner.lexer.lineno # DONE def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstruction() p[0].lineno = self.scanner.lexer.lineno # DONE def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstruction() p[0].lineno = self.scanner.lexer.lineno # DONE def p_compound_instr(self, p): """compound_instr : '{' declarations instructions_opt '}' """ declarations = p[2] instructions_opt = p[3] p[0] = AST.CompoundInstruction(declarations, instructions_opt) p[0].lineno = self.scanner.lexer.lineno # DONE def p_condition(self, p): """condition : expression""" p[0] = p[1] p[0].lineno = self.scanner.lexer.lineno # ? def p_const(self, p): """const : INTEGER | FLOAT | STRING""" p[0] = AST.Const(p[1]) p[0].lineno = self.scanner.lexer.lineno # DONE def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: if isinstance(p[1], AST.Const): value = p[1] else: value = AST.Id(p[1]) p[0] = value elif p[1] is '(': p[0] = p[2] elif p[2] is '(' and p[1] is not '(': name = p[1] args = p[3] p[0] = AST.FunctionCalling(name, args) else: firstExpr = p[1] secExpr = p[3] operator = p[2] p[0] = AST.BinExpr(operator, firstExpr, secExpr) p[0].lineno = self.scanner.lexer.lineno # DONE def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 1: p[0] = None else: p[0] = p[1] p[0].lineno = self.scanner.lexer.lineno # DONE def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: if p[1] is None: p[0] = AST.Expressions else: p[0] = p[1] p[0].addExpression(p[3]) else: p[0] = AST.Expressions() p[0].addExpression(p[1]) p[0].lineno = self.scanner.lexer.lineno # DONE def p_fundefs_opt(self, p): """fundefs_opt : fundefs | """ if p[1] is not None: fundefs = p[1] p[0] = AST.FunDefs_opt(fundefs) p[0].lineno = self.scanner.lexer.lineno # DONE def p_fundefs(self, p): """fundefs : fundefs fundef | fundef """ if len(p) == 3: if p[1] is None: p[0] = AST.FunDefs() else: p[0] = p[1] p[0].addFunDef(p[2]) else: p[0] = AST.FunDefs() p[0].addFunDef(p[1]) p[0].lineno = self.scanner.lexer.lineno # DONE def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ type = p[1] id = p[2] args = p[4] comp = p[6] p[0] = AST.FunDef(type, id, args, comp) p[0].lineno = self.scanner.lexer.lineno # DONE def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 1: p[0] = None else: p[0] = p[1] p[0].lineno = self.scanner.lexer.lineno # DONE def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: if p[1] is None: p[0] = AST.ArgsList() else: p[0] = p[1] p[0].addArg(p[3]) else: p[0] = AST.ArgsList() p[0].addArg(p[1]) p[0].lineno = self.scanner.lexer.lineno # DONE def p_arg(self, p): """arg : TYPE ID """ type = p[1] id = p[2] p[0] = AST.Arg(type, id) p[0].lineno = self.scanner.lexer.lineno
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno(1), self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") #do nowej gramatyki: def p_program(self, p): """program : blocks""" p[0] = p[1] # print p[0] #do nowej gramatyki: def p_blocks(self, p): """blocks : blocks block | block""" if len(p) != 3: #after | p[0] = AST.Blocks() p[0].push(p[1]) else: if p[1] is None: p[0] = AST.Blocks() else: p[0] = p[1] p[0].push(p[2]) #do nowej gramatyki: def p_block(self, p): """block : declarations fundefs_opt instructions_opt""" p[0] = AST.Block(p[1], p[2], p[3]) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) != 3: #after | p[0] = AST.Declarations() else: #put right `declarations` to left `declarations` and append `declaration` if p[1] is None: p[0] = AST.Declarations() else: p[0] = p[1] p[0].push(p[2]) def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: type = p[1] inits = p[2] p[0] = AST.Declaration(type, inits, p.lineno(1)) #variable initialization def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[0] = p[1] p[0].push(p[3]) else: p[0] = AST.Inits() p[0].push(p[1]) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3], p.lineno(1)) def p_instructions_opt(self, p): """instructions_opt : instructions | """ if len(p) == 2: p[0] = p[1] else: p[0] = None def p_instructions(self, p): """instructions : instructions instruction | instruction """ #almost same as declarations if len(p) != 3: #after | p[0] = AST.Instructions() p[0].push(p[1]) else: if p[1] is None: p[0] = AST.Instructions() else: p[0] = p[1] p[0].push(p[2]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] #bo zamieniamy instruction na cos po prawej def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ expr = p[2] p[0] = AST.PrintInstr(expr, p.lineno(1)) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ id = p[1] instr = p[3] p[0] = AST.LabeledInstr(id, instr) def p_assignment(self, p): """assignment : ID '=' expression ';' """ id = p[1] expr = p[3] p[0] = AST.AssignmentInstr(id, expr, p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ condition = p[3] instruction = p[5] if len(p) >= 8: else_instr = p[7] else: else_instr = None p[0] = AST.ChoiceInstr(condition, instruction, else_instr, p.lineno(1) ) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ condition = p[3] instruction = p[5] p[0] = AST.WhileInstr(condition, instruction) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ condition = p[4] instruction = p[2] p[0] = AST.RepeatInstr(condition, instruction) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ expr = p[2] p[0] = AST.ReturnInstr(expr, p.lineno(1)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr(p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr(p.lineno(1)) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions_opt '}' """ if len(p[2].declarations) != 0: p[0] = AST.CompoundInstr(p[2], p[3], p.lineno(1)) else: p[0] = AST.CompoundInstr(None, p[3], p.lineno(1)) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" p[0] = p[1] def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')'""" #typ 0 - const i ID #typ 1 - wszystkie te `expression` cos `expression` #typ 2 - to w nawiasach #typ 3 - to z ID na poczatku if len(p) == 2: p[0] = AST.Const(p[1], p.lineno(1)) elif p[1] != "(" and p[2] == "(": #lapiemy 3 typ czyli wywolanie funkcji functionName = p[1] args = p[3] p[0] = AST.CastFunction(functionName, args, p.lineno(1)) elif p[1] == "(": #2 typ p[0] = AST.ExprInBrackets(p[2], p.lineno(1)) else: #1 typ p[0] = AST.BinExpr(p[2], p[1], p[3], p.lineno(1)) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) != 1: p[0] = p[1] else: p[0] = None def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) != 4: p[0] = AST.ExprList() p[0].push(p[1]) else: p[0] = AST.ExprList() if p[1] is None else p[1] p[0].push(p[3]) def p_fundefs_opt(self, p): """fundefs_opt : fundefs | """ if len(p) > 1: p[0] = p[1] else: p[0] = None def p_fundefs(self, p): """fundefs : fundefs fundef | fundef """ if len(p) == 3: p[0] = p[1] p[0].push(p[2]) else: p[0] = AST.FunctionList() p[0].push(p[1]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.Function(p[1], p[2], p[4], p[6], p.lineno(1)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 1: p[0] = None else: p[0] = p[1] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: if p[1] is None: p[0] = AST.Arguments() else: p[0] = p[1] p[0].push(p[3]) else: p[0] = AST.Arguments() p[0].push(p[1]) def p_arg(self, p): """arg : TYPE ID """ type = p[1] id = p[2] p[0] = AST.Argument(type, id, p.lineno(1))
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : children children children""" declarations = None if len(p[1].declarations) == 0 else p[1] fundefs = None if len(p[2].fundefs) == 0 else p[2] print AST.Program(declarations, fundefs, p[3]) def p_declarations(self, p): """children : children declaration | """ if len(p) == 3: p[0] = AST.DeclarationList() if p[1] is None else p[1] p[0].addDeclaration(p[2]) else: p[0] = AST.DeclarationList() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: type = p[1] inits = p[2] p[0] = AST.Declaration(type, inits) def p_inits(self, p): """children : children ',' init | init """ if len(p) == 4: p[0] = AST.InitList() if p[1] is None else p[1] p[0].addInit(p[3]) else: p[0] = AST.InitList() p[0].addInit(p[1]) def p_init(self, p): """init : ID '=' expression """ id = p[1] expr = p[3] p[0] = AST.Init(id, expr) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[0] = AST.InstructionList() if p[1] is None else p[1] p[0].addInstruction(p[2]) else: p[0] = AST.InstructionList() p[0].addInstruction(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ expr = p[2] p[0] = AST.PrintInstruction(expr) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ id = p[1] instruction = p[3] p[0] = AST.LabeledInstruction(id, instruction) def p_assignment(self, p): """assignment : ID '=' expression ';' """ id = p[1] expr = p[3] p[0] = AST.AssignmentInstruction(id, expr) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ condition = p[3] action = p[5] alternateAction = None if len(p) < 8 else p[7] p[0] = AST.ChoiceInstruction(condition, action, alternateAction) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ condition = p[3] instruction = p[5] p[0] = AST.WhileInstruction(condition, instruction) def p_repeat_instr(self, p): """repeat_instr : REPEAT children UNTIL condition ';' """ instructions = p[2] condition = p[4] p[0] = AST.RepeatInstruction(instructions, condition) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ expression = p[2] p[0] = AST.ReturnInstruction(expression) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstruction() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstruction() def p_compound_instr(self, p): """compound_instr : '{' children children '}' """ if len(p[2].declarations) == 0: p[0] = AST.CompoundInstruction(None, p[3]) else: p[0] = AST.CompoundInstruction(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" p[0] = p[1] def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: value = p[1] p[0] = AST.Const(value) elif p[2] == "(" and p[1] != "(": funcName = p[1] args = p[3] p[0] = AST.InvocationExpression(funcName, args) elif p[1] == "(": interior = p[2] p[0] = AST.GroupedExpression(interior) else: lhs = p[1] op = p[2] rhs = p[3] p[0] = AST.BinExpr(lhs, op, rhs) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ p[0] = None if len(p) == 1 else p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = AST.ExpressionList() if p[1] is None else p[1] p[0].addExpression(p[3]) else: p[0] = AST.ExpressionList() p[0].addExpression(p[1]) def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) == 3: p[0] = p[2] p[0].addFunction(p[1]) else: p[0] = AST.FunctionExpressionList() def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunctionExpression(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ p[0] = None if len(p) == 0 else p[1] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = AST.ArgumentList() if p[1] is None else p[1] p[0].addArgument(p[3]) else: p[0] = AST.ArgumentList() p[0].addArgument(p[1]) def p_arg(self, p): """arg : TYPE ID """ type = p[1] name = p[2] p[0] = AST.Argument(type, name)
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() self.errors = False tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): self.errors = True err_format = "Syntax error at line {0}, column {1}: LexToken({2}, '{3}')" if p: print(err_format.format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" # ^ ^ ^ ^ # p[0] p[1] p[2] p[3] program = AST.Program(p[1], p[2], p[3]) p[0] = program def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: # occurs when declarations -> declarations declaration p[1].declarations.append(p[2]) p[0] = p[1] else: # occurs when declarations -> epsilon p[0] = AST.Declarations() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 3: # occurs when error p[0] = p[1] else: p[0] = AST.Declaration(p[1], p[2]) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: # occurs when inits -> inits, init p[0] = p[1] p[0].inits.append(p[3]) else: # occurs when inits -> init p[0] = AST.Inits() p[0].inits.append(p[1]) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3], p.lineno(1)) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: # occurs when instructions -> instructions instruction p[1].instructions.append(p[2]) p[0] = p[1] else: # occurs when instructions -> instruction p[0] = AST.Instructions() p[0].instructions.append(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.PrintInstr(p[2], p.lineno(1)) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstruction(p[1], p[3], p.lineno(1)) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3], p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 8: p[0] = AST.IfElseInstr(p[3], p[5], p[7]) else: p[0] = AST.IfInstr(p[3], p[5]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p[4], p[2]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstr(p[2], p.lineno(1)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstr(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" lineno = p.lineno(1) try: int(p[1]) p[0] = AST.Integer(p[1], lineno) except ValueError: try: float(p[1]) p[0] = AST.Float(p[1], lineno) except ValueError: p[0] = AST.String(p[1], lineno) def p_id_expr(self, p): """expression : ID""" p[0] = AST.Variable(p[1], p.lineno(1)) def p_const_expr(self, p): """expression : const""" p[0] = p[1] def p_paren_expression(self, p): """expression : '(' expression ')' | '(' error ')'""" p[0] = AST.ParenExpr(p[2]) def p_funcall(self, p): """expression : ID '(' expr_list_or_empty ')' | ID '(' error ')' """ p[0] = AST.Funcall(p[1], p[3], p.lineno(1)) def p_bin_expression(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression""" p[0] = AST.BinExpr(p[2], p[1], p[3], p.lineno(2)) # operator pierwszy def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ p[0] = None if len(p) == 1 else p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ p[0] = AST.ExprList() if len(p) == 4: p[0].cons_expr(p[1].expr_list, p[3]) else: p[0].append_expr(p[1]) def p_fundefs(self, p): """fundefs : fundef fundefs | """ p[0] = AST.FundefList() if len(p) == 3: p[0].cons_fun(p[2].fundef_list, p[1]) elif len(p) == 2: p[0].append_fun(p[1]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.Fundef(p[1], p[2], p[4], p[6], p.lineno(1)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.ArgList() # empty def p_args_list(self, p): """args_list : args_list ',' arg | arg """ p[0] = AST.ArgList() if len(p) == 4: p[0].cons_arg(p[1].arg_list, p[3]) else: p[0].append_arg(p[1]) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p[1], p[2], p.lineno(1))
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() self.operation_results = OperationResults.operation_results tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : blocks""" program = AST.Program(p[1]) p[0] = program def p_blocks(self, p): """blocks : blocks block | block""" if(len(p) > 2): if(isinstance(p[2], list)): p[1].extend(p[2]) else: p[1].append(p[2]) p[0] = p[1] else: if(isinstance(p[1], list)): p[0] = p[1] else: p[0] = [p[1]] def p_block(self, p): """block : declaration | fundef | instruction""" p[0] = p[1] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if(len(p) > 2): p[0] = p[2] declared_type = p[1] for i in range(len(p[0])): p[0][i].left.type = declared_type else: p[0] = p[1] def p_inits(self, p): """inits : inits ',' init | init """ if(len(p) > 3): p[1].append(p[3]) p[0] = p[1] else: p[0] = [p[1]] def p_init(self, p): """init : ID '=' expression """ decl = AST.Declaration(AST.Id("UNKNOWN", p[1], p.lineno(1)), p[3], p.lineno(1)) p[0] = decl def p_instructions(self, p): """instructions : instructions instruction | instruction """ if(len(p) > 2): if(isinstance(p[2], list)): p[1].extend(p[2]) else: p[1].append(p[2]) p[0] = p[1] else: if(isinstance(p[1], list)): p[0] = p[1] else: p[0] = [p[1]] def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ instruction = AST.PrintInstr(p[2], p.lineno(1)) p[0] = instruction def p_return_instr(self, p): """return_instr : RETURN expression ';' """ instruction = AST.ReturnInstr(p[2], p.lineno(1)) p[0] = instruction def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if(len(p) > 7): instruction = AST.IfInstr(p[3], p[5], p.lineno(1), p[7]) p[0] = instruction elif(len(p) > 5): instruction = AST.IfInstr(p[3], p[5], p.lineno(1)) p[0] = instruction def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ instruction = AST.WhileInstr(p[3], p[5], p.lineno(1)) p[0] = instruction def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ instruction = AST.RepeatUntilInstr(p[4], p[2], p.lineno(1)) p[0] = instruction def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ instruction = AST.ContinueInstr(p.lineno(1)) p[0] = instruction def p_break_instr(self, p): """break_instr : BREAK ';' """ instruction = AST.BreakInstr(p.lineno(1)) p[0] = instruction def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = p[3] def p_assignment(self, p): """assignment : ID '=' expression ';' """ expr = AST.AssignInstr("UNKNOWN", AST.Id("UNKNOWN", p[1], p.lineno(1)), p[3], p.lineno(1)) p[0] = expr def p_compound_instr(self, p): """compound_instr : '{' blocks '}' """ p[0] = p[2] def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_bin_expression(self, p): """bin_expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression """ left_expr = p[1] op = p[2] right_expr = p[3] expr = AST.BinExpr("UNKNOWN", op, left_expr, right_expr, p.lineno(2)) p[0] = expr def p_const_int(self, p): """const : INTEGER """ const = AST.Const("int", p[1], p.lineno(1)) p[0] = const def p_const_float(self, p): """const : FLOAT """ const = AST.Const("float", p[1], p.lineno(1)) p[0] = const def p_const_string(self, p): """const : STRING """ const = AST.Const("string", p[1], p.lineno(1)) p[0] = const def p_id(self, p): """id : ID""" identifier = AST.Id("UNKNOWN", p[1], p.lineno(1)) p[0] = identifier def p_expression(self, p): """expression : id | const | bin_expression | paren_expression | funcall""" p[0] = p[1] def p_paren_expression(self, p): """paren_expression : '(' expression ')' | '(' error ')' """ p[0] = p[2] def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if(len(p) > 1): p[0] = p[1] else: p[0] = [] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if(len(p) > 3): p[1].append(p[3]) p[0] = p[1] else: p[0] = [p[1]] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ return_type = p[1] fun_name = p[2] fun_id = AST.Id(p[1], p[2], p.lineno(1)) args = p[4] fundef = AST.FunDefinition(fun_id, args, p.lineno(1), p[6]) p[0] = fundef def p_funcall(self, p): """funcall : ID '(' expr_list_or_empty ')' | ID '(' error ')' """ funcall = AST.FunCall(AST.Id("UNKNOWN", p[1], p.lineno(1)), p[3], p.lineno(1)) p[0] = funcall def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if(len(p) > 1): p[0] = p[1] else: p[0] = [] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if(len(p) > 3): p[1].append(p[3]) p[0] = p[1] else: p[0] = [p[1]] def p_arg(self, p): """arg : TYPE ID """ arg = AST.Id(p[1], p[2], p.lineno(1)) p[0] = arg
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() self.tree = None tokens = Scanner.tokens # precedence = ( # ("nonassoc", 'IFX'), # ("nonassoc", 'ELSE'), # ("right", '='), # ("left", 'OR'), # ("left", 'AND'), # ("left", '|'), # ("left", '^'), # ("left", '&'), # ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), # ("left", 'SHL', 'SHR'), # ("left", '+', '-'), # ("left", '*', '/', '%'), # ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : typeDeclarations""" p[0] = AST.Program(p.lineno(1), p[1]) print p[0] def p_typeDeclarations(self, p): """typeDeclarations : typeDeclaration | typeDeclarations typeDeclaration""" if len(p) == 2: p[0] = AST.TypeDeclarations(p.lineno(1), p[1]) elif len(p) > 2: p[0] = AST.TypeDeclarations(p.lineno(1), p[2], p[1]) def p_typeDeclaration(self, p): """typeDeclaration : classDeclaration | interfaceDeclaration""" p[0] = AST.TypeDeclaration(p.lineno(1), p[1]) def p_classDeclaration(self, p): """classDeclaration : classModifier CLASS ID inherited classBody""" p[0] = AST.ClassDeclaration(p.lineno(1), p[1], p[3], p[4], p[5]) def p_classModifier(self, p): """classModifier : ACCESS modifier | modifier | ACCESS | """ if len(p) == 2: p[0] = AST.ClassModifier(p.lineno(1), p[1]) elif len(p) > 2: p[0] = AST.ClassModifier(p.lineno(1), p[1], p[2]) else: p[0] = AST.ClassModifier() def p_modifier(self, p): """modifier : ABSTRACT | FINAL""" p[0] = AST.Modifier() def p_inherited(self, p): """inherited : extends implements | extends | implements | """ if len(p) == 2: p[0] = AST.Inherited(p.lineno(1), p[1]) elif len(p) > 2: p[0] = AST.Inherited(p.lineno(1), p[1], p[2]) else: p[0] = AST.Inherited() print p[0] def p_extends(self, p): """extends : EXTENDS ID""" p[0] = AST.Extend(p.lineno(1), p[2]) def p_implements(self, p): """implements : IMPLEMENTS implement """ p[0] = AST.Implements(p.lineno(1), p[2]) def p_implement(self, p): """implement : implement ',' ID | ID """ if len(p) == 2: p[0] = AST.Implement(p.lineno(1), p[1]) else: p[0] = AST.Implement(p.lineno(1), p[3], p[1]) def p_classBody(self, p): """classBody : '{' classBodyDeclarations '}' | '{' '}' """ if len(p) > 3: p[0] = AST.ClassBody(p.lineno(1), p[2]) else: p[0] = AST.ClassBody() def p_classBodyDeclarations(self, p): """classBodyDeclarations : classBodyDeclaration | classBodyDeclarations classBodyDeclaration""" if len(p) == 2: p[0] = AST.ClassBodyDeclarations(p.lineno(1), p[1]) else: p[0] = AST.ClassBodyDeclarations(p.lineno(1), p[2], p[1]) def p_classBodyDeclaration(self, p): """classBodyDeclaration : classMemberDeclaration | constructorDeclaration""" p[0] = AST.ClassBodyDeclaration(p.lineno(1), p[1]) def p_classMemberDeclaration(self, p): """classMemberDeclaration : fieldDeclaration | methodDeclaration""" p[0] = AST.ClassMemeberDeclaration(p.lineno(1), p[1]) def p_constructorDeclaration(self, p): """constructorDeclaration : ACCESS constructorDeclarator BODY | constructorDeclarator BODY""" if len(p) == 3: p[0] = AST.ConstructorDeclaration(p.lineno(1), p[1], p[2]) else: p[0] = AST.ConstructorDeclaration(p.lineno(1), p[2], p[3], p[1]) def p_constructorDeclarator(self, p): """constructorDeclarator : ID '(' parameterList ')' | ID '(' ')' """ if len(p) == 4: p[0] = AST.ConstructorDeclarator(p.lineno(1), p[1]) else: p[0] = AST.ConstructorDeclarator(p.lineno(1), p[1], p[3]) def p_parameterList(self, p): """parameterList : parameter | parameterList ',' parameter""" if len(p) == 2: p[0] = AST.ParameterList(p.lineno(1), p[1]) else: p[0] = AST.ParameterList(p.lineno(1), p[3], p[1]) def p_parameter(self, p): """parameter : TYPE VARID""" p[0] = AST.Parameter(p.lineno(1), p[1], p[2]) def p_fieldDeclaration(self, p): """fieldDeclaration : fieldModifiers types variableDeclarator ';' | types variableDeclarator ';' """ if len(p) == 4: p[0] = AST.FieldDclaration(p.lineno(1), p[1], p[2]) else: p[0] = AST.FieldDclaration(p.lineno(1), p[2], p[3], p[1]) def p_fieldsModifiers(self, p): """fieldModifiers : ACCESS fieldModifier | ACCESS | fieldModifier""" if len(p) == 2: p[0] = AST.FieldModifiers(p.lineno(1), p[1]) else: p[0] = AST.FieldModifiers(p.lineno(1), p[1], p[2]) def p_fieldModifier(self, p): """fieldModifier : fieldModifierStatic fieldModifierFinal | fieldModifierStatic | fieldModifierFinal""" if len(p) == 3: p[0] = AST.FieldModifier(p.lineno(1), p[1], p[2]) else: p[0] = AST.FieldModifier(p.lineno(1), p[1]) def p_fieldModifierStatic(self, p): """fieldModifierStatic : STATIC""" p[0] = AST.FieldModifierStatic() def p_fieldModifierFinal(self, p): """fieldModifierFinal : FINAL""" p[0] = AST.FieldModifierFinal() def p_types(self, p): """types : TYPE | ID""" p[0] = AST.Types(p.lineno(1), p[1]) def p_variableDeclarator(self, p): """variableDeclarator : VARID | variableDeclarator '[' ']' | VARID '<' types '>' """ if len(p) > 4: p[0] = AST.VariableDeclarator(p.lineno(1), p[1], p[3]) else: p[0] = AST.VariableDeclarator(p.lineno(1), p[1]) def p_methodDeclaration(self, p): """methodDeclaration : methodHeader BODY""" p[0] = AST.MethodDeclaration(p.lineno(1), p[1], p[2]) def p_methodHeader(self, p): """methodHeader : methodModifiers mTypes methodDeclarator | mTypes methodDeclarator""" if len(p) == 3: p[0] = AST.MethodHeader(p.lineno(1), p[1],p[2]) else: p[0] = AST.MethodHeader(p.lineno(1), p[2], p[3], p[1]) def p_mTypes(self, p): """mTypes : types | voids""" p[0] = AST.MTypes(p.lineno(1), p[1]) def p_voids(self, p): """voids : VOID""" p[0] = AST.Voids() def p_methodModifiers(self, p): """methodModifiers : ACCESS methodModifier | methodModifier""" if len(p) == 2: p[0] = AST.MethodModifiers(p.lineno(1), p[1]) else: p[0] = AST.MethodModifiers(p.lineno(1), p[1], p[2]) def p_methodModifier(self, p): """methodModifier : fieldModifier methodModifier | methodModifierAbstract | methodModifierSynchronized""" p[0] = AST.MethodModifier() def p_methodModifierAbstract(self, p): """methodModifierAbstract : ABSTRACT""" p[0] = AST.MethodModifierAbstract() def p_methodModifierSynchronized(self, p): """methodModifierSynchronized : SYNCHRONIZED""" p[0] = AST.MethodModifierAbstract() def p_methodDeclarator(self, p): """methodDeclarator : VARID '(' parameterList ')' """ p[0] = AST.MethodDeclarator(p.lineno(1), p[1], p[3]) def p_interfaceDeclaration(self, p): """interfaceDeclaration : interfaceModifier INTERFACE ID extendsInterfaces interfaceBody""" p[0] = AST.InterfaceDeclaration(p.lineno(1), p[1], p[3], p[4], p[5]) def p_interfaceModifier(self, p): """interfaceModifier : ACCESS | """ if len(p) == 2: p[0] = AST.InterfaceModifier(p.lineno(1), p[1]) else: p[0] = AST.InterfaceModifier() def p_extendsInterfaces(self, p): """extendsInterfaces : EXTENDS ID | extendsInterfaces ',' ID""" if len(p) == 3: p[0] = AST.ExtendsInterfaces(p.lineno(1), p[2]) else: p[0] = AST.ExtendsInterfaces(p.lineno(1), p[3], p[1]) def p_interfaceBody(self, p): """interfaceBody : '{' interfaceBodyDeclarations '}' """ if len(p) == 3: AST.InterfaceBody() else: AST.InterfaceBody(p.lineno(1), p[2]) def p_interfaceBodyDeclarations(self, p): """interfaceBodyDeclarations : interfaceBodyDeclaration | interfaceBodyDeclarations interfaceBodyDeclaration""" if len(p) == 2: p[0] = AST.InterfaceBodyDeclarations(p.lineno(1), p[1]) else: p[0] = AST.InterfaceBodyDeclarations(p.lineno(1), p[2], p[1]) def p_interfaceBodyDeclaration(self, p): """interfaceBodyDeclaration : fieldModifiers types VARID ';' """ p[0] = AST.InterfaceBodyDeclaration(p.lineno(1), p[1], p[2],p[3])
class Mparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IF'), ("nonassoc", 'ELSE'), ("nonassoc", 'ADDASSIGN', 'SUBASSIGN', 'MULASSIGN', 'DIVASSIGN'), ("right", '='), ("nonassoc", '<', '>'), ("nonassoc", 'SMALLEREQ', 'GREATEREQ', 'NOTEQ', 'EQ'), ("left", '+', '-'), ("left", 'MATRIX_PLUS', 'MATRIX_MINUS'), ("left", '*', '/'), ("left", 'MATRIX_TIMES', 'MATRIX_DIVIDE'), ("left", '\''), ("left", 'UMINUS') ) def p_error(self, p): if p: print("Syntax error at line {0} : LexToken({1}, '{2}')".format(p.lineno, p.type, p.value)) #p[0] = AST.Error(p.lineno, p.type, p.value) else: print("Unexpected end of input") #p[0] = AST.Error def p_program(self, p): """program : instructions_opt""" p[0] = AST.Program(p[1]) print(AST.Program(p[1])) #------ instructions: ------ def p_instructions_opt(self, p): """instructions_opt : instructions | """ p[0] = p[1] def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[0] = AST.InstructionList() if p[1] is None else p[1] p[0].add_instruction(p[2]) else: p[0] = AST.InstructionList() p[0].add_instruction(p[1]) def p_instruction(self, p): """instruction : print_instr | if_instr | for_instr | while_instr | break_instr | cont_instr | return_instr | assignment | '{' instructions '}' """ if (p[1] == '{'): p[0] = p[2] else: p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT multi_print ';'""" p[0] = AST.PrintInstr(p[2], p.lineno(1)) def p_multi_print(self, p): """multi_print : multi_print ',' expression | expression""" if (not isinstance(p[0], list)): p[0] = [] if (len(p) == 4): p[0] = p[1] p[0].append(p[3]) else: p[0].append(p[1]) def p_if_instr(self, p): """if_instr : IF '(' condition ')' instruction | IF '(' condition ')' instruction ELSE instruction""" if(len(p) > 6): p[0] = AST.IfInstr(p.lineno(1), p[3], p[5], p[7]) else: p[0] = AST.IfInstr(p.lineno(1), p[3], p[5]) def p_for_instr(self, p): """for_instr : FOR id '=' range_instr instruction""" p[0] = AST.ForInstr(p[2], p[4], p[5], p.lineno(1)) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction""" p[0] = AST.WhileInstr(p[3], p[5], p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr(p.lineno(1)) def p_cont_instr(self, p): """cont_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr(p.lineno(1)) def p_return_instr(self, p): """return_instr : RETURN expression ';'""" p[0] = AST.ReturnInstr(p[2],p.lineno(1)) def p_eye_instr(self, p): """eye_instr : EYE '(' int ')'""" p[0] = AST.EyeInstr(p[3], p.lineno(1)) def p_zeros_instr(self, p): """zeros_instr : ZEROS '(' int ')' """ p[0] = AST.ZerosInstr(p[3], p.lineno(1)) def p_ones_instr(self, p): """ones_instr : ONES '(' int ')' """ p[0] = AST.OnesInstr(p[3], p.lineno(1)) def p_assignment(self, p): """assignment : id assign_ops matrix ';' | id assign_ops expression ';' | id '[' INTNUM ',' INTNUM ']' assign_ops expression ';' """ if(len(p)<6): p[0] = AST.AssInstr(p[2], p[1], p[3], p.lineno(1)) else: p[0] = AST.AssTabInstr(p[7], p[1], AST.IntNum(p[3], p.lineno(1)), AST.IntNum(p[5], p.lineno(1)), p[8], p.lineno(1)) def p_assign_ops(self, p): """assign_ops : SUBASSIGN | ADDASSIGN | DIVASSIGN | MULASSIGN | '=' """ p[0] = p[1] def p_range_instr(self, p): """range_instr : int ':' int | int ':' id | id ':' id | id ':' int""" p[0] = AST.RangeInstr(p[1],p[3]) def p_int(self, p): """int : INTNUM""" p[0] = AST.IntNum(p[1], p.lineno(1)) def p_float(self, p): """float : FLOATNUM""" p[0] = AST.FloatNum(p[1], p.lineno(1)) def p_condition(self, p): """condition : expression EQ expression | expression NOTEQ expression | expression GREATEREQ expression | expression SMALLEREQ expression | expression '>' expression | expression '<' expression""" p[0] = AST.CondInstr(p[1], p[2], p[3]) def p_number_or_id(self, p): """number_or_id : int | float | id""" p[0] = p[1] p[0] = p[1] #------ expressions: ------ def p_expression_group(self, p): """expression : '(' expression ')'""" p[0] = p[2] def p_binary_operators(self, p): """ expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | number_or_id | '-' expression %prec UMINUS | m_expr | string | ones_instr | zeros_instr | eye_instr | matrix """ #TODO: sprawdzic!!! if(len(p) == 4): p[0] = AST.BinExpr(p[2], p[1], p[3], p.lineno(1)) elif(len(p) == 3): p[0] = AST.NegatedExpr(p[2]) else: p[0] = p[1] def p_string(self, p): """ string : STRING""" p[0] = AST.String(p[1], p.lineno(1)) #------ matrix parse: ------ def p_matrix(self, p): """matrix : '[' body ']' | matrix_transp | id""" if len(p) == 4: p[0] = AST.Matrix(p[2], p.lineno(1)) else: p[0] = p[1] def p_id(self, p): """id : ID""" p[0] = AST.Variable(p[1], p.lineno(1)) def p_matrix_transp(self, p): """matrix_transp : matrix "'" """ p[0] = AST.MatrixTransp(p[1]) def p_body(self, p): '''body : rows_with_brackets | rows_with_semicolons''' p[0] = p[1] def p_rows_with_brackets(self, p): '''rows_with_brackets : '[' row ']' | rows_with_brackets ',' '[' row ']' ''' if (not isinstance(p[0], list)): p[0] = [] if (len(p) != 4): p[0] = p[1] p[0].append(p[4]) else: p[0].append(p[2]) def p_rows_with_semicolons(self, p): '''rows_with_semicolons : row | rows_with_semicolons ';' row''' if (not isinstance(p[0], list)): p[0] = [] if (len(p) != 2): p[0] = p[1] p[0].append(p[3]) else: p[0].append(p[1]) def p_row(self, p): """row : NUMBER | row ',' NUMBER """ if(not isinstance(p[0], list)): p[0] = [] if(len(p) != 2): p[0] = p[1] p[0].append(p[3]) else: p[0].append(p[1]) def p_number(self, p): """NUMBER : int | float""" p[0] = p[1] #------ matrix operations: ------ def p_matrix_matrix_operations(self, p): #zamiast matrix expression '''m_expr : matrix MATRIX_PLUS matrix | matrix MATRIX_MINUS matrix | matrix MATRIX_TIMES matrix | matrix MATRIX_DIVIDE matrix''' p[0] = AST.Matrix_bin_ops(p[1], p[2], p[3])
class Mparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ('left', ','), ('right', '=', 'ADDASSIGN', 'SUBASSIGN', 'MULASSIGN', 'DIVASSIGN'), ("left", "EQ", "NEQ"), ("left", "<", ">", "LEQ", "GEQ"), ("left", '+', '-', 'DOTADD', 'DOTSUB'), ('left', '*', '/', 'DOTMUL', 'DOTDIV'), ('right', 'UMINUS'), ) def p_error(self, p): if p: error_type = "Syntax error at line " + \ "{0}, pos {1}: LexToken({2}, '{3}')""".format( p.lineno, self.scanner.find_column(p), p.type, p.value) else: error_type = "Unexpected end of input" raise Exception def p_program(self, p): """program : instructions_opt""" p[0] = Program(p[1], line_no=p.lineno) def p_instructions_opt_1(self, p): """instructions_opt : instructions """ p[0] = InstructionsOpt(p[1], line_no=p.lineno) def p_instructions_opt_2(self, p): """instructions_opt : """ def p_instructions_1(self, p): """instructions : instructions instruction """ p[0] = p[1] + [p[2]] def p_instructions_2(self, p): """instructions : instruction """ p[0] = [p[1]] def p_instruction(self, p): """instruction : inst ';' | condition | expr ';' | inst ',' | expr ',' """ p[0] = p[1] def p_inst_assign(self, p): """inst : ids '=' expr | ids ADDASSIGN expr | ids SUBASSIGN expr | ids MULASSIGN expr | ids DIVASSIGN expr """ p[0] = Assign(p[1], p[2], p[3], line_no=p.lineno(2)) def p_ids(self, p): """ids : ID | ID '[' values ']' """ if len(p) <= 2: p[0] = Variable(p[1], line_no=p.lineno(1)) else: p[0] = Variable(p[1], p[3], line_no=p.lineno(1)) def p_break(self, p): """inst : BREAK """ p[0] = Instruction(p[1], line_no=p.lineno(1)) def p_continue(self, p): """inst : CONTINUE """ p[0] = Instruction(p[1], line_no=p.lineno(1)) def p_return(self, p): """inst : RETURN | RETURN values | RETURN expr """ value = None if len(p) > 2: value = p[2] p[0] = Instruction(p[1], value, line_no=p.lineno(1)) def p_print(self, p): """inst : PRINT values | PRINT expr """ p[0] = Instruction(p[1], p[2], line_no=p.lineno(1)) def p_expr_binary(self, p): """expr : expr '+' expr | expr '-' expr | expr '*' expr | expr '/' expr """ p[0] = BinExpr(p[2], p[1], p[3], line_no=p.lineno(2)) def p_expr_elementwise(self, p): """expr : expr DOTADD expr | expr DOTSUB expr | expr DOTMUL expr | expr DOTDIV expr """ p[0] = BinExpr(p[2], p[1], p[3], line_no=p.lineno(2)) def p_expr_eq(self, p): """expr : expr EQ expr | expr GEQ expr | expr LEQ expr | expr NEQ expr | expr '<' expr | expr '>' expr""" p[0] = Equality(p[2], p[1], p[3], line_no=p.lineno(2)) def p_expr_paren(self, p): """expr : '(' expr ')' """ p[0] = p[2] def p_expr_transpose(self, p): """expr : expr "'" """ p[0] = Transpose(p[2], p[1], line_no=p.lineno(2)) def p_expr_negative(self, p): """expr : '-' expr %prec UMINUS""" p[0] = Negation(p[2], line_no=p.lineno(1)) def p_expr(self, p): """expr : ids | integer | float | string | matrix """ p[0] = p[1] def p_integer(self, p): """integer : INTNUM """ p[0] = IntNum(p[1], line_no=p.lineno(1)) def p_float(self, p): """float : FLOAT """ p[0] = FloatNum(p[1], line_no=p.lineno(1)) def p_string(self, p): """string : STRING """ p[0] = String(p[1], line_no=p.lineno(1)) def p_matrix_operations(self, p): """matrix : ZEROS '(' values ')' | ONES '(' values ')' | EYE '(' values ')' """ p[0] = MatrixOperation(p[1], p[3], line_no=p.lineno(1)) def p_matrix_init(self, p): """matrix : '[' rows ']' | '[' rows ';' ']' """ p[0] = Matrix(p[2], line_no=p.lineno(1)) def p_rows(self, p): """rows : values """ p[0] = [p[1]] def p_rows_2(self, p): """rows : rows ';' values """ p[0] = p[1] + [p[3]] def p_values(self, p): """values : expr """ p[0] = [p[1]] def p_values_2(self, p): """values : values ',' expr """ p[0] = p[1] + [p[3]] def p_block(self, p): """ block : '{' instructions_opt '}' """ p[0] = p[2] def p_block_2(self, p): """ block : instruction """ p[0] = InstructionsOpt([p[1]], line_no=p.lineno) def p_conditional(self, p): """ condition : if_condition | for_condition | while_condition """ p[0] = p[1] def p_if(self, p): """ if_condition : if_cond""" p[0] = p[1] def p_if_2(self, p): """ if_condition : if_cond ELSE block""" p[0] = p[1] p[0].else_block = p[3] def p_if_3(self, p): """ if_condition : if_cond ELSE if_condition""" p[0] = p[1] p[0].else_cond = p[3] def p_if_cond(self, p): """ if_cond : IF '(' expr ')' block """ p[0] = IfCondition(p[3], p[5], line_no=p.lineno) def p_for(self, p): """ for_condition : FOR ids '=' range block """ p[0] = ForCondition(p[2], p[4], p[5], line_no=p.lineno(3)) def p_range(self, p): """ range : expr ':' expr """ p[0] = Range(p[1], p[3], line_no=p.lineno(2)) def p_while(self, p): """ while_condition : WHILE '(' expr ')' block """ p[0] = WhileCondition(p[3], p[5], line_no=p.lineno(1))
class PascalParser(object): #precedence rules for operators precedence = ( ('left', '+', '-'), ('left', '*', '/') ) #Each parser action is defined as the following: #def p_<name>(self, p): # """Grammar rule""" # <action code> #p is a list object that contains objects that represent the symbols in the grammar rule #For example: #""" assign : ident ASSIGN_OP expression""" # p[0] p[1] p[2] p[3] #data can be bubbled up to parent rules by assignment to p[0] #region Actions def p_program(self, p): """program : program_decl""" p[0] = p[1] print(p[1]) def p_program_decl(self, p): """program_decl : program_ident compound_statement '.' """ p[0] = p[1] def p_program_decl_err(self, p): """program_decl : program_ident error '.' """ p[0] = p[1] def p_program_decl_wvar(self, p): """program_decl : program_ident variable_decl_sec compound_statement '.'""" p[0] = p[1] def p_program_decl_wvar_err_a(self, p): """program_decl : program_ident error compound_statement '.'""" print(f"Err line {p.lineno(2)}") for s in p[3]: print('\t' + s + ';') p[0] = p[1] def p_program_decl_wvar_err_b(self, p): """program_decl : program_ident variable_decl_sec error '.'""" print("Compund statement error") p[0] = p[1] def p_program_ident(self, p): """program_ident : PROGRAM identifier ';'""" p[0] = str(p[1]) + " " + p[2] def p_program_ident_error(self, p): """program_ident : PROGRAM error ';'""" print("Program Identifier Error") def p_variable_decl_sec(self, p): """variable_decl_sec : VAR variable_decl_sec_inner""" def p_variable_decl_sec_err(self, p): """variable_decl_sec : VAR error""" print("Variable inner error") def p_variable_decl_sec_inner(self, p): """variable_decl_sec_inner : variable_declaration ';' | variable_decl_sec_inner variable_declaration ';'""" def p_variable_declaration(self, p): """variable_declaration : identifier_list ':' type""" s_type = "none" s_data = None if p[3] == "Integer": s_type = "int" s_data = 1 for s in p[1]: self.interpreter.newsym(s, s_type, s_data) def p_identifier(self, p): """identifier : NAME""" p[0] = p[1] def p_identifier_list(self, p): """identifier_list : identifier | identifier_list ',' identifier""" if len(p) == 2: p[0] = [p[1]] else: if p[1] is None: p[0] = [p[3]] else: p[0] = p[1] p[0].append(p[3]) def p_type(self, p): """type : INTEGER""" p[0] = p[1] def p_compound_statement(self, p): """compound_statement : BEGIN statement_list END""" p[0] = p[2] def p_compound_statement_err(self, p): """compound_statement : BEGIN error END""" print("Compund Statement Error") def p_statement_list(self, p): """statement_list : statement | statement_list statement""" if len(p) == 2: p[0] = [p[1]] else: if p[1] is None: p[0] = [p[2]] else: p[0] = p[1] p[0].append(p[2]) def p_statement(self, p): """statement : assignment_statement | function_statement | compound_statement""" p[0] = p[1] def p_assignment_statement(self, p): """assignment_statement : identifier OP_ASSIGN actual_value ';'""" up = f"{p[1]} := {p[3]}" p[0] = up def p_assignment_err(self, p): """assignment_statement : identifier OP_ASSIGN error ';'""" print(f"Syntax error line {p.lineno(3)}: Malformed expression") def p_function_statement(self, p): """function_statement : function_designator ';'""" param = [] name = '' desig = p[1] if(len(desig) == 2): name, param = desig else: name = desig sym = self.interpreter.getsym(name) sym.data(*param) def p_function_designator(self, p): """function_designator : identifier | identifier actual_parameter_list""" if len(p) == 2: p[0] = (p[1]) else: p[0] = (p[1], p[2]) def p_actual_parameter_list(self, p): """actual_parameter_list : '(' actual_parameter_list_inner ')'""" up = p[2] p[0] = up def p_actual_parameter_list_inner(self, p): """actual_parameter_list_inner : actual_parameter | actual_parameter_list_inner ',' actual_parameter""" if len(p) == 2: p[0] = [p[1]] else: if p[1] is None: p[0] = [p[3]] else: p[0] = p[1] p[0].append(p[3]) def p_actual_parameter(self, p): """actual_parameter : actual_value""" p[0] = p[1] def p_actual_value(self, p): """actual_value : expression""" up = p[1] exp = ''.join(p[1]) p[0] = eval(exp) def p_expression(self, p): """expression : term | '-' term | '+' term | expression addition_operator term""" up = None if len(p) == 2: up = p[1] elif len(p) == 3: up = [p[1], *p[2]] else: up = p[1] + [p[2], *p[3]] p[0] = up def p_expression_err_a(self, p): """expression : error addition_operator term""" print("Expression error type A") def p_expression_err_b(self, p): """expression : expression error term""" print("Expression error type B") def p_expression_err_c(self, p): """expression : expression addition_operator error""" print("Expression error type C") def p_addition_operator(self, p): """addition_operator : '+' | '-'""" p[0] = p[1] def p_term(self, p): """term : factor | term multiplication_operator factor""" up = None if len(p) == 2: up = [p[1]] else: up = p[1] + [p[2], p[3]] p[0] = up def p_multiplication_operator_m(self, p): """multiplication_operator : '*' | '/'""" up = p[1] if up == '/': up = '//' p[0] = up def p_factor_str(self, p): """factor : STRING""" p[0] = p[1] def p_factor_exp(self, p): """factor : '(' expression ')'""" p[0] = p[1] def p_factor_ident(self, p): """factor : identifier""" p[0] = str(self.interpreter.getsym(p[1]).data) def p_error(self, p): print("Syntax error in input!") print(p) #endregion #Helper methods def Parse(self, text): self.interpreter = Interpreter() self.Yacc.parse(text, lexer=self.Lexer.Lexer, tracking=True) def build(self,**kwargs): self.Lexer = Scanner() self.Lexer.build() self.tokens = self.Lexer.tokens self.Yacc = yacc.yacc(module=self, **kwargs)
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" def p_declarations(self, p): """declarations : declarations declaration | """ def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ def p_inits(self, p): """inits : inits ',' init | init """ def p_init(self, p): """init : ID '=' expression """ def p_instructions(self, p): """instructions : instructions instruction | instruction """ def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ def p_assignment(self, p): """assignment : ID '=' expression ';' """ def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ def p_return_instr(self, p): """return_instr : RETURN expression ';' """ def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ def p_break_instr(self, p): """break_instr : BREAK ';' """ def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ def p_condition(self, p): """condition : expression""" def p_const(self, p): """const : INTEGER | FLOAT | STRING""" def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ def p_fundefs(self, p): """fundefs : fundef fundefs | """ def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ def p_args_list(self, p): """args_list : args_list ',' arg | arg """ def p_arg(self, p): """arg : TYPE ID """
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : children children children""" declarations = None if len(p[1].declarations) == 0 else p[1] fundefs = None if len(p[2].fundefs) == 0 else p[2] print AST.Program(declarations, fundefs, p[3]) def p_declarations(self, p): """children : children declaration | """ if len(p) == 3: p[0] = AST.DeclarationList() if p[1] is None else p[1] p[0].addDeclaration(p[2]) else: p[0] = AST.DeclarationList() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: type = p[1] inits = p[2] p[0] = AST.Declaration(type, inits) def p_inits(self, p): """children : children ',' init | init """ if len(p) == 4: p[0] = AST.InitList() if p[1] is None else p[1] p[0].addInit(p[3]) else: p[0] = AST.InitList() p[0].addInit(p[1]) def p_init(self, p): """init : ID '=' expression """ id = p[1] expr = p[3] p[0] = AST.Init(id, expr) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[0] = AST.InstructionList() if p[1] is None else p[1] p[0].addInstruction(p[2]) else: p[0] = AST.InstructionList() p[0].addInstruction(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ expr = p[2] p[0] = AST.PrintInstruction(expr) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ id = p[1] instruction = p[3] p[0] = AST.LabeledInstruction(id, instruction) def p_assignment(self, p): """assignment : ID '=' expression ';' """ id = p[1] expr = p[3] p[0] = AST.AssignmentInstruction(id, expr) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ condition = p[3] action = p[5] alternateAction = None if len(p) < 8 else p[7] p[0] = AST.ChoiceInstruction(condition, action, alternateAction) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ condition = p[3] instruction = p[5] p[0] = AST.WhileInstruction(condition, instruction) def p_repeat_instr(self, p): """repeat_instr : REPEAT children UNTIL condition ';' """ instructions = p[2] condition = p[4] p[0] = AST.RepeatInstruction(instructions, condition) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ expression = p[2] p[0] = AST.ReturnInstruction(expression) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstruction() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstruction() def p_compound_instr(self, p): """compound_instr : '{' children children '}' """ if len(p[2].declarations) == 0: p[0] = AST.CompoundInstruction(None, p[3]) else: p[0] = AST.CompoundInstruction(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" p[0] = p[1] def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: value = p[1] p[0] = AST.Const(value) elif p[2] == "(" and p[1] != "(": funcName = p[1] args = p[3] p[0] = AST.InvocationExpression(funcName, args) elif p[1] == "(": interior = p[2] p[0] = AST.GroupedExpression(interior) else: lhs = p[1] op = p[2] rhs = p[3] p[0] = AST.BinExpr(lhs, op, rhs) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ p[0] = None if len(p) == 1 else p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = AST.ExpressionList() if p[1] is None else p[1] p[0].addExpression(p[3]) else: p[0] = AST.ExpressionList() p[0].addExpression(p[1]) def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) == 3: p[0] = p[2] p[0].addFunction(p[1]) else: p[0] = AST.FunctionExpressionList() def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunctionExpression(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ p[0] = None if len(p) == 0 else p[1] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = AST.ArgumentList() if p[1] is None else p[1] p[0].addArgument(p[3]) else: p[0] = AST.ArgumentList() p[0].addArgument(p[1]) def p_arg(self, p): """arg : TYPE ID """ type = p[1] name = p[2] p[0] = AST.Argument(type, name)
class MParser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens + Scanner.literals precedence = ( ('nonassoc', 'IFX'), ('nonassoc', 'ELSE'), ('left', ','), ('right', '=', 'PLUSASSIGN', 'MINUSASSIGN', 'MULASSIGN', 'DIVASSIGN'), ('left', 'EQ', 'NEQ'), ('left', '>', '<', 'LESSEQ', 'MOREEQ'), ('left', '+', '-'), ('left', '*', '/'), ('nonassoc', 'UMINUS'), ('left', 'DOTPLUS', 'DOTMINUS'),#? ('left', 'DOTMUL', 'DOTDIV'),#? ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : instructions_opt""" p[0] = AST.Program(p[1]) print(p[0]) def p_instructions_opt_1(self, p): """instructions_opt : instructions """ p[0] = p[1] def p_instructions_opt_2(self, p): """instructions_opt : """ def p_instructions(self, p): """instructions : instructions instruction | instruction""" if len(p) == 3: p[0] = AST.InstructionList() if p[1] is None else p[1] p[0].add_instruction(p[2]) else: p[0] = AST.InstructionList() p[0].add_instruction(p[1]) def p_instruction(self, p): """instruction : if_else_instr | while_instr | for_instr | break_instr | continue_instr | return_instr | print_instr | instr_block | assignment ';'""" p[0] = p[1] def p_if_else_inst(self, p): """if_else_instr : IF '(' expression ')' instruction %prec IFX | IF '(' expression ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ else_inst = p[7] if len(p) == 8 else None p[0] = AST.IfElseInstr(p[3], p[5], else_inst) def p_while_inst(self, p): """while_instr : WHILE '(' expression ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p[3], p[5], p.lineno(1)) def p_for_inst(self, p): """for_instr : FOR for_init instruction""" p[0] = AST.ForInstr(p[2], p[3]) def p_for_init(self, p): """for_init : ID '=' expression ':' expression""" p[0] = AST.ForInit(p[1], p[3], p[5], p.lineno(1)) def p_break_inst(self, p): """break_instr : BREAK ';'""" p[0] = AST.BreakInstr(p.lineno(1)) def p_continue_inst(self, p): """continue_instr : CONTINUE ';'""" p[0] = AST.ContinueInstr(p.lineno(1)) def p_return_instr(self, p): """return_instr : RETURN expression ';'""" p[0] = AST.ReturnInstr(p[2], p.lineno(1)) def p_print_instr(self, p): """print_instr : PRINT print_vars ';' | PRINT error ';'""" p[0] = AST.PrintInstr(p[2], p.lineno(1)) def p_print_vars(self, p): """print_vars : print_vars ',' print_var | print_var""" if len(p) == 4: p[0] = AST.PrintVarsList() if p[1] is None else p[1] p[0].add_var(p[3]) else: p[0] = AST.PrintVarsList() p[0].add_var(p[1]) def p_print_var(self, p): """print_var : STRING | expression """ p[0] = p[1] def p_complex_instr(self, p): """instr_block : '{' instructions '}'""" p[0] = AST.InstrBlock(p[2]) def p_number_int(self, p): """number : INT""" p[0] = AST.Integer(p[1], p.lineno(1)) def p_number_float(self, p): """number : FLOAT""" p[0] = AST.Float(p[1], p.lineno(1)) def p_lvalue(self, p): """lvalue : ID | ID '[' INT ']' | ID '[' INT ',' INT ']'""" if len(p) == 2: p[0] = AST.LValue(p[1], None, p.lineno(1)) else: p[0] = AST.LValue(p[1], [p[3]], p.lineno(1)) if len(p) == 5 else AST.LValue(p[1], [p[3], p[5]], p.lineno(1)) def p_assignment(self, p): """assignment : lvalue assign_op expression""" p[0] = AST.AssignmentInstr(p[1], p[2], p[3], p.lineno(1)) def p_assign_op(self, p): """assign_op : '=' | PLUSASSIGN | MINUSASSIGN | MULASSIGN | DIVASSIGN""" p[0] = p[1] def p_expression(self, p): """expression : number | lvalue | matrix_init | '(' expression ')' | '-' expression %prec UMINUS | expression '\\''""" if len(p) == 2: p[0] = p[1] elif len(p) == 3: p[0] = AST.UnOperation(p[1], p[2], p.lineno(1)) if p[1] == '-' else AST.UnOperation(p[2], p[1], p.lineno(2)) else: p[0] = p[2] def p_rel_op(self, p): """expression : expression '<' expression | expression '>' expression | expression EQ expression | expression NEQ expression | expression LESSEQ expression | expression MOREEQ expression""" p[0] = AST.BinOperation(p[2], p[1], p[3], p.lineno(2)) def p_num_op(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression""" p[0] = AST.BinOperation(p[2], p[1], p[3], p.lineno(2)) def p_dot_op(self, p): """expression : expression DOTPLUS expression | expression DOTMINUS expression | expression DOTMUL expression | expression DOTDIV expression""" p[0] = AST.BinOperation(p[2], p[1], p[3], p.lineno(2)) def p_matrix_init(self, p): """matrix_init : eye | ones | zeros | '[' matrix_rows ']' | '[' scopes ']'""" p[0] = p[1] if len(p) == 2 else p[2] def p_eye(self, p): """eye : EYE '(' expression ')' """ p[0] = AST.EyeInit(p[3], p.lineno(1)) def p_ones(self, p): """ones : ONES '(' expression ')' """ p[0] = AST.OnesInit(p[3], p.lineno(1)) def p_zeros(self, p): """zeros : ZEROS '(' expression ')' """ p[0] = AST.ZerosInit(p[3], p.lineno(1)) def p_matrix_rows(self, p): """matrix_rows : matrix_rows ';' row_elems | row_elems """ if len(p) == 4: p[0] = AST.Matrix(p.lineno(1)) if p[1] is None else p[1] p[0].add_row(p[3]) else: p[0] = AST.Matrix(p.lineno(1)) p[0].add_row(p[1]) def p_row_elems(self, p): """row_elems : row_elems ',' number | number """ if len(p) == 4: p[0] = AST.MatrixRow(p.lineno(1)) if p[1] is None else p[1] p[0].add_elem(p[3]) else: p[0] = AST.MatrixRow(p.lineno(1)) p[0].add_elem(p[1]) def p_scopes(self, p): """scopes : scope | scopes ';' scope """ if len(p) == 4: p[0] = AST.Matrix(p.lineno(1)) if p[1] is None else p[1] p[0].add_row(p[3]) else: p[0] = AST.Matrix(p.lineno(1)) p[0].add_row(p[1]) def p_scope(self, p): """scope : INT ':' INT | number ':' number ':' number""" p[0] = AST.MatrixRow(p.lineno(1)) if len(p) == 4: p[0].add_from_scope(p[1], 1, p[3]) else: p[0].add_from_scope(p[1], p[3], p[5])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : declarations fundefs_opt instructions_opt""" print( AST.Program(declarations=p[1], fundefs_opt=p[2], instructions_opt=p[3])) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: p[0] = AST.Declarations() if p[1] is None else p[1] p[0].add(p[2]) else: p[0] = AST.Declarations() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: p[0] = AST.Declaration(d_type=p[1], inits=p[2]) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[0] = AST.Inits() if p[1] is None else p[1] p[0].add(p[3]) else: p[0] = AST.Inits() p[0].add(p[1]) def p_init(self, p): """init : ID '=' expression """ d_id = p[1] expr = p[3] p[0] = AST.Init(d_id, expr) def p_instructions_opt(self, p): """instructions_opt : instructions | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.Instructions() def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[0] = AST.Instructions() if p[1] is None else p[1] p[0].add(p[2]) else: p[0] = AST.Instructions() p[0].add(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ expression_list = p[2] p[0] = AST.PrintInstruction(expression_list) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstruction(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(id=p[1], expression=p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ else_instruction = None if len(p) < 8 else p[7] p[0] = AST.ChoiceInstruction(condition=p[3], instruction=p[5], else_instruction=else_instruction) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstruction(condition=p[3], instruction=p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstruction(condition=p[4], instructions=p[2]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstruction(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstruction() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstruction() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions_opt '}' """ p[0] = AST.CompoundInstruction(declarations=p[2], instructions_opt=p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" p[0] = p[1] def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: p[0] = AST.Const(p[1]) elif p[1] == '(': p[0] = p[2] elif p[2] == '(': p[0] = AST.Funcall(id=p[1], expression_list=p[3]) else: p[0] = AST.BinExpr(left=p[1], op=p[2], right=p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = ExpressionList() def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = AST.Expressions() if p[1] is None else p[1] p[0].add(p[3]) else: p[0] = AST.Expressions() p[0].add(p[1]) def p_fundefs_opt(self, p): """fundefs_opt : fundefs | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.Fundefs() def p_fundefs(self, p): """fundefs : fundefs fundef | fundef """ if len(p) == 3: p[0] = AST.Fundefs() if p[1] is None else p[1] p[0].add(p[2]) else: p[0] = AST.Fundefs() p[0].add(p[1]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.Fundef(d_type=p[1], id=p[2], arguments=p[4], compound_instructions=p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.Arguments() def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = AST.Arguments() if p[1] is None else p[1] p[0].add(p[3]) else: p[0] = AST.Arguments() p[0].add(p[1]) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Argument(type=p[1], id=p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if not p: print('Syntax error at end of input') else: pass def handle_error(self, type, p): print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')" .format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) def p_program(self, p): """program : declarations fundefs_opt instructions_opt""" p[0] = Program(p[1], p[2], p[3]) # declarations def p_declarations(self, p): """declarations : declarations declaration""" if p[2]: p[0] = DeclarationList(p[1].dec_list + [p[2]]) else: p[0] = p[1] def p_no_declarations(self, p): """declarations : """ p[0] = DeclarationList([]) # END declarations # declaration def p_declaration(self, p): """declaration : TYPE inits ';'""" p[0] = Declaration(p[1], p[2]) def p_error_declaration(self, p): """declaration : error ';'""" self.handle_error('declaration', p[1]) # END declaration # inits def p_inits(self, p): """inits : inits ',' init""" p[0] = InitList(p[1].init_list + [p[3]]) def p_single_init(self, p): """inits : init """ p[0] = InitList([p[1]]) # END inits def p_init(self, p): """init : ID '=' expression """ p[0] = Init(p[1], p[3]) # instructions_opt def p_instructions_opt(self, p): """instructions_opt : instructions""" p[0] = p[1] def p_empty_instructions_opt(self, p): """instructions_opt : """ p[0] = InstructionList([]) # END instructions_opt # instructions def p_instructions(self, p): """instructions : instructions instruction""" p[0] = InstructionList(p[1].instr_list + [p[2]]) def p_sinle_instruction(self, p): """instructions : instruction """ p[0] = InstructionList([p[1]]) # END instructions def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] # print_instr def p_print_instr(self, p): """print_instr : PRINT expr_list ';'""" p[0] = PrintInstr(p[2]) def p_print_instr_err(self, p): """print_instr : PRINT error ';' """ self.handle_error('print', p[2]) # END print_instr def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = Labeled_instr(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = Assignment(p[1], p[3]) # choice_instr def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX """ p[0] = ChoiceInstr(p[3], p[5]) def p_choice_instr_with_else(self, p): """choice_instr : IF '(' condition ')' instruction ELSE instruction """ p[0] = ChoiceInstr(p[3], p[5], p[7]) def p_error_choice_instr(self, p): """choice_instr : IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ self.handle_error('IF', p[3]) # END choice)instr # while_instr def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction """ p[0] = WhileInstr(p[3], p[5]) def p_error_while_instr(self, p): """while_instr : WHILE '(' error ')' instruction """ self.handle_error('while', p[3]) # END while_instr def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = RepeatInstr(p[4], p[2]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = Return(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = KeyWord("continue") def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = KeyWord("break") def p_compound_instr(self, p): """compound_instr : '{' declarations instructions_opt '}' """ p[0] = Compound_instr(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = Condition(p[1]) def p_const_I(self, p): """const : INTEGER""" p[0] = Integer(p[1]) def p_const_F(self, p): """const : FLOAT""" p[0] = Float(p[1]) def p_const_S(self, p): """const : STRING""" p[0] = String(p[1]) # expression def p_expression(self, p): """expression : ID '(' expr_list_or_empty ')' """ p[0] = ExpressionIdWithList(p[1], p[3]) def p_expression_const(self, p): """expression : const """ p[0] = p[1] def p_expression_id(self, p): """expression : ID """ p[0] = Id(p[1]) def p_expression_with_par(self, p): """expression : '(' expression ')' """ p[0] = p[2] def p_expression_two_exprs(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression """ p[0] = BinExpr(p[2], p[1], p[3]) def p_expression_err(self, p): """expression : ID '(' error ')' | '(' error ')'""" self.handle_error('Expr', p[2]) # END expression # expr_list_or_empty def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list""" p[0] = p[1] def p_empty_expr_list(self, p): """expr_list_or_empty : """ p[0] = ExprList([]) # END expr_list_or_empty # expr_list def p_expr_list(self, p): """expr_list : expr_list ',' expression""" p[0] = ExprList(p[1].expr_list + [p[3]]) def p_single_expr(self, p): """expr_list : expression """ p[0] = ExprList([p[1]]) # END expr_list # fundefs_opt def p_fundefs_opt(self, p): """fundefs_opt : fundefs""" p[0] = p[1] def p_empty_fundefs_opt(self, p): """fundefs_opt : """ p[0] = FunctionList([]) # END fundefs_opt # fundefs def p_fundefs(self, p): """fundefs : fundefs fundef""" p[0] = FunctionList(p[1].fun_list + [p[2]]) def p_single_fundef(self, p): """fundefs : fundef """ p[0] = FunctionList([p[1]]) # END fundefs def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = Function(p[1], p[2], p[4], p[6]) # args_list_or_empty def p_args_list_or_empty(self, p): """args_list_or_empty : args_list""" p[0] = p[1] def p_empty_args_list(self, p): """args_list_or_empty : """ p[0] = ArgsList([]) # END args_list_or_empty # args_list def p_args_list(self, p): """args_list : args_list ',' arg""" p[0] = ArgsList(p[1].args_list + [p[3]]) def p_single_arg_list(self, p): """args_list : arg """ p[0] = ArgsList([p[1]]) # END args_list def p_arg(self, p): """arg : TYPE ID """ p[0] = Arg(p[1], p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : instruction_list""" p[0] = AST.Program(p[1]) def p_instruction_list(self, p): """instruction_list : instruction_list instruction_item | """ if len(p) == 3: p[0] = list(p[1]) if p[1] else [] p[0].append(p[2]) else: p[0] = [] def p_instruction_item(self, p): """instruction_item : declaration | fundef | instruction""" p[0] = p[1] def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: p[0] = list(p[1]) if p[1] else [] p[0].append(p[2]) else: p[0] = [] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: p[0] = AST.Declaration(AST.Name(p[1]), p[2]) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[0] = list(p[1]) p[0].append(p[3]) else: p[0] = [p[1]] def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Initializer(AST.Name(p[1]), p[3]) def p_instructions_opt(self, p): """instructions_opt : instructions | """ if len(p) == 2: p[0] = list(p[1]) else: p[0] = [] def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[0] = list(p[1]) p[0].append(p[2]) else: p[0] = [p[1]] def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ p[0] = AST.PrintInstr(p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstr(AST.Name(p[1]), p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(AST.Name(p[1]), p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ p[0] = AST.IfInstr(p[3], p[5], None if len(p) < 8 else p[7]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstr(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstr(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : integer | float | string""" p[0] = p[1] def p_integer(self, p): """integer : INTEGER""" p[0] = AST.Integer(p[1]) def p_float(self, p): """float : FLOAT""" p[0] = AST.Float(p[1]) def p_string(self, p): """string : STRING""" p[0] = AST.String(p[1]) def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: if isinstance(p[1], AST.Const): p[0] = p[1] else: p[0] = AST.Name(p[1]) elif p[1] == '(': p[0] = AST.EnclosedExpr(p[2]) elif p[2] == '(': p[0] = AST.MethodCallExpr(AST.Name(p[1]), p[3]) else: p[0] = AST.BinaryExpr(p[1], AST.Operator(p[2]), p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = list(p[1]) else: p[0] = [] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = list(p[1]) p[0].append(p[3]) else: p[0] = [p[1]] def p_fundefs_opt(self, p): """fundefs_opt : fundefs | """ if len(p) == 2: p[0] = list(p[1]) else: p[0] = [] def p_fundefs(self, p): """fundefs : fundefs fundef | fundef """ if len(p) == 3: p[0] = list(p[1]) p[0].append(p[2]) else: p[0] = [p[1]] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunctionDef(AST.Name(p[1]), AST.Name(p[2]), p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = list(p[1]) else: p[0] = [] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = list(p[1]) p[0].append(p[3]) else: p[0] = [p[1]] def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Argument(AST.Name(p[1]), AST.Name(p[2]))
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : sections""" p[0] = AST.Program(p[1]) def p_sections(self, p): """sections : sections section | """ p[0] = [] if len(p) == 1 else p[1] + [p[2]] def p_section(self, p): """section : fundef | statement """ p[0] = p[1] def p_statement(self, p): """statement : declaration | instruction """ p[0] = p[1] def p_statements(self, p): """statements : statements statement | statement""" p[0] = [p[1]] if len(p) == 2 else p[1] + [p[2]] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ p[0] = p[1] if len(p) == 3 else AST.Declaration(p[1], p[2]) def p_inits(self, p): """inits : inits ',' init | init """ p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]] def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3], p.lineno(1)) def p_instructions(self, p): """instructions : instructions instruction | instruction """ p[0] = p[1] + [p[2]] if len(p) == 3 else [p[1]] def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ p[0] = AST.PrintInstr(p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstr(p[1], p[3], p.lineno(1)) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3], p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ p[0] = AST.ChoiceInstr(*p[3::2]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstr(p[2], p.lineno(1)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr(p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr(p.lineno(1)) def p_compound_instr(self, p): """compound_instr : '{' statements '}' """ p[0] = AST.CompoundInstr(p[2]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : float | integer | string""" p[0] = p[1] def p_integer(self, p): """integer : INTEGER""" p[0] = AST.Integer(p[1]) def p_float(self, p): """float : FLOAT""" p[0] = AST.Float(p[1]) def p_string(self, p): """string : STRING""" p[0] = AST.String(p[1]) def p_bin_expr(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression""" p[0] = AST.BinExpr(p[2], p[1], p[3], p.lineno(2)) def p_funcall_expr(self, p): """expression : ID '(' expr_list_or_empty ')' | ID '(' error ')' """ p[0] = AST.FunCall(p[1], p[3], p.lineno(1)) def p_bracket_expr(self, p): """ expression : '(' expression ')' | '(' error ')'""" p[0] = p[2] def p_expression(self, p): """expression : const | ID""" p[0] = AST.Identifier(p[1], p.lineno(1)) if type(p[1]) is str else p[1] def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ p[0] = [] if len(p) == 1 else p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ p[0] = [p[1]] if len(p) == 2 else p[1] + [p[3]] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' '{' statements '}' """ p[0] = AST.FunDef(p[1], p[2], p[4], p[7], p.lineno(1), p.lineno(8)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ p[0] = [] if len(p) == 1 else p[1] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ p[0] = [p[1]] if len(p) == 2 else p[1] + [p[3]] def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.FunArg(p[1], p[2], p.lineno(1))
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_file(self, p): """file : program""" program = p[1] print AST.File(program) def p_program(self, p): """program : program_parts | """ p[0] = p[1] if len(p) == 2 else AST.Epsilon() def p_program_parts(self, p): """program_parts : program_parts program_part | program_part""" if len(p) == 3: p[0] = p[1] p[0].appendPart(p[2]) else: p[0] = AST.ProgramParts() p[0].appendPart(p[1]) def p_program_part(self, p): """program_part : declaration | instruction | fundef""" p[0] = p[1] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ type = p[1] inits = p[2] p[0] = AST.Declaration(type, inits) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[0] = p[1] p[0].addInit(p[3]) else: p[0] = AST.InitList() p[0].addInit(p[1]) def p_init(self, p): """init : ID '=' expression """ id = p[1] expression = p[3] p[0] = AST.Init(id, expression) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ p[0] = AST.PrintInstruction(p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstruction(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ condition = p[3] instruction = p[5] elseInstruction = p[7] if len(p) == 8 else None p[0] = AST.ChoiceInstruction(condition, instruction, elseInstruction) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ condition = p[3] instruction = p[5] p[0] = AST.WhileLoop(condition, instruction) def p_repeat_instr(self, p): """repeat_instr : REPEAT program_parts UNTIL condition ';' """ program_parts = p[2] condition = p[4] p[0] = AST.RepeatInstruction(program_parts, condition) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstruction(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstruction() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstruction() def p_compound_instr(self, p): """compound_instr : '{' program_parts '}' """ program_parts = p[2] p[0] = AST.CompoundInstruction(program_parts) def p_condition(self, p): """condition : expression""" p[0] = AST.Condition(p[1]) def p_const(self, p): """const : INTEGER | FLOAT | STRING""" p[0] = AST.Const(p[1]) def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ lenp = len(p) if lenp == 2: p[0] = p[1] elif lenp == 4: if p[1] == '(': if p[2] == ')': p[0] = AST.Epsilon else: p[0] = p[2] else: p[0] = AST.BinExpr(p[2], p[1], p[3]) elif lenp == 5: p[0] = AST.FunCall(p[1], p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 1: p[0] = AST.Epsilon() else: p[0] = p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 2: p[0] = AST.ExprList() p[0].addExpr(p[1]) else: p[0] = p[1] p[0].addExpr(p[3]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ ret = p[1] name = p[2] args = p[4] compound = p[6] p[0] = AST.Fundef(ret, name, args, compound) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.Epsilon() def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = p[1] p[0].appendArg(p[3]) else: p[0] = AST.ArgsList() p[0].appendArg(p[1]) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p[1], p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) error_encountered = False def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" p[0] = Program(p[1], p[2], p[3]) #if self.error_encountered == False: # p[0].accept(TypeChecker(), SymbolTable(None)) p[0].error_encountered = self.error_encountered def p_declarations(self, p): """declarations : declarations declaration | """ if (len(p) == 3): p[1].append(p[2]) p[0] = p[1] else: p[0] = list() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: p[0] = Declaration(p[1], p[2]) else: print "Bad declaration at line", p.lineno(1) self.error_encountered = True def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[1].append(p[3]) p[0] = p[1] else: p[0] = list() p[0].append(p[1]) def p_init(self, p): """init : ID '=' expression """ p[0] = Init(p[1], p[3], p.lineno(1)) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[1].append(p[2]) p[0] = p[1] else: p[0] = list() p[0].append(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ if isinstance(p[2], Node): p[0] = PrintInstr(p[2]) else: print "Bad expression in print instruction at line", p.lineno(1) self.error_encountered = True def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = p[3] def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = Assignment(p[1], p[3], p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if isinstance(p[3], Node) == False: print "Bad condition in choice instruction at line", p.lineno(1) self.error_encountered = True elif len(p) == 6: p[0] = ChoiceInstr(p[3], p[5]) else: p[0] = ChoiceInstr(p[3], p[5], p[7]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ if isinstance(p[3], Node) == False: print "Bad condition in while instruction at line", p.lineno(1) self.error_encountered = True else: p[0] = WhileInstr(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = RepeatInstr(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = RetInstr(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = ContinueInstr() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = BreakInstr() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = CompoundInstr(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" try: p[0] = Integer(int(p[1]), p.lineno(1)) except ValueError: try: p[0] = Float(float(p[1]), p.lineno(1)) except ValueError: p[0] = String(p[1], p.lineno(1)) ''' if isinstance(p[1], int): p[0] = Integer(p[1], p.lineno(1)) elif isinstance(p[1], float): p[0] = Float(p[1], p.lineno(1)) else: p[0] = String(p[1], p.lineno(1)) ''' def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 5: if isinstance(p[3], list): p[0] = FunCall(p[1], p[3], p.lineno(1)) else: print "Bad function call at line", p.lineno(1) self.error_encountered = True elif len(p) == 4 and p[1] == '(': if isinstance(p[2], Node) == False: print "Bad expression at line", p.lineno(1) self.error_encountered = True else: p[0] = p[2] elif len(p) == 2: if type(p[1]) is str: p[0] = Variable(p[1], p.lineno(1)) else: p[0] = p[1] else: p[0] = BinExpr(p[1], p[2], p[3], p.lineno(2)) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = list() def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[1].append(p[3]) p[0] = p[1] else: p[0] = list() p[0].append(p[1]) def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) == 3: p[2].append(p[1]) p[0] = p[2] else: p[0] = list() def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = FunDef(p[1], p[2], p[4], p[6], p.lineno(1)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] #at least one element in list else: p[0] = list() #empty list def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[1].append(p[3]) p[0] = p[1] else: p[0] = list() p[0].append(p[1]) def p_arg(self, p): """arg : TYPE ID """ p[0] = Arg(p[1], p[2], p.lineno(1))
class Cparser(object): palka = '' def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) error = 0 def p_error(self, p): Cparser.error = 1 if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) #exit(1); else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" p[0] = AST.Program(p[1], p[2], p[3]) #print(p[0].toString(0)) p[1].line = self.scanner.lexer.lineno p[1].line = self.scanner.lexer.lineno def p_declarations(self, p): """declarations : declarations declaration""" p[0] = AST.Declarations(p[1], p[2]) p[0].line = self.scanner.lexer.lineno def p_declarations_1(self, p): """declarations : """ p[0] = AST.Empty() p[0].line = self.scanner.lexer.lineno def p_declaration(self, p): """declaration : TYPE inits ';' """ p[0] = AST.Declaration(p[1], p[2]) p[0].line = self.scanner.lexer.lineno def p_declaration_error(self, p): """declaration : error ';' """ self.p_error(p[1]) def p_inits(self, p): """inits : inits ',' init""" p[0] = AST.Inits(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_inits_1(self, p): """inits : init""" p[0] = AST.Inits(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_instructions(self, p): """instructions : instructions instruction""" p[0] = AST.Instructions(p[1], p[2]) p[0].line = self.scanner.lexer.lineno def p_instructions_1(self, p): """instructions : instruction""" p[0] = AST.Instructions(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = AST.Instruction(p[1]) p[0].line = self.scanner.lexer.lineno def p_print_instr(self, p): """print_instr : PRINT expression ';'""" p[0] = AST.Print(p[2]) p[0].line = self.scanner.lexer.lineno def p_print_instr_1(self, p): """print_instr : PRINT error ';' """ self.p_error(p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.Labeled(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX""" p[0] = AST.Choice(p[3], p[5], None) p[0].line = self.scanner.lexer.lineno def p_choice_instr_1(self, p): """choice_instr : IF '(' condition ')' instruction ELSE instruction""" p[0] = AST.Choice(p[3], p[5], p[7]) p[0].line = self.scanner.lexer.lineno def p_choice_instr_error(self, p): """choice_instr : IF '(' error ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX""" self.p_error(p[3]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction""" p[0] = AST.While(p[3], p[5]) p[0].line = self.scanner.lexer.lineno def p_while_instr_error(self, p): """while_instr : WHILE '(' error ')' instruction """ self.p_error(p[3]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.Repeat(p[2], p[4]) p[0].line = self.scanner.lexer.lineno def p_repeat_error(self, p): """repeat_instr : REPEAT instructions UNTIL error ';' """ self.p_error(p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.Return(p[2]) p[0].line = self.scanner.lexer.lineno def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.Keyword(p[1]) p[0].line = self.scanner.lexer.lineno def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.Keyword(p[1]) p[0].line = self.scanner.lexer.lineno def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstruction(p[2], p[3]) p[0].line = self.scanner.lexer.lineno def p_condition(self, p): """condition : expression""" p[0] = AST.Condition(p[1]) p[0].line = self.scanner.lexer.lineno def p_int(self, p): """const : INTEGER""" p[0] = AST.Integer(p[1]) p[0].line = self.scanner.lexer.lineno def p_float(self, p): """const : FLOAT""" p[0] = AST.Float(p[1]) p[0].line = self.scanner.lexer.lineno def p_string(self, p): """const : STRING""" p[0] = AST.String(p[1]) p[0].line = self.scanner.lexer.lineno def p_expression_const(self, p): """expression : const""" p[0] = p[1] def p_expression_id(self, p): """expression : ID""" p[0] = AST.Variable(p[1]) p[0].line = self.scanner.lexer.lineno def p_expression(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '^' expression | expression '|' expression | expression '&' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression """ p[0] = AST.BinExpression(p[1], p[2], p[3]) p[0].line = self.scanner.lexer.lineno def p_expression_1(self, p): """expression : ID '(' expr_list_or_empty ')'""" p[0] = AST.Funcall(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_expression_2(self, p): """expression : '(' expression ')'""" p[0] = AST.ExpressionInParentheses(p[2]) p[0].line = self.scanner.lexer.lineno def p_expression_error(self, p): """expression : '(' error ')'""" self.p_error(p[2]) def p_expression_error_2(self, p): """expression : ID '(' error ')'""" self.p_error(p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list""" p[0] = AST.ExpressionList(p[1], None) p[0].line = self.scanner.lexer.lineno def p_expr_list_or_empty_1(self, p): """expr_list_or_empty : """ p[0] = AST.Empty() p[0].line = self.scanner.lexer.lineno def p_expr_list(self, p): """expr_list : expr_list ',' expression""" p[0] = AST.ExpressionList(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_expr_list_1(self, p): """expr_list : expression""" p[0] = AST.ExpressionList(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_fundefs(self, p): """fundefs : fundef fundefs""" p[0] = AST.FunctionDefinitions(p[1], p[2]) p[0].line = self.scanner.lexer.lineno def p_fundefs_1(self, p): """fundefs : """ p[0] = AST.Empty() p[0].line = self.scanner.lexer.lineno def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunctionDefinition(p[1], p[2], p[4], p[6]) p[0].line = self.scanner.lexer.lineno def p_args_list_or_empty(self, p): """args_list_or_empty : args_list""" p[0] = AST.ArgumentList(p[1], None) p[0].line = self.scanner.lexer.lineno def p_arg_list_or_empty_1(self, p): """args_list_or_empty : """ p[0] = AST.Empty() p[0].line = self.scanner.lexer.lineno def p_args_list(self, p): """args_list : args_list ',' arg""" p[0] = AST.ArgumentList(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_arg_list_1(self, p): """args_list : arg""" p[0] = AST.ArgumentList(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Argument(p[1], p[2]) p[0].line = self.scanner.lexer.lineno
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : declarations fundefs_opt instructions_opt""" def p_declarations(self, p): """declarations : declarations declaration | """ def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ def p_inits(self, p): """inits : inits ',' init | init """ def p_init(self, p): """init : ID '=' expression """ def p_instructions_opt(self, p): """instructions_opt : instructions | """ def p_instructions(self, p): """instructions : instructions instruction | instruction """ def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ def p_assignment(self, p): """assignment : ID '=' expression ';' """ def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ def p_return_instr(self, p): """return_instr : RETURN expression ';' """ def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ def p_break_instr(self, p): """break_instr : BREAK ';' """ def p_compound_instr(self, p): """compound_instr : '{' declarations instructions_opt '}' """ def p_condition(self, p): """condition : expression""" def p_const(self, p): """const : INTEGER | FLOAT | STRING""" def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ def p_fundefs_opt(self, p): """fundefs_opt : fundefs | """ def p_fundefs(self, p): """fundefs : fundefs fundef | fundef """ def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ def p_args_list(self, p): """args_list : args_list ',' arg | arg """ def p_arg(self, p): """arg : TYPE ID """
class Cparser(object): def __init__(self): self.error_occured = False self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : main_parts_interlacing""" #p[0] = ('program',p[1],p[2],p[3]) p[0] = Program(p[1]) def p_main_parts_interlacing(self, p): """main_parts_interlacing : main_parts_interlacing main_part | main_part """ if p.__len__() == 3: p[0] = MainPartsInerlacing(p[1], p[2]) else: p[0] = MainPartsInerlacing(None, p[1]) def p_main_part(self, p): """ main_part : declaration | fundef | instruction """ p[0] = p[1] def p_declarations(self, p): """declarations : declarations declaration | """ #p[0] = ('') if p.__len__() == 1 else ('decl',p[1], p[2]) p[0] = None if p.__len__() == 1 else Declarations(p[1], p[2]) def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ #p[0] = ('declaration',p[1], p[2]) if p.__len__() == 4 else ('declaration-error',p[1]) #p[0] = Declaration(p[1], p[2]) if not type(p[1]) == LexToken: p[0] = Declaration(p[1], p[2]) else: self.error_occured = True def p_inits(self, p): """inits : inits ',' init | init """ #p[0] = ('inits',p[1],p[3]) if p.__len__() == 4 \ # else ('init',p[1]) p[0] = Inits(p[1],p[3]) if p.__len__() == 4 \ else p[1] def p_init(self, p): """init : ID '=' expression """ #p[0] = ('init','=',p[1],p[3]) p[0] = Init(p[1], p[3]) def p_instructions_opt(self, p): """instructions_opt : instructions | """ #p[0] = ('instructions_opt',p[1]) if p.__len__()==2 else('empty_instr') p[0] = InstructionsOpt(p[1]) if p.__len__() == 2 else None def p_instructions(self, p): """instructions : instructions instruction | instruction """ #p[0] = ('instructions',p[1],p[2]) if p.__len__()==3 else ('instruction', p[1]) p[0] = Instructions(p[1], p[2]) if p.__len__() == 3 else p[1] def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ #p[0] = ('instruction-node',p[1]) p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ #p[0] = ('print_instr', p[1], p[2]) if not type(p[2]) == LexToken: p[0] = PrintInstr(p[2]) else: self.error_occured = True def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ #p[0] = ('labeled_instr', p[1], p[3]) p[0] = LabeledInstr(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ #p[0] = ('assignment',p[1],p[3]) p[0] = Assignment(p[1], p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ #p[0] = ('if-cond-instr',p[3],p[5])if p.__len__() == 6 else ('if-cond-instr-else-instr',p[3],p[5],p[7]) if not type(p[3]) == LexToken: p[0] = ChoiceInstr(p[3], p[5]) if p.__len__() == 6 else ChoiceInstr( p[3], p[5], p[7]) else: self.error_occured = True def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ #p[0] = ('while-instr',p[3],p[5]) if not type(p[3]) == LexToken: p[0] = WhileInstr(p[3], p[5]) else: self.error_occured = True def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ #p[0] = ('repeat',p[2],p[4]) p[0] = RepeatInstr(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ #p[0] = ('return',p[2]) p[0] = ReturnInstr(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ #p[0] = ('continue') p[0] = ContinueInstr() def p_break_instr(self, p): """break_instr : BREAK ';' """ #p[0] = ('break') p[0] = BreakInstr() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions_opt '}' """ #p[0] = ('compound_instr',p[2],p[3]) p[0] = CompoundInstr(p[2], p[3]) def p_condition(self, p): """condition : expression""" #p[0] = ('condition',p[1]) p[0] = Condition(p[1]) def p_const(self, p): """const : INTEGER | FLOAT | STRING""" #p[0] = p[1] p[0] = Const(p[1]) #to-do!! def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ #p[0] = (p[1]) if p.__len__() == 2 else \ # (p[2],p[1],p[3]) if p.__len__() == 4 and p[1]!='(' else \ # p[2] if p.__len__() == 4 and p[1]=='(' else (p[1],p[3]) """ p[0] = p[1] if p.__len__() == 2 else \ BinExpr(p[2],p[1],p[3]) if p.__len__() == 4 and p[1]!='(' else \ p[2] if p.__len__() == 4 and p[1]=='(' else DeclaredFunc(p[1],p[3]) """ if p.__len__() == 2: p[0] = p[1] elif p.__len__() == 4: if p[1] != '(': p[0] = BinExpr(p[2], p[1], p[3]) else: if not type(p[2]) == LexToken: p[0] = p[2] else: self.error_occured = True else: if not type(p[3]) == LexToken: p[0] = DeclaredFunc(p[1], p[3]) else: self.error_occured = True def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ #p[0] = ('expr_list',p[1]) if p.__len__()==2 else ('empty_exprlist') p[0] = PExprListOrEmpty(p[1]) if p.__len__() == 2 else None def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ #p[0] = ('expr_list',p[1],p[3]) if p.__len__() == 4 else ('expr',p[1]) p[0] = PExprList(p[1], p[3]) if p.__len__() == 4 else p[1] def p_fundefs_opt(self, p): """fundefs_opt : fundefs | """ #p[0] = ('fundefs_opt',p[1]) if p.__len__() == 2 else ('no fundefs') p[0] = FuncDefsOpt(p[1]) if p.__len__() == 2 else None def p_fundefs(self, p): """fundefs : fundefs fundef | fundef """ #p[0] = ('fundefs',p[1],p[2]) if p.__len__() == 3 else ("fundef", p[1]) p[0] = FuncDefs(p[1], p[2]) if p.__len__() == 3 else p[1] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ #p[0] = ('fundef',p[2],p[1],p[4],p[6]) p[0] = FuncDef(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ #p[0] = ('args_list_',p[1]) if p.__len__() == 2 else ("empty-args-list") p[0] = p[1] if p.__len__() == 2 else None def p_args_list(self, p): """args_list : args_list ',' arg | arg """ #p[0] = ('args_list',p[1],p[3]) if p.__len__() == 4 else ('arg', p[1]) p[0] = ArgsList(p[1], p[3]) if p.__len__() == 4 else p[1] def p_arg(self, p): """arg : TYPE ID """ #p[0] = ('arg',p[1],p[2]) p[0] = Arg(p[1], p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : segments""" if len(p) == 2: p[0] = ast.Program(p.lineno(1), p[1]) # list def p_segments(self, p): """segments : segments segment | """ if len(p) == 3: p[0] = p[1] p[0].append(p[2]) elif len(p) == 1: p[0] = [] # 1-1 def p_segment(self, p): """segment : declaration | function_definition | instruction """ if len(p) == 2: p[0] = p[1] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: p[0] = ast.Declaration(p.lineno(1), p[1], p[2]) # list def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[0] = p[1] p[0].append(p[3]) elif len(p) == 2: p[0] = [p[1]] def p_init(self, p): """init : ID '=' expression """ if len(p) == 4: p[0] = ast.Init(p.lineno(1), p[1], p[3]) # list def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[0] = p[1] p[0].append(p[2]) elif len(p) == 2: p[0] = [p[1]] # 1-1 def p_instruction(self, p): """instruction : print_instruction | labeled_instruction | assignment | choice_instruction | while_instruction | repeat_instruction | return_instruction | break_instruction | continue_instruction | compound_instructions | expression ';'""" if len(p) == 2 or len(p) == 3: p[0] = p[1] def p_print_instruction(self, p): """print_instruction : PRINT expr_list ';' | PRINT error ';' """ if len(p) == 4: p[0] = ast.PrintInstruction(p.lineno(1), p[2]) def p_labeled_instruction(self, p): """labeled_instruction : ID ':' instruction """ p[0] = ast.LabeledInstruction(p.lineno(1), p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ if len(p) == 5: identifier = ast.Identifier(p.lineno(1), p[1]) p[0] = ast.Assignment(p.lineno(1), identifier, p[3]) def p_choice_instruction(self, p): """choice_instruction : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) >= 6: p[0] = ast.ChoiceInstruction(p.lineno(1), p[3], p[5], None) if len(p) == 8: p[0] = ast.ChoiceInstruction(p.lineno(1), p[3], p[5], p[7]) def p_while_instruction(self, p): """while_instruction : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ if len(p) == 6: p[0] = ast.WhileInstruction(p.lineno(1), p[3], p[5]) def p_repeat_instruction(self, p): """repeat_instruction : REPEAT instructions UNTIL condition ';' """ if len(p) == 6: p[0] = ast.RepeatInstruction(p.lineno(1), p[2], p[4]) def p_return_instruction(self, p): """return_instruction : RETURN expression ';' """ if len(p) == 4: p[0] = ast.ReturnInstruction(p.lineno(1), p[2]) def p_break_instruction(self, p): """break_instruction : BREAK ';' """ if len(p) == 3: p[0] = ast.BreakInstruction(p.lineno(1)) def p_continue_instruction(self, p): """continue_instruction : CONTINUE ';' """ if len(p) == 3: p[0] = ast.ContinueInstruction(p.lineno(1)) def p_compound_instructions(self, p): """compound_instructions : '{' compound_segments '}' """ if len(p) == 4: p[0] = ast.CompoundInstructions(p.lineno(1), p[2], p.lineno(3)) # list def p_compound_segments(self, p): """compound_segments : compound_segments compound_segment | """ if len(p) == 3: p[0] = p[1] p[0].append(p[2]) elif len(p) == 1: p[0] = [] # 1-1 def p_compound_segment(self, p): """compound_segment : declaration | instruction """ if len(p) == 2: p[0] = p[1] # 1-1 def p_condition(self, p): """condition : expression""" if len(p) == 2: p[0] = p[1] # 1-1 def p_const(self, p): """const : integer | float | string """ if len(p) == 2: p[0] = p[1] def p_integer(self, p): """integer : INTEGER""" if len(p) == 2: p[0] = ast.Integer(p.lineno(1), p[1]) def p_float(self, p): """float : FLOAT""" if len(p) == 2: p[0] = ast.Float(p.lineno(1), p[1]) def p_string(self, p): """string : STRING""" if len(p) == 2: p[0] = ast.String(p.lineno(1), p[1]) def p_identifier_expression(self, p): """identifier_expression : ID""" p[0] = ast.Identifier(p.lineno(1), p[1]) def p_function_call_expression(self, p): """function_call_expression : ID '(' expr_list_or_empty ')' | ID '(' error ')' """ p[0] = ast.FunctionCallExpression(p.lineno(1), p[1], p[3]) # 1-1 def p_expression(self, p): """expression : binary_expression | '(' expression ')' | '(' error ')' | identifier_expression | function_call_expression | const """ if len(p) == 4: if p[1] == '(': p[0] = p[2] else: p[0] = p[1] def p_binary_expression(self, p): """binary_expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression """ if len(p) == 4: p[0] = ast.BinExpr(p.lineno(2), p[1], p[2], p[3]) def p_function_definition(self, p): """function_definition : TYPE ID '(' args_list_or_empty ')' compound_instructions """ if len(p) == 7: p[0] = ast.FunctionDefinition(p.lineno(1), p[1], p[2], p[4], p[6], p[6].end_lineno) # list def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = p[1] p[0].append(p[3]) elif len(p) == 2: p[0] = [p[1]] def p_arg(self, p): """arg : TYPE ID """ if len(p) == 3: p[0] = ast.Argument(p.lineno(1), p[1], p[2]) # list def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = [] # list def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = p[1] p[0].append(p[3]) elif len(p) == 2: p[0] = [p[1]] # 1-1 def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] elif len(p) == 1: p[0] = []
class Cparser(object): palka = '' def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) error = 0 def p_error(self, p): Cparser.error = 1 if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) #exit(1); else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" p[0] = AST.Program(p[1], p[2], p[3]) #print(p[0].toString(0)) p[1].line = self.scanner.lexer.lineno p[1].line = self.scanner.lexer.lineno def p_declarations(self, p): """declarations : declarations declaration""" p[0] = AST.Declarations(p[1], p[2]) p[0].line = self.scanner.lexer.lineno def p_declarations_1(self, p): """declarations : """ p[0] = AST.Empty() p[0].line = self.scanner.lexer.lineno def p_declaration(self, p): """declaration : TYPE inits ';' """ p[0] = AST.Declaration(p[1], p[2]) p[0].line = self.scanner.lexer.lineno def p_declaration_error(self, p): """declaration : error ';' """ self.p_error(p[1]) def p_inits(self, p): """inits : inits ',' init""" p[0] = AST.Inits(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_inits_1(self, p): """inits : init""" p[0] = AST.Inits(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_instructions(self, p): """instructions : instructions instruction""" p[0] = AST.Instructions(p[1], p[2]) p[0].line = self.scanner.lexer.lineno def p_instructions_1(self, p): """instructions : instruction""" p[0] = AST.Instructions(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = AST.Instruction(p[1]) p[0].line = self.scanner.lexer.lineno def p_print_instr(self, p): """print_instr : PRINT expression ';'""" p[0] = AST.Print(p[2]) p[0].line = self.scanner.lexer.lineno def p_print_instr_1(self, p): """print_instr : PRINT error ';' """ self.p_error(p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.Labeled(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX""" p[0] = AST.Choice(p[3], p[5], None) p[0].line = self.scanner.lexer.lineno def p_choice_instr_1(self, p): """choice_instr : IF '(' condition ')' instruction ELSE instruction""" p[0] = AST.Choice(p[3], p[5], p[7]) p[0].line = self.scanner.lexer.lineno def p_choice_instr_error(self, p): """choice_instr : IF '(' error ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX""" self.p_error(p[3]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction""" p[0] = AST.While(p[3], p[5]) p[0].line = self.scanner.lexer.lineno def p_while_instr_error(self, p): """while_instr : WHILE '(' error ')' instruction """ self.p_error(p[3]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.Repeat(p[2], p[4]) p[0].line = self.scanner.lexer.lineno def p_repeat_error(self, p): """repeat_instr : REPEAT instructions UNTIL error ';' """ self.p_error(p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.Return(p[2]) p[0].line = self.scanner.lexer.lineno def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.Keyword(p[1]) p[0].line = self.scanner.lexer.lineno def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.Keyword(p[1]) p[0].line = self.scanner.lexer.lineno def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstruction(p[2], p[3]) p[0].line = self.scanner.lexer.lineno def p_condition(self, p): """condition : expression""" p[0] = AST.Condition(p[1]) p[0].line = self.scanner.lexer.lineno def p_int(self, p): """const : INTEGER""" p[0] = AST.Integer(p[1]) p[0].line = self.scanner.lexer.lineno def p_float(self, p): """const : FLOAT""" p[0] = AST.Float(p[1]) p[0].line = self.scanner.lexer.lineno def p_string(self, p): """const : STRING""" p[0] = AST.String(p[1]) p[0].line = self.scanner.lexer.lineno def p_expression_const(self, p): """expression : const""" p[0] = p[1] def p_expression_id(self, p): """expression : ID""" p[0] = AST.Variable(p[1]) p[0].line = self.scanner.lexer.lineno def p_expression(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '^' expression | expression '|' expression | expression '&' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression """ p[0] = AST.BinExpression(p[1], p[2], p[3]) p[0].line = self.scanner.lexer.lineno def p_expression_1(self, p): """expression : ID '(' expr_list_or_empty ')'""" p[0] = AST.Funcall(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_expression_2(self, p): """expression : '(' expression ')'""" p[0] = AST.ExpressionInParentheses(p[2]) p[0].line = self.scanner.lexer.lineno def p_expression_error(self, p): """expression : '(' error ')'""" self.p_error(p[2]) def p_expression_error_2(self, p): """expression : ID '(' error ')'""" self.p_error(p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list""" p[0] = AST.ExpressionList(p[1], None) p[0].line = self.scanner.lexer.lineno def p_expr_list_or_empty_1(self, p): """expr_list_or_empty : """ p[0] = AST.Empty() p[0].line = self.scanner.lexer.lineno def p_expr_list(self, p): """expr_list : expr_list ',' expression""" p[0] = AST.ExpressionList(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_expr_list_1(self, p): """expr_list : expression""" p[0] = AST.ExpressionList(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_fundefs(self, p): """fundefs : fundef fundefs""" p[0] = AST.FunctionDefinitions(p[1], p[2]) p[0].line = self.scanner.lexer.lineno def p_fundefs_1(self, p): """fundefs : """ p[0] = AST.Empty() p[0].line = self.scanner.lexer.lineno def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunctionDefinition(p[1], p[2], p[4], p[6]) p[0].line = self.scanner.lexer.lineno def p_args_list_or_empty(self, p): """args_list_or_empty : args_list""" p[0] = AST.ArgumentList(p[1], None) p[0].line = self.scanner.lexer.lineno def p_arg_list_or_empty_1(self, p): """args_list_or_empty : """ p[0] = AST.Empty() p[0].line = self.scanner.lexer.lineno def p_args_list(self, p): """args_list : args_list ',' arg""" p[0] = AST.ArgumentList(p[1], p[3]) p[0].line = self.scanner.lexer.lineno def p_arg_list_1(self, p): """args_list : arg""" p[0] = AST.ArgumentList(None, p[1]) p[0].line = self.scanner.lexer.lineno def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Argument(p[1], p[2]) p[0].line = self.scanner.lexer.lineno
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : segments""" p[0] = AST.Program(p[1]) def p_segments(self, p): """segments : segments segment | segment""" segments = None segment = None if len(p) > 2: segments = p[1] segment = p[2] else: segment = p[1] p[0] = AST.Segments(segments, segment) # def p_declarations(self, p): # """declarations : declarations declaration # | """ # declarations = None # declaration = None # # if len(p) == 3: # declarations = p[1] # declaration = p[2] # # p[0] = AST.Declarations(p[1], p[2]) def p_segment(self, p): """segment : fundef | instruction | declaration""" p[0] = p[1] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ type = None inits = None error = None if len(p) > 3: type = p[1] inits = p[2] else: error = p[1] p[0] = AST.Declaration(type, inits, error) def p_inits(self, p): """inits : inits ',' init | init """ inits = None init = None if (len(p) > 2): inits = p[1] init = p[3] else: init = p[1] p[0] = AST.Inits(inits, init) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3], p.lineno(1)) # def p_instructions_opt(self, p): # """instructions_opt : instructions # | """ def p_instructions(self, p): """instructions : instructions instruction | instruction """ instructions = None instruction = None if len(p) > 2: instructions = p[1] instruction = p[2] else: instruction = p[1] p[0] = AST.Instructions(instructions, instruction) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ p[0] = AST.PrintInstruction(p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstruction(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3], p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ condition = p[3] instruction = p[5] else_instruction = None if (len(p) > 7): else_instruction = p[7] p[0] = AST.ChoiceInstruction(condition, instruction, else_instruction) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstruction(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstruction(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstruction(p[2], p.lineno(1)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstruction() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstruction() def p_compound_instr(self, p): """compound_instr : '{' segments '}' """ p[0] = AST.CompoundInstruction(p[2]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" if re.match(r"\d+(\.\d*)|\.\d+", p[1]): p[0] = AST.Float(p[1], p.lineno(1)) elif re.match(r"\d+", p[1]): p[0] = AST.Integer(p[1], p.lineno(1)) else: p[0] = AST.String(p[1], p.lineno(1)) def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: if isinstance(p[1], AST.Const): p[0] = p[1] else: p[0] = AST.Variable(p[1], p.lineno(1)) elif p[1] == '(' and p[3] == ')': p[0] = AST.ParenExpression(p[2]) elif p[2] == '(' and p[1] != '(': p[0] = AST.FunctionExpression(p[1], p[3], p.lineno(1)) else: p[0] = AST.BinExpr(p[2], p[1], p[3], p.lineno(2)) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ expr_list = None if len(p) > 1: expr_list = p[1] p[0] = AST.ExpressionList(expr_list, None) def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ expr_list = None expression = None if len(p) > 2: expr_list = p[1] expression = p[3] else: expression = p[1] p[0] = AST.ExpressionList(expr_list, expression) # def p_fundefs_opt(self, p): # """fundefs_opt : fundefs # | """ # # def p_fundefs(self, p): # """fundefs : fundefs fundef # | fundef """ # # gramatyka? # def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.Fundef(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ args_list = None if len(p) > 1: args_list = p[1] p[0] = AST.ArgumentsList(args_list, None) def p_args_list(self, p): """args_list : args_list ',' arg | arg """ args_list = None arg = None if len(p) > 2: args_list = p[1] arg = p[3] else: arg = p[1] p[0] = AST.ArgumentsList(args_list, arg) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Argument(p[1], p[2], p.lineno(1))
class Cparser(object): # Upon creatinon we create a user-defined scanner (scanner.py) def __init__(self): self.scanner = Scanner() self.scanner.build() # We get a list of tokens tokens = Scanner.tokens # We decide precedence of operators precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : declarations fundefs instructions""" # p[0] : p[1] p[2] p[3] if len(p[1].declarations) == 0: declarations = None else: declarations = p[1] if len(p[2].fundefs) == 0: fundefs = None else: fundefs = p[2] if len(p[3].instructions) == 0: instructions = None else: instructions = p[3] print AST.Program(declarations, fundefs, instructions) def p_declarations(self, p): """declarations : declarations declaration | """ # p[0] p[1] p[2] # If the it's the first production if len(p) == 3: # If there is only one declaration omit p[1] if p[1] is None: p[0] = AST.DeclarationList() # If there are more make them p[0] to recursively process else: p[0] = p[1] # Store the declaration from p[2] p[0].addDeclaration(p[2]) # If it's the second production else: p[0] = AST.DeclarationList() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ # p[0] p[1] p[2] ; # If the declaration is written properly if len(p) == 4: type = p[1] inits = p[2] p[0] = AST.Declaration(type, inits) # Multiple inits def p_inits(self, p): """inits : inits ',' init | init """ # If it's the first production if len(p) == 4: if p[1] is None: p[0] = None else: p[0] = p[1] p[0].addInit(p[3]) # If it's the second production else: p[0] = AST.InitList() p[0].addInit(p[1]) # Signel init def p_init(self, p): """init : ID '=' expression """ id = p[1] expr = p[3] p[0] = AST.Init(id, expr) # Block of instructions def p_instructions(self, p): """instructions : instructions instruction | instruction """ # if the first production if len(p) == 3: if p[1] is None: p[0] = AST.InstructionList else: p[0] = p[1] p[0].addInstruction(p[2]) # If the second productio else: p[0] = AST.InstructionList() p[0].addInstruction(p[1]) # A single instruction, here we have all different types of instructions def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" # We just assign the proper one and let next functions handle it p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ expr = p[2] p[0] = AST.PrintInstruction(expr) # What is a laveled instruction? def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ id = p[1] instruction = p[3] p[0] = AST.LabeledInstruction(id, instruction) def p_assignment(self, p): """assignment : ID '=' expression ';' """ id = p[1] expr = p[3] p[0] = AST.AssignmentInstruction(id, expr) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ condition = p[3] if_instruction = p[5] if len(p) < 8: else_instruction = None else: else_instruction = p[7] p[0] = AST.ChoiceInstruction(condition, if_instruction, else_instruction) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ condition = p[3] instruction = p[5] p[0] = AST.WhileInstruction(condition, instruction) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ instructions = p[2] condition = p[4] p[0] = AST.RepeatInstruction(instructions, condition) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ expression = p[2] p[0] = AST.ReturnInstruction(expression) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstruction() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstruction() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ if len(p[2].declarations) == 0: p[0] = AST.CompoundInstruction(None, p[3]) else: p[0] = AST.CompoundInstruction(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" p[0] = p[1] def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: value = p[1] p[0] = AST.Const(value) elif p[2] == "(" and p[1] != "(": funcName = p[1] args = p[3] p[0] = AST.InvocationExpression(funcName, args) elif p[1] == "(": p[0] = p[2] else: lhs = p[1] op = p[2] rhs = p[3] p[0] = AST.BinExpr(lhs, op, rhs) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ p[0] = None if len(p) == 1 else p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = AST.ExpressionList() if p[1] is None else p[1] p[0].addExpression(p[3]) else: p[0] = AST.ExpressionList() p[0].addExpression(p[1]) def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) == 3: p[0] = p[2] p[0].addFunction(p[1]) else: p[0] = AST.FunctionExpressionList() def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunctionExpression(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ p[0] = None if len(p) == 0 else p[1] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = AST.ArgumentList() if p[1] is None else p[1] p[0].addArgument(p[3]) else: p[0] = AST.ArgumentList() p[0].addArgument(p[1]) def p_arg(self, p): """arg : TYPE ID """ type = p[1] name = p[2] p[0] = AST.Argument(type, name)
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : podprogramy""" p[0] = AST.Program(p[1]) def p_podprogramy(self, p): """podprogramy : podprogramy podprogram | """ if len(p) == 3: podprogram = p[2] if p[1] == None: p[0] = AST.Podprogramy() else: p[0] = p[1] p[0].addPodprogram(podprogram) else: p[0] = AST.Podprogramy() def p_podprogram(self, p): """podprogram : declaration | fundef | instruction | """ p[0] = AST.Podprogram(p[1]) def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: type = p[1] inits = p[2] p[0] = AST.Declaration(type, inits) else: p[0] = AST.Error(p[1]) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: if p[1] == None: p[0] = AST.InitList(p[3]) else: p[0] = p[1] p[0].addInit(p[3]) else: p[0] = AST.InitList(p[1]) def p_init(self, p): """init : ID '=' expression """ id = p[1] exp = p[3] p[0] = AST.Init(id, exp, p.lineno(1)) def p_instructions(self, p): """instructions : instruction instructions | instruction """ if len(p) == 3: if p[2] == None: p[0] = AST.InstList(p[1]) else: p[0] = p[2] p[0].addInst(p[1]) else: p[0] = AST.InstList(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ data = p[2] p[0] = AST.PrtInst(data, p.lineno(1)) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ id = p[1] inst = p[3] p[0] = AST.LabInst(id, inst, p.lineno(1)) def p_assignment(self, p): """assignment : ID '=' expression ';' """ id = p[1] exp = p[3] p[0] = AST.AsgInst(id, exp, p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ cond = p[3] inst = p[5] if len(p) >= 8: alt = p[7] else: alt = None p[0] = AST.ChoiInst(cond, inst, alt) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ cond = p[3] inst = p[5] p[0] = AST.WhiInst(cond, inst) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ inst = p[3] cond = p[5] p[0] = AST.RepInst(inst, cond) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ exp = p[2] p[0] = AST.RetInst(exp, p.lineno(1)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.Continue(p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.Break(p.lineno(1)) #Przypilnowac by instruction nie zawieral fundefu #stworzyc unit -> declaration | instruction #i jeszcze stworzyc kolejna co by miala liste unitow. #poczatek zmian def p_units(self, p): """units : units unit | """ if len(p) == 3: unit = p[2] if p[1] == None: p[0] = AST.Units() else: p[0] = p[1] p[0].addUnit(unit) else: p[0] = AST.Units() def p_unit(self, p): """unit : declaration | instruction | """ p[0] = AST.Unit(p[1]) #koniec zmian def p_compound_instr(self, p): """compound_instr : '{' units '}' """ if len(p[2].children) == 0: p[0] = AST.CompInst(None, p.lineno(3)) else: p[0] = AST.CompInst(p[2], p.lineno(3)) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : integer | float | string""" p[0] = p[1] def p_integer(self, p): """integer : INTEGER""" p[0] = AST.Integer(p[1], p.lineno(1)) def p_float(self, p): """float : FLOAT""" p[0] = AST.Float(p[1], p.lineno(1)) def p_string(self, p): """string : STRING""" p[0] = AST.String(p[1], p.lineno(1)) def p_expression_id(self, p): """expression : ID""" p[0] = AST.Variable(p.lineno(1), p[1]) #H4X10R5K1 sposob na odronienie ID od const def p_expression(self, p): """expression : const | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: p[0] = p[1] elif p[2] == '(' and p[1] != '(': function_name = p[1] parameters = p[3] p[0] = AST.CallExp(function_name, parameters, p.lineno(1)) elif p[1] == '(': p[0] = p[2] else: left = p[1] operator = p[2] right = p[3] p[0] = AST.BinExpr(left, operator, right, p.lineno(2)) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = None def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: if p[1] == None: p[0] = AST.ExpList(p[3]) else: p[0] = p[1] p[0].addExp(p[3]) else: p[0] = AST.ExpList(p[1]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ type = p[1] name = p[2] parameters = p[4] body = p[6] p[0] = AST.Function(type, name, parameters, body, p.lineno(1)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = None def p_args_list(self, p): """args_list : arg ',' args_list | arg """ if len(p) == 4: if p[3] == None: p[0] = AST.ArgList(p[1]) else: p[0] = p[3] p[0].addArgToList(p[1]) else: p[0] = AST.ArgList(p[1]) def p_arg(self, p): """arg : TYPE ID """ type = p[1] name = p[2] p[0] = AST.Parameter(type, name, p.lineno(1))
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() self.errorsOccured = False tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') self.errorsOccured = True def p_program(self, p): """program : classdefs declarations fundefs instructions""" p[0] = AST.Program(p[1], p[2], p[3], p[4]) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) > 1: p[1].list.append(p[2]) p[0] = p[1] else: p[0] = AST.Declarations() def p_declaration(self, p): """declaration : TYPE inits ';' | id classinits ';' | error ';' """ if len(p) > 2: p[0] = AST.Declaration(p[1], p[2]) else: p[0] = p[1] def p_inits(self, p): """inits : inits ',' init | init """ if len(p) > 2: p[1].list.append(p[3]) p[0] = p[1] else: inits = AST.Inits() inits.list.append(p[1]) p[0] = inits def p_init(self, p): """init : id '=' expression """ p[0] = AST.Init(p[1], p[3]) def p_classinits(self, p): """classinits : classinits ',' classinit | classinit """ if len(p) > 2: p[1].list.append(p[3]) p[0] = p[1] else: classinits = AST.Classinits() classinits.list.append(p[1]) p[0] = classinits def p_classinit(self, p): """classinit : id """ p[0] = AST.Classinit(p[1]) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 2: instructions = AST.Instructions() instructions.list.append(p[1]) p[0] = instructions else: p[1].list.append(p[2]) p[0] = p[1] def p_instruction(self, p): """instruction : expression ';' | print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.PrintInstr(p[2]) def p_labeled_instr(self, p): """labeled_instr : id ':' instruction """ p[0] = AST.LabeledInstr(p[1], p[3]) def p_assignment(self, p): """assignment : access '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3]) def p_access(self, p): """access : id | id '.' id """ if len(p) == 2: access = AST.Access(p.lineno(1)) access.list.append(p[1]) p[0] = access else: access = AST.Access(p.lineno(1)) access.list.append(p[1]) access.list.append(p[3]) p[0] = access def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 6: p[0] = AST.ChoiceInstr(p[3], p[5], None) else: p[0] = AST.ChoiceInstr(p[3], p[5], p[7]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstr(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.Continue() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.Break() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}'""" p[0] = AST.CompoundInstr(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = AST.Condition(p[1]) def p_const(self, p): """const : integer | float | string""" p[0] = p[1] def p_integer(self, p): """integer : INTEGER""" p[0] = AST.Integer(p[1], p.lineno(1)) def p_float(self, p): """float : FLOAT""" p[0] = AST.Float(p[1], p.lineno(1)) def p_string(self, p): """string : STRING""" p[0] = AST.String(p[1][1:-1], p.lineno(1)) def p_id(self, p): """id : ID""" p[0] = AST.Id(p[1], p.lineno(1)) def p_expression(self, p): """expression : const | access | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | access '(' expr_list_or_empty ')' | access '(' error ')' """ if len(p) == 2: p[0] = p[1] elif p[1] == '(': p[0] = AST.ParExpr(p[2]) elif len(p) == 4: p[0] = AST.BinExpr(p[1], p[2], p[3]) else: p[0] = AST.FunExpr(p[1], p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 1: p[0] = AST.ExprList() else: p[0] = p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[1].list.append(p[3]) p[0] = p[1] else: toReturn = AST.ExprList() toReturn.list.append(p[1]) p[0] = toReturn def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) == 3: p[2].list.reverse() p[2].list.append(p[1]) p[2].list.reverse() p[0] = p[2] else: p[0] = AST.FunDefs() def p_fundef(self, p): """fundef : TYPE id '(' args_list_or_empty ')' compound_instr | id id '(' args_list_or_empty ')' compound_instr""" p[0] = AST.FunDef(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 1: p[0] = AST.ArgList() else: p[0] = p[1] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 2: argList = AST.ArgList() argList.list.append(p[1]) p[0] = argList else: p[1].list.append(p[3]) p[0] = p[1] def p_arg(self, p): """arg : TYPE id | id id""" p[0] = AST.Arg(p[1], p[2]) def p_classdefs(self, p): """classdefs : classdef classdefs | """ if len(p) == 3: p[2].list.reverse() p[2].list.append(p[1]) p[2].list.reverse() p[0] = p[2] else: p[0] = AST.ClassDefs() def p_classdef(self, p): """classdef : accessmodificator CLASS id classcontent | accessmodificator CLASS id EXTENDS id classcontent""" if len(p) < 7: p[0] = AST.ClassDef(p[1], p[3], None, p[4]) else: p[0] = AST.ClassDef(p[1], p[3], p[5], p[6]) def p_classcontent(self, p): """classcontent : '{' fielddefs ';' methoddefs '}' """ p[0] = AST.Classcontent(p[2], p[4]) def p_fielddefs(self, p): """fielddefs : fielddef fielddefs | """ if len(p) == 3: p[2].list.reverse() p[2].list.append(p[1]) p[2].list.reverse() p[0] = p[2] else: p[0] = AST.Fielddefs() def p_fielddef(self, p): """fielddef : accessmodificator declaration """ p[0] = AST.Fielddef(p[1], p[2]) def p_methoddefs(self, p): """methoddefs : methoddef methoddefs | """ if len(p) == 3: p[2].list.reverse() p[2].list.append(p[1]) p[2].list.reverse() p[0] = p[2] else: p[0] = AST.Methoddefs() def p_methoddef(self, p): """methoddef : accessmodificator fundef""" p[0] = AST.Methoddef(p[1], p[2]) def p_accessmodificator(self,p): """accessmodificator : PRIVATE | PROTECTED | PUBLIC""" p[0] = p[1]
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", "IFX"), ("nonassoc", "ELSE"), ("right", "="), ("left", "OR"), ("left", "AND"), ("left", "|"), ("left", "^"), ("left", "&"), ("nonassoc", "<", ">", "EQ", "NEQ", "LE", "GE"), ("left", "SHL", "SHR"), ("left", "+", "-"), ("left", "*", "/", "%"), ) def p_error(self, p): if p: print( "Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format( p.lineno, self.scanner.find_tok_column(p), p.type, p.value ) ) else: print("At end of input") def p_program(self, p): """program : parts """ p[0] = Program(p[1]) def p_parts(self, p): """parts : part parts | part """ if len(p) == 3: result = [] result.append(p[1]) result.extend(p[2].parts) p[0] = Parts(result) else: p[0] = Parts([p[1]]) def p_part(self, p): """part : fundef | instruction | declaration """ p[0] = p[1] def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: result = [] result.extend(p[1].declarations) result.append(p[2]) p[0] = Declarations(result) else: p[0] = Declarations([]) def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: p[0] = Declaration(p[1], p[2]) else: p[0] = Error(p[1]) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: result = [] result.extend(p[1].inits) result.append(p[3]) p[0] = Inits(result) else: p[0] = Inits([p[1]]) def p_init(self, p): """init : ID '=' expression """ p[0] = Init(p[1], p[3]) def p_instruction_opt(self, p): """instructions_opt : instructions | """ if len(p) == 2: p[0] = InstructionsOpt(p[1]) else: p[0] = InstructionsOpt([]) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: result = [] result.extend(p[1].instructions) result.append(p[2]) p[0] = Instructions(result) else: p[0] = Instructions([p[1]]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';'""" p[0] = PrintInstruction(p[2]) def p_print_error_instr(self, p): """print_instr : PRINT error ';' """ p[0] = PrintInstruction(p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = LabeledInstruction(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AssignementInstr(p[1], p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction """ if p[6] == "else": p[0] = IfElseInstruction(p[3], p[5], p[7]) else: p[0] = IfInstruction(p[3], p[5]) def p_choice_error(self, p): """choice_instr : IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ p[0] = Error(p[3]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction """ # todo: what does it mean error? p[0] = WhileInstruction(p[3], p[5]) def p_while_error(self, p): """while_instr : WHILE '(' error ')' instruction """ p[0] = Error(p[3]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = RepeatInstr(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = ReturnInstr(p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = ContinueInstr() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = BreakInstr() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions_opt '}' """ p[0] = CompoundInstr(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = Condition(p[1]) def p_const_integer(self, p): """const : INTEGER""" p[0] = Integer(p[1]) def p_const_float(self, p): """const : FLOAT""" p[0] = Float(p[1]) def p_const_string(self, p): """const : STRING""" p[0] = String(p[1]) def p_expression_const(self, p): """expression : const""" p[0] = ConstExpression(p[1]) def p_expression_id(self, p): """expression : ID""" p[0] = IdExpression(p[1]) def p_expression_mathop(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression""" if p[2] == "+": p[0] = AddExpression(p[1], p[3]) elif p[2] == "-": p[0] = SubtractExpression(p[1], p[3]) elif p[2] == "*": p[0] = MultiplyExpression(p[1], p[3]) elif p[2] == "/": p[0] = DivideExpression(p[1], p[3]) elif p[2] == "%": p[0] = ModuloExpression(p[1], p[3]) def p_expression_bitwise(self, p): """expression : expression '|' expression | expression '&' expression | expression '^' expression""" if p[2] == "|": p[0] = BinOrExpression(p[1], p[3]) elif p[2] == "&": p[0] = BinAndExpression(p[1], p[3]) elif p[2] == "^": p[0] = BinXorExpression(p[1], p[3]) def p_expression_bool(self, p): """expression : expression AND expression | expression OR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression""" if p[2] == "&&": p[0] = AndExpression(p[1], p[3]) elif p[2] == "||": p[0] = OrExpression(p[1], p[3]) elif p[2] == "==": p[0] = EqualExpression(p[1], p[3]) elif p[2] == "!=": p[0] = NotEqualExpression(p[1], p[3]) elif p[2] == "<": p[0] = LowerExpression(p[1], p[3]) elif p[2] == ">": p[0] = GreaterExpression(p[1], p[3]) elif p[2] == "<=": p[0] = LowerEqualExpression(p[1], p[3]) elif p[2] == ">=": p[0] = GreaterEqualExpression(p[1], p[3]) def p_expression_bracket(self, p): """expression : '(' expression ')'""" p[0] = BracketExpression(p[2]) def p_expression_error_bracket(self, p): """expression : '(' error ')'""" p[0] = Error(p[2]) def p_funcall_expression(self, p): """expression : ID '(' expr_list_or_empty ')' """ p[0] = FuncallExpression(p[1], p[3]) def p_funcall_error(self, p): """expression : ID '(' error ')' """ p[0] = Error(p[3]) def p_shift_expression(self, p): """expression : expression SHL expression | expression SHR expression""" if p[2] == ">>": p[0] = SHRExpression(p[1], p[3]) elif p[2] == "<<": p[0] = SHLExpression(p[1], p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = ExpressionListOrEmpty(p[1]) else: p[0] = Node() def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: result = [] result.extend(p[1].expressions) result.append(p[3]) p[0] = ExpressionList(result) else: p[0] = ExpressionList([p[1]]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = FunDef(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = ArgListOrEmpty(p[1]) else: p[0] = ArgListOrEmpty([]) def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: result = [] result.extend(p[1].args) result.append(p[3]) p[0] = ArgList(result) else: p[0] = ArgList([p[1]]) def p_arg(self, p): """arg : TYPE ID """ p[0] = Argument(p[1], p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : constructions | """ p[0] = AST.Program(p[1]) def p_constructions(self, p): """constructions : constructions construction | construction""" if len(p) > 1: if isinstance(p[1], AST.ConstructionList): p[1].add_to_list(p[2]) p[0] = p[1] else: p[0] = AST.ConstructionList() p[0].add_to_list(p[1]) def p_construction(self, p): """construction : declaration | fundef | instruction """ p[0] = AST.Construction(p[1]) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) > 1: if p[1] == None: p[1] = AST.DeclarationList() p[0] = p[1] if len(p) > 2: p[1].add_to_list(p[2]) else: p[0] = AST.DeclarationList() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ p[0] = AST.Declaration(p[1], p[2], p.lineno(1)) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) > 2: if p[1] == None: p[0] = AST.InitList() else: p[0] = p[1] p[0].add_to_list(p[3]) else: p[0] = AST.InitList() p[0].add_to_list(p[1]) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3], p.lineno(1)) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) > 2: if p[1] == None: p[1] = AST.InstructionList() p[1].add_to_list(p[2]) p[0] = p[1] else: p[0] = AST.InstructionList(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = AST.Instruction(p[1]) def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.PrintInstr("PRINT", p[2], p.lineno(1)) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstr(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3], p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 6: p[0] = AST.ChoiceInstr(p[3], p[5]) elif len(p) > 6: p[0] = AST.ChoiceInstr(p[3], p[5], p[7]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p[2], p[4], p.lineno(1)) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstr(p[2], p.lineno(1)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr(p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr(p.lineno(1)) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstr(p[2], p[3], p.lineno(4)) def p_condition(self, p): """condition : expression""" p[0] = AST.Condition(p[1]) def p_const(self, p): """const : INTEGER | FLOAT | STRING""" if re.match(r"\d+(\.\d*)|\.\d+", p[1]): p[0] = AST.Float(p[1], p.lineno(1)) elif re.match(r"\d+", p[1]): p[0] = AST.Integer(p[1], p.lineno(1)) elif re.match(r'\"([^\\\n]|(\\.))*?\"', p[1]): p[0] = AST.String(p[1], p.lineno(1)) def p_expression_id(self, p): """expression_id : ID""" p[0] = AST.Variable(p[1], p.lineno(1)) def p_expression(self, p): """expression : const | expression_id | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: p[0] = p[1] elif p[2] == "(" and p[1] != "(": p[0] = AST.Funcall(p[1], p[3], p.lineno(1)) elif len(p) == 4: if p[1] != '(': p[0] = AST.BinExpr(p[2], p[1], p[3], p.lineno(2)) else: p[0] = p[2] def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ p[0] = p[1] if len(p) >= 2 else AST.ExpressionList() def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) > 2: if p[1] is None: p[1] = AST.ExpressionList() p[0] = p[1] p[0].add_to_list(p[3]) else: p[0] = AST.ExpressionList() p[0].add_to_list(p[1]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.Fundef(p[2], p[4], p[6], p[1], p.lineno(1)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ p[0] = p[1] if len(p) > 1 else AST.ArgList(line=p.lineno(0)) def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) > 2: if p[1] is None: p[1] = AST.ArgList() p[0] = p[1] p[0].add_to_list(p[3]) else: p[0] = AST.ArgList() p[0].add_to_list(p[1]) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p[2], p[1], p.lineno(2))
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print("Unexpected end of input") def p_program(self, p): """program : blocks""" p[0] = p[1] def p_blocks(self, p): """blocks : blocks block | """ if len(p) == 3: p[1].children.append(p[2]) p[0] = p[1] else: p[0] = AST.Blocks() def p_block(self, p): """block : declaration | fundef | instruction""" p[0] = p[1] def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: p[1].children.append(p[2]) p[0] = p[1] else: p[0] = AST.Declarations() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: p[0] = AST.Declaration(p[1], p[2]) # else: # p[0] = p[1] def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[1].children.append(p[3]) p[0] = p[1] else: p[0] = AST.Inits() p[0].children.append(p[1]) def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p[1], p[3], p.lineno(1)) def p_instructions_opt(self, p): """instructions_opt : instructions | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.Instructions() def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[1].children.append(p[2]) p[0] = p[1] else: p[0] = AST.Instructions() p[0].children.append(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr | expression ';' """ p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expr_list ';' | PRINT error ';' """ if len(p) == 4: p[0] = AST.InstructionPrint(p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p[1], p[3], p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 8: p[0] = AST.InstructionIf(p[3], p[5], p[7]) else: p[0] = AST.InstructionIf(p[3], p[5], None) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.InstructionWhile(p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.Repeat(p[2], p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.Return(p[2], p.lineno(1)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.Continue(p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.Break(p.lineno(1)) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions_opt '}' """ p[0] = AST.CompoundInstruction(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" if re.match(r"\d+(\.\d*)|\.\d+", p[1]): p[0] = AST.Float(p[1]) elif re.match(r"\d+", p[1]): p[0] = AST.Integer(p[1]) else: p[0] = AST.String(p[1]) def p_expression(self, p): """expression : const | ID | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: if isinstance(p[1], AST.Const): p[0] = p[1] else: p[0] = AST.Variable(p[1], p.lineno(1)) elif p[1] == '(': p[0] = p[2] elif p[2] == '(': p[0] = AST.FunCall(p[1], p[3], p.lineno(1)) else: p[0] = AST.BinExpr(p[2], p[1], p[3], p.lineno(2)) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.ExpressionList() def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[1].children.append(p[3]) p[0] = p[1] else: p[0] = AST.ExpressionList() p[0].children.append(p[1]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunDef(p[1], p[2], p[4], p[6], p.lineno(1)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = AST.ArgList() def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[1].children.append(p[3]) p[0] = p[1] else: p[0] = AST.ArgList() p[0].children.append(p[1]) def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p[1], p[2], p.lineno(1))
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" p[0] = AST.Program(p.lineno(1), p[1], p[2], p[3]) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: p[0] = p[1] + [p[2]] elif len(p) == 1: p[0] = [] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: p[0] = [AST.Declaration(p.lineno(1), p[1], p[2])] elif len(p) == 3: pass def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[0] = p[1] + [p[3]] elif len(p) == 2: p[0] = [p[1]] def p_init(self, p): """init : ID '=' expression """ p[0] = AST.Init(p.lineno(1), p[1], p[3]) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[0] = p[1] + [p[2]] elif len(p) == 2: p[0] = [p[1]] def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = AST.PrintInstr(p.lineno(1), p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = AST.LabeledInstr(p.lineno(1), p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = AST.Assignment(p.lineno(1), p[1], p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' error ')' instruction %prec IFX """ p[0] = AST.ChoiceInstr(p.lineno(1), p[3], p[5]) def p_choice_with_else_instr(self, p): """choice_instr : IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction ELSE instruction """ p[0] = AST.ChoiceInstr(p.lineno(1), p[3], p[5], p[7]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = AST.WhileInstr(p.lineno(1), p[3], p[5]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = AST.RepeatInstr(p.lineno(1), p[4], p[2]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = AST.ReturnInstr(p.lineno(1), p[2]) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstr(p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstr(p.lineno(1)) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = AST.CompoundInstr(p.lineno(1), p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = AST.Condition(p.lineno(1), p[1]) def p_const_int(self, p): """const : INTEGER""" p[0] = AST.Integer(p.lineno(1), p[1]) def p_const_float(self, p): """const : FLOAT""" p[0] = AST.Float(p.lineno(1), p[1]) def p_const_string(self, p): """const : STRING""" p[0] = AST.String(p.lineno(1), p[1]) def p_expr_binop(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression""" p[0] = AST.BinExpr(p.lineno(1), p[2], p[1], p[3]) def p_expr_group(self, p): """expression : '(' expression ')' | '(' error ')' """ p[0] = p[2] def p_expr_const(self, p): """expression : const""" p[0] = p[1] def p_expr_id(self, p): """expression : ID""" p[0] = AST.Variable(p.lineno(1), None, p[1]) def p_expr_funcall(self, p): """expression : ID '(' expr_list_or_empty ')' | ID '(' error ')' """ p[0] = AST.Funcall(p.lineno(1), p[1], p[3]) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 2: p[0] = p[1] elif len(p) == 1: p[0] = [] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = p[1] + [p[3]] elif len(p) == 2: p[0] = [p[1]] def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) == 3: p[0] = [p[1]] + p[2] elif len(p) == 1: p[0] = [] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = [AST.Fundef(p.lineno(1), p[1], p[2], p[4], p[6])] def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 2: p[0] = p[1] elif len(p) == 1: p[0] = [] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = p[1] + [p[3]] elif len(p) == 2: p[0] = [p[1]] def p_arg(self, p): """arg : TYPE ID """ p[0] = AST.Arg(p.lineno(1), p[1], p[2])
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", 'IFX'), ("nonassoc", 'ELSE'), ("right", '='), ("left", 'OR'), ("left", 'AND'), ("left", '|'), ("left", '^'), ("left", '&'), ("nonassoc", '<', '>', 'EQ', 'NEQ', 'LE', 'GE'), ("left", 'SHL', 'SHR'), ("left", '+', '-'), ("left", '*', '/', '%'), ) def p_error(self, p): if p: print("Syntax error at line {0}, column {1}: LexToken({2}, '{3}')". format(p.lineno, self.scanner.find_tok_column(p), p.type, p.value)) else: print('At end of input') def p_program(self, p): """program : declarations fundefs instructions""" p[0] = Program(p[1], p[2], p[3], p.lineno(1)) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 1: p[0] = [] else: p[0] = p[1] + [p[2]] def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ p[0] = Declaration(p[1], p[2], p.lineno(1)) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[3]] def p_init(self, p): """init : ID '=' expression """ p[0] = Init(p[1], p[3], p.lineno(1)) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ p[0] = Print(p[2], p.lineno(1)) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = Labeled(p[1], p[3], p.lineno(1)) def p_assignment(self, p): """assignment : ID '=' expression ';' """ p[0] = Assignment(p[1], p[3], p.lineno(1)) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ if len(p) == 8: p[0] = IfElse(p[3], p[5], p[7], p.lineno(1)) else: p[0] = If(p[3], p[5], p.lineno(1)) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ p[0] = While(p[3], p[5], p.lineno(1)) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = Repeat(p[2], p[4], p.lineno(1)) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = Return(p[2], p.lineno(1)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = Continue(p.lineno(1)) def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = Break(p.lineno(1)) def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = CompoundInstructions(p[2], p[3], p.lineno(1)) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : integer | float | string""" p[0] = p[1] def p_integer(self, p): """integer : INTEGER""" p[0] = Integer(p[1], p.lineno(1)) def p_float(self, p): "float : FLOAT" p[0] = Float(p[1], p.lineno(1)) def p_string(self, p): "string : STRING" p[0] = String(p[1], p.lineno(1)) def p_binary_expression(self, p): """binary_expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression""" p[0] = BinExpr(p[2], p[1], p[3], p.lineno(2)) def p_funcall(self, p): """funcall : ID '(' expr_list_or_empty ')' | ID '(' error ')' """ p[0] = Funcall(p[1], p[3], p.lineno(1)) def p_expression(self, p): """expression : const | name | binary_expression | '(' expression ')' | '(' error ')' | funcall""" if len(p) == 4: p[0] = p[2] elif len(p) == 2: p[0] = p[1] def p_name(self, p): """name : ID""" p[0] = Variable(p[1], p.lineno(1)) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ if len(p) == 1: p[0] = [] else: p[0] = p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[3]] def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) == 1: p[0] = [] else: p[0] = [p[1]] + p[2] def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = Fundef(p[2], p[1], p[4], p[6], p.lineno(1)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if len(p) == 1: p[0] = [] else: p[0] = p[1] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[3]] def p_arg(self, p): """arg : TYPE ID """ p[0] = Argument(p[1], p[2], p.lineno(1))
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", "IFX"), ("nonassoc", "ELSE"), ("right", "="), ("left", "OR"), ("left", "AND"), ("left", "|"), ("left", "^"), ("left", "&"), ("nonassoc", "<", ">", "EQ", "NEQ", "LE", "GE"), ("left", "SHL", "SHR"), ("left", "+", "-"), ("left", "*", "/", "%"), ) def p_error(self, p): if p: print( "Syntax error at line {0}, column {1}: LexToken({2}, '{3}')".format( p.lineno, self.scanner.find_tok_column(p), p.type, p.value ) ) else: print("At end of input") def p_program(self, p): """program : declarations fundefs instructions""" declarations = None if len(p[1].children) == 0 else p[1] fundefs = None if len(p[2].children) == 0 else p[2] p[0] = AST.Program(declarations, fundefs, p[3]) def p_declarations(self, p): """declarations : declarations declaration | """ if len(p) == 3: p[0] = AST.DeclarationList() if p[1] is None else p[1] p[0].addDeclaration(p[2]) else: p[0] = AST.DeclarationList() def p_declaration(self, p): """declaration : TYPE inits ';' | error ';' """ if len(p) == 4: type = p[1] inits = p[2] p[0] = AST.Declaration(type, inits) def p_inits(self, p): """inits : inits ',' init | init """ if len(p) == 4: p[0] = AST.InitList() if p[1] is None else p[1] p[0].addInit(p[3]) else: p[0] = AST.InitList() p[0].addInit(p[1]) def p_init(self, p): """init : ID '=' expression """ id = p[1] expr = p[3] p[0] = AST.Init(p.lineno(1), id, expr) def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[0] = AST.InstructionList() if p[1] is None else p[1] p[0].addInstruction(p[2]) else: p[0] = AST.InstructionList() p[0].addInstruction(p[1]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' | PRINT error ';' """ expr = p[2] p[0] = AST.PrintInstruction(p.lineno(1), expr) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ id = p[1] instruction = p[3] p[0] = AST.LabeledInstruction(p.lineno(1), id, instruction) def p_assignment(self, p): """assignment : ID '=' expression ';' """ id = p[1] expr = p[3] p[0] = AST.AssignmentInstruction(p.lineno(1), id, expr) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX | IF '(' condition ')' instruction ELSE instruction | IF '(' error ')' instruction %prec IFX | IF '(' error ')' instruction ELSE instruction """ condition = p[3] action = p[5] alternateAction = None if len(p) < 8 else p[7] p[0] = AST.ChoiceInstruction(condition, action, alternateAction) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction | WHILE '(' error ')' instruction """ condition = p[3] instruction = p[5] p[0] = AST.WhileInstruction(condition, instruction) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ instructions = p[2] condition = p[4] p[0] = AST.RepeatInstruction(instructions, condition) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ expression = p[2] p[0] = AST.ReturnInstruction(p.lineno(1), expression) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = AST.ContinueInstruction() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = AST.BreakInstruction() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ if len(p[2].children) == 0: p[0] = AST.CompoundInstruction(p[2], p[3]) else: p[0] = AST.CompoundInstruction(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const(self, p): """const : INTEGER | FLOAT | STRING""" if re.match(r"\d+(\.\d*)|\.\d+", p[1]): p[0] = AST.Float(p.lineno(1), p[1]) elif re.match(r"\d+", p[1]): p[0] = AST.Integer(p.lineno(1), p[1]) else: p[0] = AST.String(p.lineno(1), p[1]) def p_expression_id(self, p): """expression : ID""" p[0] = AST.Variable(p.lineno(1), p[1]) def p_expression(self, p): """expression : const | expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression | '(' expression ')' | '(' error ')' | ID '(' expr_list_or_empty ')' | ID '(' error ')' """ if len(p) == 2: p[0] = p[1] elif p[1] == "(": interior = p[2] p[0] = AST.GroupedExpression(interior) elif p[2] == "(": funcName = p[1] args = p[3] p[0] = AST.InvocationExpression(p.lineno(1), funcName, args) else: lhs = p[1] op = p[2] rhs = p[3] p[0] = AST.BinExpr(p.lineno(2), lhs, op, rhs) def p_expr_list_or_empty(self, p): """expr_list_or_empty : expr_list | """ p[0] = None if len(p) == 1 else p[1] def p_expr_list(self, p): """expr_list : expr_list ',' expression | expression """ if len(p) == 4: p[0] = AST.ExpressionList() if p[1] is None else p[1] p[0].addExpression(p[3]) else: p[0] = AST.ExpressionList() p[0].addExpression(p[1]) def p_fundefs(self, p): """fundefs : fundef fundefs | """ if len(p) == 3: p[0] = p[2] p[0].addFunction(p[1]) else: p[0] = AST.FunctionExpressionList() def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = AST.FunctionExpression(p[1], p[2], p[4], p[6]) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ p[0] = None if len(p) == 0 else p[1] def p_args_list(self, p): """args_list : args_list ',' arg | arg """ if len(p) == 4: p[0] = AST.ArgumentList() if p[1] is None else p[1] p[0].addArgument(p[3]) else: p[0] = AST.ArgumentList() p[0].addArgument(p[1]) def p_arg(self, p): """arg : TYPE ID """ type = p[1] name = p[2] p[0] = AST.Argument(p.lineno(1), type, name)
class Cparser(object): def __init__(self): self.scanner = Scanner() self.scanner.build() tokens = Scanner.tokens precedence = ( ("nonassoc", "IFX"), ("nonassoc", "ELSE"), ("right", "="), ("left", "OR"), ("left", "AND"), ("left", "|"), ("left", "^"), ("left", "&"), ("nonassoc", "<", ">", "EQ", "NEQ", "LE", "GE"), ("left", "SHL", "SHR"), ("left", "+", "-"), ("left", "*", "/", "%"), ) def handle_error(self, where, p): print ( "Syntax error in %s at line %d, column %d, at token LexToken(%s, '%s')" % (where, p.lineno, self.scanner.find_tok_column(p), p.type, p.value) ) def p_error(self, p): if not p: print "Unexpected end of input" else: # let the productions handle the error on their own pass def p_program(self, p): """program : ext_declarations fundefs instructions""" p[0] = Program(p[1], p[2], p[3], pos(p)) p[0].printTree(0) def p_ext_declarations(self, p): """ext_declarations : declarations""" p[0] = p[1] def p_declarations(self, p): """declarations : declarations declaration""" if p[2]: p[0] = DeclarationList(p[1].decls + [p[2]]) else: # error p[0] = p[1] def p_declarations_single(self, p): """declarations : declaration""" if p[1]: p[0] = DeclarationList([p[1]]) else: # error p[0] = DeclarationList([]) def p_declaration_blank(self, p): """declarations : """ p[0] = DeclarationList([]) def p_declaration_fundef(self, p): """declaration : fundefs""" p[0] = p[1] def p_declaration(self, p): """declaration : TYPE inits ';' """ p[0] = Declaration(p[1], p[2], pos(p)) def p_declaration_error(self, p): """declaration : error ';' """ self.handle_error("declaration", p[1]) def p_inits(self, p): """inits : inits ',' init""" p[0] = InitList(p[1].inits + [p[3]]) def p_inits_single(self, p): """inits : init""" p[0] = InitList([p[1]]) def p_init(self, p): """init : ID '=' expression """ p[0] = Init(p[1], p[3]) def p_instructions(self, p): """instructions : instructions instruction""" if p[2]: p[0] = InstructionList(p[1].instrs + [p[2]]) else: p[0] = p[1] def p_instructions_single(self, p): """instructions : instruction """ if p[1]: p[0] = InstructionList([p[1]]) else: p[0] = InstructionList([]) def p_instruction(self, p): """instruction : print_instr | labeled_instr | assignment | choice_instr | while_instr | repeat_instr | return_instr | break_instr | continue_instr | compound_instr""" p[0] = p[1] def p_print_instr(self, p): """print_instr : PRINT expression ';' """ p[0] = PrintInstruction(p[2]) def p_print_error(self, p): """print_instr : PRINT error ';' """ self.handle_error("print instruction", p[2]) def p_labeled_instr(self, p): """labeled_instr : ID ':' instruction """ p[0] = LabeledInstruction(p[1], p[3]) def p_assignment(self, p): """assignment : ID '=' expression ';' """ if p[3]: p[0] = Assignment(p[1], p[3], pos(p)) else: # error pass def p_assignment_error(self, p): """assignment : ID '=' error ';' """ self.handle_error("assignment", p[3]) def p_choice_instr(self, p): """choice_instr : IF '(' condition ')' instruction %prec IFX""" p[0] = ChoiceInstruction(p[3], p[5]) def p_choice_instr_else(self, p): """choice_instr : IF '(' condition ')' instruction ELSE instruction""" p[0] = ChoiceInstruction(p[3], p[5], p[7]) def p_choice_instr_error(self, p): """choice_instr : IF '(' error ')' instruction %prec IFX""" self.handle_error("if condition", p[3]) def p_choice_instr_else_error(self, p): """choice_instr : IF '(' error ')' instruction ELSE instruction""" self.handle_error("if condition", p[3]) def p_while_instr(self, p): """while_instr : WHILE '(' condition ')' instruction""" p[0] = WhileInstruction(p[1], p[3], p[5]) def p_while_error(self, p): """while_instr : WHILE '(' error ')' instruction """ self.handle_error("while instruction", p[3]) def p_repeat_instr(self, p): """repeat_instr : REPEAT instructions UNTIL condition ';' """ p[0] = RepeatInstruction(p[1], p[2], p[3], p[4]) def p_repeat_error(self, p): """repeat_instr : REPEAT instructions UNTIL error ';' """ self.handle_error("repeat instruction", p[4]) def p_return_instr(self, p): """return_instr : RETURN expression ';' """ p[0] = ReturnInstruction(p[2], pos(p)) def p_continue_instr(self, p): """continue_instr : CONTINUE ';' """ p[0] = ContinueInstruction() def p_break_instr(self, p): """break_instr : BREAK ';' """ p[0] = BreakInstruction() def p_compound_instr(self, p): """compound_instr : '{' declarations instructions '}' """ p[0] = CompoundInstructions(p[2], p[3]) def p_condition(self, p): """condition : expression""" p[0] = p[1] def p_const_integer(self, p): """const : INTEGER""" p[0] = Integer(p[1]) def p_const_float(self, p): """const : FLOAT""" p[0] = Float(p[1]) def p_const_string(self, p): """const : STRING""" p[0] = String(p[1]) def p_expression_const(self, p): """expression : const""" p[0] = p[1] def p_expression_id(self, p): "expression : ID" p[0] = Variable(p[1], pos(p)) def p_expression_brackets(self, p): "expression : '(' expression ')'" p[0] = p[2] def p_expression_brackets_error(self, p): "expression : '(' error ')'" self.handle_error("expression (bracket)", p[2]) def p_expression_fun_call(self, p): "expression : ID '(' expr_list_or_empty ')'" p[0] = FunctionCall(p[1], p[3], pos(p)) def p_expression_fun_call_error(self, p): "expression : ID '(' error ')'" self.handle_error("function call", p[3]) def p_expression_binary_op(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression '%' expression | expression '|' expression | expression '&' expression | expression '^' expression | expression AND expression | expression OR expression | expression SHL expression | expression SHR expression | expression EQ expression | expression NEQ expression | expression '>' expression | expression '<' expression | expression LE expression | expression GE expression""" p[0] = BinExpr(p[1], p[2], p[3], pos(p)) def p_expr_list_non_empty(self, p): """expr_list_or_empty : expr_list""" p[0] = p[1] def p_expr_list_empty(self, p): """expr_list_or_empty : """ p[0] = ExprList([]) def p_expr_list(self, p): """expr_list : expr_list ',' expression""" p[0] = ExprList(p[1].exprs + [p[3]]) def p_expr_list_single(self, p): """expr_list : expression""" p[0] = ExprList([p[1]]) # def p_fundefs(self, p): # """fundefs : fundefs fundef # | fundef """ # if p[2]: # p[0] = FunctionDefList(p[1].fundefs + [ p[2] ]) # else: # p[0] = FunctionDefList([ p[1] ]) def p_fundefs(self, p): """fundefs : fundefs fundef""" p[0] = FunctionDefList(p[1].fundefs + [p[2]]) def p_fundefs_single(self, p): """fundefs : fundef""" p[0] = FunctionDefList([p[1]]) def p_fundefs_empty(self, p): """fundefs : """ p[0] = FunctionDefList([]) def p_fundef(self, p): """fundef : TYPE ID '(' args_list_or_empty ')' compound_instr """ p[0] = FunctionDef(p[1], p[2], p[4], p[6], pos(p)) def p_args_list_or_empty(self, p): """args_list_or_empty : args_list | """ if p[1]: p[0] = p[1] else: p[0] = ArgsList([]) # def p_args_list(self, p): # """args_list : args_list ',' arg # | arg """ # if p[3]: # p[0] = ArgsList(p[1].args + [ p[3] ]) # else: # p[0] = ArgsList([ p[1] ]) def p_args_list(self, p): """args_list : args_list ',' arg""" p[0] = ArgsList(p[1].args + [p[3]]) def p_args_list_single(self, p): """args_list : arg""" p[0] = ArgsList([p[1]]) def p_arg(self, p): """arg : TYPE ID """ p[0] = Arg(p[1], p[2])