from rply import LexerGenerator
class Lexer():
def __init__(self):
self.lexer = LexerGenerator()
def _add_tokens(self):
# Print
self.lexer.add('PRINT', r'print')
self.lexer.add('SQRT', r'sqrt')
# Parenthesis
self.lexer.add('OPEN_PAREN', r'\(')
self.lexer.add('CLOSE_PAREN', r'\)')
# Semi Colon
self.lexer.add('SEMI_COLON', r'\;')
# Operators
self.lexer.add('SUM', r'\+')
self.lexer.add('SUB', r'\-')
self.lexer.add('MUL', r'\*')
self.lexer.add('DIV', r'\/')
# Number
self.lexer.add('NUMBER', r'\d+')
# Ignore spaces
self.lexer.ignore('\s+')
def get_lexer(self):
self._add_tokens()
return self.lexer.build()
# !pip install rply
# !pip install ast
class Number():
def __init__(self, value):
self.value = value
def eval(self):
return int(self.value)
class BinaryOp():
def __init__(self, left, right):
self.left = left
self.right = right
class Sum(BinaryOp):
def eval(self):
return self.left.eval() + self.right.eval()
class Sub(BinaryOp):
def eval(self):
return self.left.eval() - self.right.eval()
class Mul(BinaryOp):
def eval(self):
return self.left.eval() * self.right.eval()
class Div(BinaryOp):
def eval(self):
return self.left.eval() / self.right.eval()
class Print():
def __init__(self, value):
self.value = value
def eval(self):
print(self.value.eval())
import fastnumbers
fastnumbers.isreal("d")
False
from rply import ParserGenerator
# from ast import Number, Sum, Sub, Print
class Parser():
def __init__(self):
self.pg = ParserGenerator(
# A list of all token names accepted by the parser.
['NUMBER', 'SQRT','PRINT', 'OPEN_PAREN', 'CLOSE_PAREN',
'SEMI_COLON', 'SUM', 'SUB', 'MUL', 'DIV'], precedence=[
('left',['SUM','SUB']),
('left',['DIV','MUL'])
]
)
def parse(self):
# @self.pg.production('function : SQRT OPEN_PAREN expression CLOSE_PAREN')
# def func(p):
# # print(p)
# return (p[2])
@self.pg.production('program : PRINT OPEN_PAREN expression CLOSE_PAREN SEMI_COLON')
def program(p):
return Print(p[2])
@self.pg.production('expression : expression SUM expression')
@self.pg.production('expression : expression SUB expression')
@self.pg.production('expression : expression MUL expression')
@self.pg.production('expression : expression DIV expression')
def expression(p):
left = p[0]
right = p[2]
operator = p[1]
if operator.gettokentype() == 'SUM':
return Sum(left, right)
elif operator.gettokentype() == 'SUB':
return Sub(left, right)
elif operator.gettokentype() == 'MUL':
return Mul(left, right)
elif operator.gettokentype() == 'DIV':
return Div(left, right)
@self.pg.production('expression : NUMBER')
def number(p):
return Number(p[0].value)
@self.pg.error
def error_handle(token):
raise ValueError(token)
def get_parser(self):
return self.pg.build()
%%time
text_input = """
print(SQRT(4*3/2));
"""
lexer = Lexer().get_lexer()
tokens = lexer.lex(text_input)
pg = Parser()
pg.parse()
parser = pg.get_parser()
# print(parser)
parser.parse(tokens).eval()
C:\Users\argenisleon\Anaconda3\lib\site-packages\ipykernel_launcher.py:55: ParserGeneratorWarning: Token 'SQRT' is unused
--------------------------------------------------------------------------- LexingError Traceback (most recent call last) <timed exec> in <module> ~\Anaconda3\lib\site-packages\rply\parser.py in parse(self, tokenizer, state) 30 else: 31 try: ---> 32 lookahead = next(tokenizer) 33 except StopIteration: 34 lookahead = None ~\Anaconda3\lib\site-packages\rply\lexer.py in __next__(self) 58 59 def __next__(self): ---> 60 return self.next() ~\Anaconda3\lib\site-packages\rply\lexer.py in next(self) 55 return token 56 else: ---> 57 raise LexingError(None, SourcePosition(self.idx, -1, -1)) 58 59 def __next__(self): LexingError: (None, SourcePosition(idx=7, lineno=-1, colno=-1))