Example #1
0
class Parser:
    tokens = Lexer().tokens

    def __init__(self):
        self.tempCount = 0
        self.quad = 0
        self.codeGenerator = CodeGenerator()
    
    # part 1 ----------------------------------------------------------------------------------------
    def p_program(self, p):
        "program : declist MAIN LRB RRB block"
        self.codeGenerator.generate_main_code(p, self.next_quad(), self.next_quad())

    def p_declist_empty(self, p):
        """
        declist :
        """
        self.codeGenerator.generate_declist_empty_code(p)
    
    def p_declist(self, p):
        """
        declist : declist dec
        """
        self.codeGenerator.generate_declist_code(p, self.next_quad())
        

    def p_dec_vardec(self, p):
        """
        dec : vardec
        """
        self.codeGenerator.generate_dec_vardec_code(p)

    def p_vardec(self, p):
        """
        vardec : idlist COLON type SEMICOLON
        """
        self.codeGenerator.generate_vardec_code(p)

    def p_type(self, p):
        """
        type : INTEGER
        type : FLOAT
        type : BOOLEAN
        """
        pass

    def p_iddec_ID(self, p):
        """
        iddec : ID
        """
        self.codeGenerator.generate_iddec_ID_code(p)


    def p_iddec_assign(self, p):
        """
        iddec : ID ASSIGN exp
        """
        self.codeGenerator.generate_iddec_assign_code(p, self.next_quad(), self.next_quad(), self.next_quad())

    def p_iddec_array(self, p):
        """
        iddec : ID LSB exp RSB
        """
        self.codeGenerator.generate_iddec_array_code(p, self.new_temp())

    def p_idlist(self, p):
        """
        idlist : iddec
        """
        self.codeGenerator.generate_idlist_code(p)

    def p_idlist_comma(self, p):
        """
        idlist : idlist COMMA iddec
        """
        self.codeGenerator.generate_idlist_comma_code(p, self.next_quad())

    def p_exp_assign(self, p):
        "exp : ID ASSIGN exp"
        self.codeGenerator.generate_exp_assign_code(p, self.next_quad(), self.next_quad(), self.next_quad())

    def p_exp_arithmetic(self, p):
        """
        exp : exp SUM exp
        exp : exp SUB exp
        exp : exp DIV exp
        exp : exp MOD exp
        exp : exp MUL exp
        """
        self.codeGenerator.generate_exp_arithmetic_code(p, self.new_temp(), self.new_temp(), self.new_temp(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_exp_const(self, p):
        "exp : const"
        self.codeGenerator.generate_exp_const_code(p)

    def p_exp_ID(self, p):
        "exp : ID"
        self.codeGenerator.generate_exp_ID_code(p)

    def p_exp_array(self, p):
        "exp : ID LSB exp RSB"
        self.codeGenerator.generate_exp_array_code(p, self.new_temp(), self.new_temp(), self.new_temp())

    def p_lvalue(self, p):
        "exp : ID LSB exp RSB ASSIGN exp"
        self.codeGenerator.generate_lvalue_code(p, self.new_temp(), self.new_temp(), self.new_temp(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_exp_sub(self, p):
        "exp : SUB exp"
        self.codeGenerator.generate_exp_sub_code(p, self.new_temp(), self.new_temp(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_exp_par(self, p):
        "exp : LRB exp RRB"
        self.codeGenerator.generate_exp_par_code(p)

    def p_const_arithmetic(self, p):
        """
        const : FLOATNUMBER
        const : INTEGERNUMBER
        """
        self.codeGenerator.generate_const_arithmetic_code(p)

    def p_block(self, p):
        """
        block : LCB stmtlist RCB
        """
        self.codeGenerator.generate_block_code(p)

    def p_stmtlist(self, p):
        """
        stmtlist : stmtlist stmt
        """
        self.codeGenerator.generate_stmtlist_code(p, self.next_quad())

    def p_stmtlist_empty(self, p):
        "stmtlist :"
        self.codeGenerator.generate_stmtlist_empty_code(p)

    def p_stmt_sem(self, p):
        """
        stmt : exp SEMICOLON
        """
        self.codeGenerator.generate_stmt_sem_code(p)

    def p_stmt_block(self, p):
        """
        stmt : block
        """
        self.codeGenerator.generate_stmt_block_code(p)

    def p_stmt_var(self, p):
        """
        stmt : vardec
        """
        self.codeGenerator.generate_stmt_var_code(p)

    def p_stmt_print(self, p):
        """
        stmt : PRINT LRB ID RRB SEMICOLON
        """
        self.codeGenerator.generate_stmt_print_code(p)

    # part 2 ----------------------------------------------------------------------------------------

    def p_stmt_if(self, p):
        "stmt : IF LRB exp RRB stmt elseiflist %prec IFREDUCE"
        self.codeGenerator.generate_stmt_if_code(p, self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_stmt_while(self, p):
        "stmt : WHILE LRB exp RRB stmt"
        self.codeGenerator.generate_stmt_while_code(p, self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_stmt_if_else(self, p):
        "stmt : IF LRB exp RRB stmt elseiflist ELSE stmt"
        self.codeGenerator.generate_stmt_if_else_code(p, self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_stmt_for(self, p):
        "stmt : FOR LRB exp SEMICOLON exp SEMICOLON exp RRB stmt"
        self.codeGenerator.generate_stmt_for_code(p, self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_stmt_foreach(self, p):
        "stmt : FOR LRB ID IN ID RRB stmt"
        self.codeGenerator.generate_stmt_foreach_code(p, self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.new_temp(), self.new_temp(), self.new_temp(), self.new_temp())

    def p_stmt_case(self, p):
        "stmt : ON LRB exp RRB LCB cases RCB SEMICOLON"
        self.codeGenerator.generate_stmt_case_code(p)

    def p_case(self, p):
        """
        case : WHERE const COLON stmtlist
        """
        self.codeGenerator.generate_case_code(p, self.next_quad(), self.next_quad(), self.next_quad())

    def p_cases(self, p):
        "cases : cases case"
        self.codeGenerator.generate_cases_code(p, self.next_quad(), self.next_quad())

    def p_cases_empty(self, p):
        "cases :"
        self.codeGenerator.generate_cases_empty_code(p)

    def p_elseiflist(self, p):
        """
        elseiflist : elseiflist ELSEIF LRB exp RRB stmt
        """
        self.codeGenerator.generate_elseiflist_code(p, self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_elseiflist_empty(self, p):
        "elseiflist :"
        self.codeGenerator.generate_elseiflist_empty_code(p)

    def p_exp_relop(self, p):
        "exp : relopexp %prec EXP"
        self.codeGenerator.generate_exp_relop_code(p)

    def p_relopexp(self, p):
        """
        relopexp : exp GT exp
        relopexp : exp LT exp
        relopexp : exp NE exp
        relopexp : exp EQ exp
        relopexp : exp LE exp
        relopexp : exp GE exp
        """
        self.codeGenerator.generate_relopexp_code(p, self.next_quad(), self.next_quad())

    def p_relopexp_rel(self, p):
        """
        relopexp : relopexp GT exp
        relopexp : relopexp LT exp
        relopexp : relopexp NE exp
        relopexp : relopexp EQ exp
        relopexp : relopexp LE exp
        relopexp : relopexp GE exp
        """
        self.codeGenerator.generate_relopexp_rel_code(p, self.next_quad(), self.next_quad(), self.next_quad())

    def p_exp_and(self, p):
        "exp : exp AND exp"
        self.codeGenerator.generate_exp_and_code(p, self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_exp_or(self, p):
        "exp : exp OR exp"
        self.codeGenerator.generate_exp_or_code(p, self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_exp_not(self, p):
        "exp : NOT exp"
        self.codeGenerator.generate_exp_not_code(p, self.next_quad(), self.next_quad())

    def p_const(self, p):
        """
        const : TRUE
        const : FALSE
        """
        self.codeGenerator.generate_stmt_const_code(p, self.next_quad())

    # part 3 ----------------------------------------------------------------------------------------

    def p_paramdecs(self, p):
        """
        paramdecs : paramdecslist
        """
        self.codeGenerator.generate_paramdecs_code(p)

    def p_paramdecs_empty(self, p):
        """
        paramdecs :
        """
        self.codeGenerator.generate_paramdecs_empty_code(p)

    def p_paramdecslist(self, p):
        """
        paramdecslist : paramdec
        """
        self.codeGenerator.generate_paramdeclist_code(p)

    def p_paramdecslist_comma(self, p):
        """
        paramdecslist : paramdecslist COMMA paramdec
        """
        self.codeGenerator.generate_paramdeclist_comma_code(p)

    def p_paramdec(self, p):
        """
        paramdec : ID COLON type
        paramdec : ID LSB RSB COLON type
        """
        self.codeGenerator.generate_paramdec_code(p)

    def p_exp_fun(self, p):
        """
        exp : ID LRB RRB
        """
        self.codeGenerator.generate_exp_fun_code(p, self.new_temp(), self.new_temp(), self.next_quad(), self.next_quad())

    def p_exp_fun_explist(self, p):
        "exp : ID LRB explist RRB"
        self.codeGenerator.generate_exp_fun_explist_code(p, self.new_temp(), self.new_temp(), self.next_quad(), self.next_quad(), self.next_quad())

    def p_funcdec(self, p):
        """
        funcdec : FUNCTION ID LRB paramdecs RRB block
        """
        self.codeGenerator.generate_funcdec_code(p, self.next_quad(), self.next_quad(), self.next_quad(), self.new_temp())

    def p_funcdec_return(self, p):
        """
        funcdec : FUNCTION ID LRB paramdecs RRB COLON type block
        """
        self.codeGenerator.generate_funcdec_return_code(p, self.next_quad(), self.next_quad(), self.next_quad(), self.new_temp(), self.new_temp())

    def p_explist(self, p):
        """
        explist : exp
        """
        self.codeGenerator.generate_explist_code(p)

    def p_explist_comma(self, p):
        """
        explist : explist COMMA exp
        """
        self.codeGenerator.generate_explist_comma_code(p, self.next_quad())

    def p_dec_funcdec(self, p):
        """
        dec : funcdec
        """
        self.codeGenerator.generate_dec_fundec_code(p)

    def p_stmt_return(self, p):
        """
        stmt : RETURN exp SEMICOLON
        """
        self.codeGenerator.generate_stmt_return_code(p)

    precedence = (
        ('right', "ASSIGN"),
        ('left', "OR"),
        ('left', "AND"),
        ('left', "NOT"),
        ('left', 'EXP'),
        ('left', "GT", "LT", "NE", "EQ", "LE", "GE"),
        ('left', "MOD"),
        ('left', "SUM", "SUB"),
        ('left', "MUL", "DIV"),
        ('left', "IFREDUCE"),
        ('left', "ELSE", "ELSEIF"),
    )

    def new_temp(self):
        temp = "T" + str(self.tempCount)
        self.tempCount += 1
        return temp

    def next_quad(self):
        temp = 'L' + str(self.quad)
        self.quad += 1
        return temp

    def p_error (self, p):
        print ('>> Syntax error at', p.value)
        # raise Exception('Syntax error at', p.value)

    def build(self, **kwargs):
        self.parser = yacc.yacc(module=self, **kwargs)
        return self.parser