├── .gitignore ├── README.md ├── codeGenerator.py ├── lexer.py ├── main.py ├── nonTerminal.py ├── parser.py └── test.txt /.gitignore: -------------------------------------------------------------------------------- 1 | README.md 2 | .gitignore 3 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # compiler99 2 | Here you can get all the useful contents needed for the project - TA 3 | -------------------------------------------------------------------------------- /codeGenerator.py: -------------------------------------------------------------------------------- 1 | from nonTerminal import NonTerminal 2 | 3 | 4 | class CodeGenerator: 5 | 6 | def __init__(self): 7 | pass 8 | 9 | def generate_arithmetic_code(self, p, temp): 10 | p[0] = NonTerminal() 11 | p[0].place = temp 12 | p[0].code = p[0].place + " = " 13 | p[0].code += p[1].get_value() + " " + p[2] + " " + p[3].get_value() 14 | print(p[0].code) 15 | -------------------------------------------------------------------------------- /lexer.py: -------------------------------------------------------------------------------- 1 | from ply import lex 2 | 3 | 4 | class Lexer: 5 | tokens = [ 6 | 'IF', 'WHILE', 'PRINT', 7 | 'LRB', 'RRB', 'LCB', 'RCB', 8 | 'INTEGER', 'SUM', 'SUB', 'MUL', 'DIV', 9 | 'LT', 'GT', 'SEMICOLON' 10 | ] 11 | 12 | # COLONS 13 | t_SEMICOLON = r';' 14 | # BRACKETS 15 | t_LRB = r'\(' 16 | t_RRB = r'\)' 17 | t_LCB = r'\{' 18 | t_RCB = r'\}' 19 | # OPERATOR 20 | t_SUM = r'\+' 21 | t_SUB = r'\-' 22 | t_MUL = r'\*' 23 | t_DIV = r'\/' 24 | t_LT = r'\<' 25 | t_GT = r'\>' 26 | # KW 27 | t_IF = r'if' 28 | t_WHILE = r'while' 29 | t_PRINT = r'print' 30 | 31 | def t_INTEGER(self, t): 32 | r'(\d+)' 33 | return t 34 | 35 | def t_newline(self, t): 36 | r'\n+' 37 | t.lexer.lineno += len(t.value) 38 | 39 | t_ignore = '\n \t' 40 | 41 | def t_error(self, t): 42 | raise Exception('Error at', t.value) 43 | 44 | def build(self, **kwargs): 45 | self.lexer = lex.lex(module=self, **kwargs) 46 | return self.lexer 47 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from lexer import Lexer 2 | from parser import Parser 3 | lexer = Lexer().build() 4 | file = open('test.txt') 5 | text_input = file.read() 6 | file.close() 7 | lexer.input(text_input) 8 | # while True: 9 | # tok = lexer.token() 10 | # if not tok: break 11 | # print(tok) 12 | parser = Parser() 13 | parser.build().parse(text_input, lexer, False) 14 | -------------------------------------------------------------------------------- /nonTerminal.py: -------------------------------------------------------------------------------- 1 | class NonTerminal: 2 | 3 | def __init__(self): 4 | self.value = "" 5 | self.code = "" 6 | self.place = "" 7 | 8 | def get_value(self): 9 | if self.value == "": 10 | return self.place 11 | return self.value 12 | 13 | -------------------------------------------------------------------------------- /parser.py: -------------------------------------------------------------------------------- 1 | from ply import yacc 2 | from lexer import Lexer 3 | from nonTerminal import NonTerminal 4 | from codeGenerator import CodeGenerator 5 | 6 | 7 | class Parser: 8 | 9 | tokens = Lexer().tokens 10 | 11 | def __init__(self): 12 | self.tempCount = 0 13 | self.codeGenerator = CodeGenerator() 14 | 15 | def p_program(self, p): 16 | "program : exp" 17 | pass 18 | 19 | def p_exp_sum(self, p): 20 | "exp : exp SUM exp" 21 | self.codeGenerator.generate_arithmetic_code(p, self.new_temp()) 22 | 23 | def p_exp_sub(self, p): 24 | "exp : exp SUB exp" 25 | self.codeGenerator.generate_arithmetic_code(p, self.new_temp()) 26 | 27 | def p_exp_mul(self, p): 28 | "exp : exp MUL exp" 29 | self.codeGenerator.generate_arithmetic_code(p, self.new_temp()) 30 | 31 | def p_exp_div(self, p): 32 | "exp : exp DIV exp" 33 | self.codeGenerator.generate_arithmetic_code(p, self.new_temp()) 34 | 35 | def p_exp_integer(self, p): 36 | "exp : INTEGER" 37 | p[0] = NonTerminal() 38 | p[0].value = p[1] 39 | 40 | def new_temp(self): 41 | temp = "T" + str(self.tempCount) 42 | self.tempCount += 1 43 | return temp 44 | 45 | precedence = ( 46 | ('left', 'SUM', 'SUB'), 47 | ('left', 'MUL', 'DIV') 48 | ) 49 | 50 | def p_error(self, p): 51 | print(p.value) 52 | raise Exception('ParsingError: invalid grammar at ', p) 53 | 54 | def build(self, **kwargs): 55 | """build the parser""" 56 | self.parser = yacc.yacc(module=self, **kwargs) 57 | return self.parser 58 | -------------------------------------------------------------------------------- /test.txt: -------------------------------------------------------------------------------- 1 | 2 + 3 * 4 / 5 --------------------------------------------------------------------------------