# ----------------------------------------------------------------------------- # calc.py # ----------------------------------------------------------------------------- import sys sys.path.insert(0, "../..") from sly import Lexer, Parser class CalcLexer(Lexer): tokens = { NAME, NUMBER } ignore = ' \t' literals = { '=', '+', '-', '*', '/', '(', ')' } # Tokens NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' @_(r'\d+') def NUMBER(self, t): t.value = int(t.value) return t @_(r'\n+') def newline(self, t): self.lineno += t.value.count('\n') def error(self, t): print("Illegal character '%s'" % t.value[0]) self.index += 1 class CalcParser(Parser): tokens = CalcLexer.tokens precedence = ( ('left', '+', '-'), ('left', '*', '/'), ('right', UMINUS), ) def __init__(self): self.names = { } @_('NAME "=" expr') def statement(self, p): self.names[p.NAME] = p.expr @_('expr') def statement(self, p): print(p.expr) @_('expr "+" expr') def expr(self, p): return p.expr0 + p.expr1 @_('expr "-" expr') def expr(self, p): return p.expr0 - p.expr1 @_('expr "*" expr') def expr(self, p): return p.expr0 * p.expr1 @_('expr "/" expr') def expr(self, p): return p.expr0 / p.expr1 @_('"-" expr %prec UMINUS') def expr(self, p): return -p.expr @_('"(" expr ")"') def expr(self, p): return p.expr @_('NUMBER') def expr(self, p): return p.NUMBER @_('NAME') def expr(self, p): try: return self.names[p.NAME] except LookupError: print("Undefined name '%s'" % p.NAME) return 0 if __name__ == '__main__': lexer = CalcLexer() parser = CalcParser() while True: try: text = input('calc > ') except EOFError: break if text: parser.parse(lexer.tokenize(text))