#does not need extra lines of code, just debugging! # goal to get…
Question #does not need extra lines of code, just debugging! # goal to get… #does not need extra lines of code, just debugging!# goal to get output for sqrt(4) or sqrt(sqrt(91) or sqrt(3*3) +2 ##from enum import Enum from math import sqrt# Token types## EOF (end-of-file) token is used to indicate that# there is no more input left for lexical analysisINTEGER, FLOAT, PLUS, MINUS, MUL, DIV, LPAREN, RPAREN, EOF = ( ‘INTEGER’, ‘FLOAT’, ‘PLUS’, ‘MINUS’, ‘MUL’, ‘DIV’, ‘(‘, ‘)’, ‘EOF’)class TokenType(Enum): # single-character token types PLUS = ‘+’ MINUS = ‘-‘ MUL = ‘*’ FLOAT_DIV = ‘/’ LPAREN = ‘(‘ RPAREN = ‘)’ SEMI = ‘;’ DOT = ‘.’ COLON = ‘:’ COMMA = ‘,’ # block of reserved words PROGRAM = ‘PROGRAM’ # marks the beginning of the block INTEGER = ‘INTEGER’ REAL = ‘REAL’ INTEGER_DIV = ‘DIV’ VAR = ‘VAR’ PROCEDURE = ‘PROCEDURE’ BEGIN = ‘BEGIN’ END = ‘END’ # marks the end of the block # misc ID = ‘ID’ INTEGER_CONST = ‘INTEGER_CONST’ REAL_CONST = ‘REAL_CONST’ ASSIGN = ‘:=’ EOF = ‘EOF’class Token(object): def __init__(self, token_type, value): self.type = token_type self.value = value def __str__(self): “””String representation of the class instance. Examples: Token(INTEGER, 3) Token(PLUS, ‘+’) Token(MUL, ‘*’) “”” return ‘Token({type}, {value})’.format( type=self.type, value=repr(self.value) ) def __repr__(self): return self.__str__() class Lexer(object): def __init__(self, text): # client string input, e.g. “4 + 2 * 3 – 6 / 2” self.text = text # self.pos is an index into self.text self.pos = 0 self.current_char = self.text[self.pos] def id(self): “””Handle identifiers and reserved keywords””” value = ” while self.current_char is not None and self.current_char.isalpha(): value += self.current_char self.advance() print(value) return Token(TokenType.ID, value) def error(self, msg=None): if msg != None: raise Exception(msg) if self.pos > len(self.text) – 1: raise Exception(‘Unexpected end of file at position %d.’ % self.pos) raise Exception(‘Unexpected character ‘%c’ at position %d.’ % (self.text[self.pos], self.pos)) def advance(self): “””Advance the `pos` pointer and set the `current_char` variable.””” self.pos += 1 if self.pos > len(self.text) – 1: self.current_char = None # Indicates end of input else: self.current_char = self.text[self.pos] def skip_whitespace(self): while self.current_char is not None and self.current_char.isspace(): self.advance() def number(self): “””Return a (multidigit) integer or float consumed from the input.””” is_int = True result = ” starting_pos = self.pos while self.current_char is not None and self.current_char.isdigit(): result += self.current_char self.advance() if self.current_char == ‘.’: is_int = False result += self.current_char self.advance() while self.current_char is not None and self.current_char.isdigit(): result += self.current_char self.advance() if result == ‘.’: self.error(‘Expected numeric value at position {pos:d}, received ‘.”.format(pos=starting_pos)) return Token(INTEGER, int(result)) if is_int else Token(FLOAT, float(result)) def get_next_token(self): “””Lexical analyzer (also known as scanner or tokenizer) This method is responsible for breaking a sentence apart into tokens. One token at a time. “”” while self.current_char is not None: if self.current_char.isspace(): self.skip_whitespace() continue if self.current_char.isdigit() or self.current_char == ‘.’: return self.number() if self.current_char.isalpha(): return self.id() if self.current_char == ‘+’: self.advance() return Token(PLUS, ‘+’) if self.current_char == ‘-‘: self.advance() return Token(MINUS, ‘-‘) if self.current_char == ‘*’: self.advance() return Token(MUL, ‘*’) if self.current_char == ‘/’: self.advance() return Token(DIV, ‘/’) if self.current_char == ‘(‘: self.advance() return Token(LPAREN, ‘(‘) if self.current_char == ‘)’: self.advance() return Token(RPAREN, ‘)’) self.error() return Token(EOF, None)################################################################################ ## PARSER ## ################################################################################class AST(object): passclass BinOp(AST): def __init__(self, left, op, right): self.left = left self.token = self.op = op self.right = rightclass Num(AST): def __init__(self, token): self.token = token self.value = token.valueclass UnaryOp(AST): def __init__(self, op, expr): self.token = self.op = op self.expr = exprclass ProcedureCall(AST): def __init__(self, proc_name, actual_params, token): self.proc_name = proc_name self.actual_params = actual_params # a list of AST nodes self.token = token # a reference to procedure declaration symbol self.proc_symbol = Noneclass Parser(object): def __init__(self, lexer): self.lexer = lexer # set current token to the first token taken from the input self.current_token = self.lexer.get_next_token() def get_next_token(self): return self.lexer.get_next_token() def proccall_statement(self): “””proccall_statement : ID LPAREN (expr (COMMA expr)*)? RPAREN””” token = self.current_token proc_name = self.current_token.value self.eat(TokenType.ID) self.eat(TokenType.LPAREN) actual_params = [] if self.current_token.type != TokenType.RPAREN: node = self.expr() actual_params.append(node) print(‘it is proccal, second 2 line’) while self.current_token.type == TokenType.COMMA: self.eat(TokenType.COMMA) node = self.expr() actual_params.append(node) print(‘it is proccal, third line’) self.eat(TokenType.RPAREN) print(‘it is proccal, 4 line’) node = ProcedureCall( proc_name=proc_name, actual_params=actual_params, token=token, ) print(‘it is proccal’) return node def error(self): raise Exception(‘Invalid syntax.’) def eat(self, token_type): if self.current_token.type == token_type: self.current_token = self.get_next_token() else: print(‘hello’) self.error() def factor(self): “””factor : (PLUS | MINUS) factor | INTEGER | FLOAT | LPAREN expr RPAREN””” token = self.current_token if token.type == PLUS or token.type == MINUS: self.eat(token.type) node = UnaryOp(token, self.factor()) return node elif token.type == INTEGER: self.eat(INTEGER) return Num(token) elif token.type == FLOAT: self.eat(FLOAT) return Num(token) elif token.type == LPAREN: self.eat(LPAREN) node = self.expr() self.eat(RPAREN) return node elif token.type == TokenType.ID: return self.proccall_statement() def term(self): “””term : factor ((MUL | DIV) factor)*””” node = self.factor() while self.current_token.type in (MUL, DIV): token = self.current_token if token.type == MUL: self.eat(MUL) elif token.type == DIV: self.eat(DIV) node = BinOp(left=node, op=token, right=self.factor()) return node def expr(self): “”” expr : term ((PLUS | MINUS) term)* term : factor ((MUL | DIV) factor)* factor : (PLUS | MINUS) factor | INTEGER | LPAREN expr RPAREN “”” node = self.term() while self.current_token.type in (PLUS, MINUS): token = self.current_token if token.type == PLUS: self.eat(PLUS) elif token.type == MINUS: self.eat(MINUS) node = BinOp(left=node, op=token, right=self.term()) return node def parse(self): node = self.expr() if self.current_token.type != EOF: self.error() return node################################################################################ ## INTERPRETER ## ################################################################################class NodeVisitor(object): def visit(self, node): if type(node).__name__ == ‘NoneType’: raise Exception(‘Unexpected end of input.’) method_name = ‘visit_’ + type(node).__name__ visitor = getattr(self, method_name, self.generic_visit) return visitor(node) def generic_visit(self, node): raise Exception(‘No visit_{} method’.format(type(node).__name__))class Interpreter(NodeVisitor): def __init__(self, parser): self.parser = parser def visit_BinOp(self, node): if node.op.type == PLUS: return self.visit(node.left) + self.visit(node.right) elif node.op.type == MINUS: return self.visit(node.left) – self.visit(node.right) elif node.op.type == MUL: return self.visit(node.left) * self.visit(node.right) elif node.op.type == DIV: return self.visit(node.left) // self.visit(node.right) def visit_Num(self, node): return node.value def visit_ProcedureCall(self, node): params = [] for parameter in node.actual_params: params.append(self.visit(parameter)) if node.proc_name == ‘sqrt’: return sqrt(*params) #convert a list into var of arguments def visit_UnaryOp(self, node): op = node.op.type if op == PLUS: return +self.visit(node.expr) elif op == MINUS: return -self.visit(node.expr) def interpret(self): tree = self.parser.parse() if tree is None: return ” return self.visit(tree)def main(): while True: try: text = input(‘spi> ‘) if text == ‘exit’: raise EOFError except EOFError: # If user types CTRL+D print(‘Bye.’) break if not text: continue try: lexer = Lexer(text) parser = Parser(lexer) interpreter = Interpreter(parser) result = interpreter.interpret() print(result) except Exception as error: print(‘Error:’, error)if __name__ == ‘__main__’: main() Computer Science Engineering & Technology Python Programming CS 4181 Share QuestionEmailCopy link Comments (0)


