def p_def_class(p): """ class_def : CLASS TYPE_ID LBRACE feature_list RBRACE SEMICOLON | CLASS TYPE_ID INHERITS TYPE_ID LBRACE feature_list RBRACE SEMICOLON """ if len(p) == 7: p[0] = ast.ClassDeclarationNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(2)), p[2], p[4]) else: p[0] = ast.ClassDeclarationNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(2)), p[2], p[6], p[4])
def p_branch_list(p): """ branch_list : OBJECT_ID COLON type ACTION expr SEMICOLON | OBJECT_ID COLON type ACTION expr SEMICOLON branch_list """ if len(p) == 7: p[0] = [ast.BranchNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1], p[3], p[5])] else: p[0] = [ast.BranchNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1], p[3], p[5])] + p[7]
def p_attr_def(p): """ attr_def : OBJECT_ID COLON type | OBJECT_ID COLON type ASSIGN expr """ if len(p) == 4: p[0] = ast.AttrDeclarationNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1], p[3]) else: p[0] = ast.AttrDeclarationNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1], p[3], p[5])
def p_func_call(p): """ func_call : atom DOT OBJECT_ID LPAREN arg_list RPAREN | OBJECT_ID LPAREN arg_list RPAREN | atom AT TYPE_ID DOT OBJECT_ID LPAREN arg_list RPAREN """ if len(p) == 7: p[0] = ast.CallNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1], p[3], p[5]) elif len(p) == 5: p[0] = ast.CallNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), None, p[1], p[3]) elif len(p) == 9: p[0] = ast.CallNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1], p[5], p[7], p[3])
def p_factor(p): """ factor : ISVOID factor | INT_COMP factor | atom """ first_token = p.slice[1].type if len(p) > 1 else None if first_token == 'ISVOID': p[0] = ast.IsVoidNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[2]) elif first_token == 'INT_COMP': p[0] = ast.IntCompNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[2]) else: p[0] = p[1]
def p_term(p): """ term : term MULT factor | term DIV factor | factor """ operator = p.slice[2].type if len(p) > 2 else None if operator is None: p[0] = p[1] elif operator == 'MULT': p[0] = ast.StarNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) elif operator == 'DIV': p[0] = ast.DivNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3])
def p_arith(p): """ arith : arith PLUS term | arith MINUS term | term """ operator = p.slice[2].type if len(p) > 2 else None if operator is None: p[0] = p[1] elif operator == 'PLUS': p[0] = ast.PlusNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) elif operator == 'MINUS': p[0] = ast.MinusNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3])
def p_open_expr(p): """ open_expr : LET let_var_list IN expr | OBJECT_ID ASSIGN expr | NOT expr """ first_token = p.slice[1].type if len(p) > 1 else None if first_token == 'LET': p[0] = ast.LetNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[2], p[4]) elif first_token == 'OBJECT_ID': p[0] = ast.AssignNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1], p[3]) elif first_token == 'NOT': p[0] = ast.NotNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[2])
def p_open_expr_lvl3(p): """ open_expr_lvl3 : ISVOID open_expr_lvl3 | INT_COMP open_expr_lvl3 | open_expr """ first_token = p.slice[1].type if len(p) > 1 else None if first_token == 'ISVOID': p[0] = ast.IsVoidNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[2]) elif first_token == 'INT_COMP': p[0] = ast.IntCompNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1]) else: p[0] = p[1]
def p_open_expr_lvl2(p): """ open_expr_lvl2 : term MULT open_expr_lvl3 | term DIV open_expr_lvl3 | open_expr_lvl3 """ operator = p.slice[2].type if len(p) > 2 else None if operator == 'MULT': p[0] = ast.StarNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) elif operator == 'DIV': p[0] = ast.DivNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) else: p[0] = p[1]
def p_open_expr_lvl1(p): """ open_expr_lvl1 : arith PLUS open_expr_lvl2 | arith MINUS open_expr_lvl2 | open_expr_lvl2 """ operator = p.slice[2].type if len(p) > 2 else None if operator == 'PLUS': p[0] = ast.PlusNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) elif operator == 'MINUS': p[0] = ast.MinusNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) else: p[0] = p[1]
def p_comparer(p): """ comparer : comparer LT arith | comparer LTEQ arith | comparer EQ arith | arith """ operator = p.slice[2].type if len(p) > 2 else None if operator == 'LT': p[0] = ast.LessNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) elif operator == 'LTEQ': p[0] = ast.LessEqualNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) elif operator == 'EQ': p[0] = ast.EqualNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) else: p[0] = p[1]
def p_error(p): if p is None: line_no = find_last_line(input_text) errors.append('(%s, 0) - SyntacticError: ERROR at or near EOF' % line_no) else: col_no = find_column(p.lexer.lexdata, p.lexpos) errors.append(('(%s, %s) - SyntacticError: ERROR at or near "%s"'.format(p) % (p.lineno, col_no, p.value)))
def p_expr(p): """ expr : comparer LT open_expr_lvl1 | comparer LTEQ open_expr_lvl1 | comparer EQ open_expr_lvl1 | open_expr_lvl1 | comparer """ operator = p.slice[2].type if len(p) > 2 else None if operator == 'LT': p[0] = ast.LessNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) elif operator == 'LTEQ': p[0] = ast.LessEqualNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) elif operator == 'EQ': p[0] = ast.EqualNode(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2)), p[1], p[3]) else: p[0] = p[1]
def p_error(self, p): self.errors = True if p: self.print_error(p) else: error_text = SyntaticError.ERROR % 'EOF' column = find_column(self.lexer.lexer, self.lexer.lexer) line = self.lexer.lexer.lineno print(SyntaticError(error_text, line, column - 1))
def t_STRING_newline(t): r"\n" if not t.lexer.string_backslash: # FATAL ERROR errors.append( "(%s, %s) - LexicographicError: STRING ERROR NON-ESCAPED NEWLINE CHARACTER" % (t.lexer.lineno, find_column(t.lexer.lexdata, t.lexpos))) t.lexer.pop_state() else: t.lexer.string_backslash = False t.lexer.lineno += 1
def p_atom(p): """ atom : INTEGER | OBJECT_ID | STRING | BOOL | LPAREN expr RPAREN | NEW TYPE_ID | IF expr THEN expr ELSE expr FI | WHILE expr LOOP expr POOL | LBRACE expr_list RBRACE | CASE expr OF branch_list ESAC | func_call """ first_token = p.slice[1].type if len(p) > 1 else None second_token = p.slice[2].type if len(p) > 2 else None if first_token == 'INTEGER': p[0] = ast.ConstantNumNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1]) elif first_token == 'OBJECT_ID' and second_token is None: p[0] = ast.VariableNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1]) elif first_token == 'STRING': p[0] = ast.StringNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1]) elif first_token == 'BOOL': p[0] = ast.BoolNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1]) elif first_token == 'LPAREN': p[0] = p[2] elif first_token == 'NEW': p[0] = ast.InstantiateNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[2]) elif first_token == 'IF': p[0] = ast.ConditionalNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[2], p[4], p[6]) elif first_token == 'WHILE': p[0] = ast.LoopNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[2], p[4]) elif first_token == 'LBRACE': p[0] = ast.BlockNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[2]) elif first_token == 'CASE': p[0] = ast.CaseNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[2], p[4]) elif first_token == 'func_call': p[0] = p[1]
def t_error(t): col = find_column(t.lexer.lexdata, t.lexpos) errors.append('(%s, %s) - LexicographicError: ILLEGAL CHARACTER "%s"' % (t.lexer.lineno, col, t.value[0])) t.lexer.skip(1)
def t_COMMENT_eof(t): if t.lexer.current_state(): col = find_column(t.lexer.lexdata, t.lexpos) errors.append("(%s, %s) - LexicographicError: EOF in comment" % (t.lexer.lineno, col))
def t_COMMENT_error(t): col = find_column(t.lexer.lexdata, t.lexpos) errors.append("(%s, %s) - LexicographicError: COMMENT ERROR " % (t.lexer.lineno, col)) t.lexer.skip(1)
def t_STRING_eof(t): if t.lexer.current_state(): errors.append( "(%s, %s) - LexicographicError: EOF ERROR IN STRING STATE" % (t.lexer.lineno, find_column(t.lexer.lexdata, t.lexpos)))
def t_STRING_error(t): col = find_column(t.lexer.lexdata, t.lexpos) errors.append("(%s, %s) - LexicographicError: ERROR %s " % (t.lexer.lineno, col, t.value[0])) t.lexer.skip(1)
def t_STRING_null(t): r"\0" errors.append("(%s, %s) - LexicographicError: STRING NULL ERROR" % (t.lexer.lineno, find_column(t.lexer.lexdata, t.lexpos))) t.lexer.skip(1)
def p_meth_def(p): """ meth_def : OBJECT_ID LPAREN param_list RPAREN COLON type LBRACE expr RBRACE """ p[0] = ast.FuncDeclarationNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1], p[3], p[6], p[8])
def p_program(p): """ program : class_list """ p[0] = ast.ProgramNode(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1)), p[1]) pass