from lexer import TokenType class Expr: def accept(self, visitor): raise Exception("needs to be implemented") class Literal: def __init__(self, value): self.value = value def accept(self, visitor): visitor.visitLiteral(self) def __str__(self): return f"{self.value}" class Symbol: def __init__(self, name): self.name = name def accept(self, visitor): visitor.visitSymbol(self) def __str__(self): return f"'{self.name}" class Nary: def __init__(self, symbol, args): self.symbol = symbol self.args = args def accept(self, visitor): visitor.visitNary(self) def __str__(self): out = f"[{self.symbol} => (" first = True for arg in self.args: if first: out = f"{out} {arg}" first = False else: out = f"{out}, {arg}" return f"{out} )]" class Binary: def __init__(self, symbol, left, right): self.symbol = symbol self.left = left self.right = right def accept(self, visitor): visitor.visitBinary(self) class Visitor: def visitLiteral(self, literal): return literal.value def visitBinary(self, binary): sym = binary.symbol.text left = binary.left.accept(self) right = binary.right.accept(self) return "({sym} {left} {right}" def visitNary(self, nary): sym = nary.symbol.text args = [] for arg in nary.args: args.append(arg.accept(self)) return "({sym} {' '.join(args)})" def visitSymbol(self, symbol): return symbol.name def parseExpression(token, prev, tokens): idx = 0 args = [] prev = token while tokens[idx].type_ != TokenType.CLOSE_PAREN: token = tokens[idx] inc = 1 if token.type_ == TokenType.OPEN_PAREN: expr, inc = parseExpression(token, prev, tokens[idx+1:]) args.append(expr) elif token.type_ in (TokenType.STRING, TokenType.TRUE, TokenType.FALSE, TokenType.INT, TokenType.FLOAT): expr, inc = parseLiteral(token, prev, tokens[idx+1:]) args.append(expr) else: expr, inc = parseSymbol(token, prev, tokens[idx+1:]) args.append(expr) idx += inc prev = token return Expr.Nary(args[0], args[1:]), idx + 2 # parens def parseSymbol(token, prev, tokens): return Expr.Symbol(token.text), 1 def parseLiteral(token, prev, tokens): return Expr.Literal(token.value), 1 def parse(tokens): idx = 0 prev = None exprs = [] while tokens[idx].type_ != TokenType.EOF: token = tokens[idx] counter = 1 if token.type_ == TokenType.OPEN_PAREN: expr, counter = parseExpression(token, prev, tokens[idx+1:]) exprs.append(expr) elif token.type_ in (TokenType.FALSE, TokenType.TRUE, TokenType.STRING, TokenType.INT, TokenType.FLOAT): lit, counter = parseLiteral(token, prev, tokens[idx+1:]) exprs.append(lit) else: sym, counter = parseSymbol(token, prev, tokens[idx+1:]) exprs.append(sym) idx += counter prev = token return exprs