sly/example/calc/calc.py

104 lines
2.2 KiB
Python
Raw Normal View History

2016-09-02 21:07:32 +02:00
# -----------------------------------------------------------------------------
# calc.py
# -----------------------------------------------------------------------------
import sys
2018-01-30 14:42:27 +01:00
sys.path.append('../..')
2016-09-02 21:07:32 +02:00
from sly import Lexer, Parser
class CalcLexer(Lexer):
2018-01-30 14:42:27 +01:00
tokens = { NAME, NUMBER, PLUS, TIMES, MINUS, DIVIDE, ASSIGN, LPAREN, RPAREN }
2016-09-02 21:07:32 +02:00
ignore = ' \t'
2018-01-30 14:42:27 +01:00
# Tokens
NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
NUMBER = r'\d+'
# Special symbols
PLUS = r'\+'
MINUS = r'-'
TIMES = r'\*'
DIVIDE = r'/'
ASSIGN = r'='
LPAREN = r'\('
RPAREN = r'\)'
# Ignored pattern
ignore_newline = r'\n+'
# Extra action for newlines
def ignore_newline(self, t):
2016-09-02 21:07:32 +02:00
self.lineno += t.value.count('\n')
2018-01-10 13:09:20 +01:00
def error(self, t):
print("Illegal character '%s'" % t.value[0])
2016-09-02 21:07:32 +02:00
self.index += 1
class CalcParser(Parser):
tokens = CalcLexer.tokens
2016-09-14 21:21:33 +02:00
2018-01-30 14:42:27 +01:00
precedence = (
('left', PLUS, MINUS),
('left', TIMES, DIVIDE),
('right', UMINUS)
)
def __init__(self):
self.names = { }
@_('NAME ASSIGN expr')
def statement(self, p):
self.names[p.NAME] = p.expr
@_('expr')
def statement(self, p):
print(p.expr)
@_('expr PLUS expr')
2016-09-14 21:21:33 +02:00
def expr(self, p):
2018-01-30 14:42:27 +01:00
return p.expr0 + p.expr1
2016-09-14 21:21:33 +02:00
2018-01-30 14:42:27 +01:00
@_('expr MINUS expr')
2016-09-14 21:21:33 +02:00
def expr(self, p):
2018-01-30 14:42:27 +01:00
return p.expr0 - p.expr1
2016-09-14 21:21:33 +02:00
2018-01-30 14:42:27 +01:00
@_('expr TIMES expr')
2016-09-14 21:21:33 +02:00
def expr(self, p):
2018-01-30 14:42:27 +01:00
return p.expr0 * p.expr1
2016-09-14 21:21:33 +02:00
2018-01-30 14:42:27 +01:00
@_('expr DIVIDE expr')
def expr(self, p):
return p.expr0 / p.expr1
2016-09-14 21:21:33 +02:00
2018-01-30 14:42:27 +01:00
@_('MINUS expr %prec UMINUS')
def expr(self, p):
return -p.expr
2016-09-14 21:21:33 +02:00
2018-01-30 14:42:27 +01:00
@_('LPAREN expr RPAREN')
def expr(self, p):
return p.expr
2016-09-02 21:07:32 +02:00
@_('NUMBER')
2018-01-30 14:42:27 +01:00
def expr(self, p):
return int(p.NUMBER)
2016-09-02 21:07:32 +02:00
2018-01-30 14:42:27 +01:00
@_('NAME')
def expr(self, p):
try:
return self.names[p.NAME]
except LookupError:
print(f'Undefined name {p.NAME!r}')
return 0
2016-09-02 21:07:32 +02:00
if __name__ == '__main__':
lexer = CalcLexer()
2016-09-02 21:07:32 +02:00
parser = CalcParser()
while True:
try:
text = input('calc > ')
2016-09-02 21:07:32 +02:00
except EOFError:
break
2018-01-30 14:42:27 +01:00
if text:
parser.parse(lexer.tokenize(text))