Skip to content

Instantly share code, notes, and snippets.

@costrouc
Created February 3, 2019 23:13
Show Gist options
  • Select an option

  • Save costrouc/f08bb88902437ba9d92017eb4c673581 to your computer and use it in GitHub Desktop.

Select an option

Save costrouc/f08bb88902437ba9d92017eb4c673581 to your computer and use it in GitHub Desktop.
parser + ast + python source code translation
import ast
import astunparse
import sly
class CalculatorLexer(sly.Lexer):
tokens = { SYMBOL, NUMBER, PLUS, MINUS, TIMES, DIVIDE, LPAREN, RPAREN }
ignore = ' \t'
SYMBOL = r'[A-Za-z][A-Za-z0-9_]*'
PLUS = r'\+'
MINUS = r'\-'
TIMES = r'\*'
DIVIDE = '/'
LPAREN = '\('
RPAREN = '\)'
@_(r'[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?')
def NUMBER(self, t):
t.value = float(t.value)
return t
class CalculatorParser(sly.Parser):
tokens = CalculatorLexer.tokens
precedence = (
('left', 'PLUS', 'MINUS'),
('left', 'TIMES', 'DIVIDE'),
('left', 'UMINUS')
)
@_('expr PLUS expr',
'expr MINUS expr',
'expr TIMES expr',
'expr DIVIDE expr')
def expr(self, p):
op_map = {
'+': ast.Add,
'-': ast.Sub,
'*': ast.Mult,
'/': ast.Div
}
return ast.BinOp(p.expr0, op_map[p[1]](), p.expr1)
@_('MINUS expr %prec UMINUS')
def expr(self, p):
return ast.UnaryOp(ast.USub(), p.expr)
@_('NUMBER')
def expr(self, p):
return ast.Num(p[0])
@_('LPAREN expr RPAREN')
def expr(self, p):
return p.expr
@_('SYMBOL LPAREN expr RPAREN')
def expr(self, p):
return ast.Call(func=ast.Name(id=p.SYMBOL), args=[p.expr], keywords=[])
if __name__ == '__main__':
parser = CalculatorParser()
lexer = CalculatorLexer()
print('Simple Calculator to exit type (q)uit')
while True:
text = input('calc> ')
if text in {'q', 'quit'}: break
tree = parser.parse(lexer.tokenize(text))
source = astunparse.unparse(tree)[:-1] # remove newline
print('SOURCE', source)
print('EVAL', eval(source))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment