2016-09-02 21:07:32 +02:00
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# 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, value):
|
|
|
|
print("Illegal character '%s'" % value[0])
|
|
|
|
self.index += 1
|
|
|
|
|
|
|
|
class CalcParser(Parser):
|
|
|
|
tokens = CalcLexer.tokens
|
|
|
|
|
|
|
|
precedence = (
|
|
|
|
('left', '+', '-'),
|
|
|
|
('left', '*', '/'),
|
|
|
|
('right', 'UMINUS'),
|
|
|
|
)
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
self.names = { }
|
|
|
|
|
2016-09-07 20:10:58 +02:00
|
|
|
@_('NAME "=" expression')
|
|
|
|
def statement(self, p):
|
2016-09-02 21:07:32 +02:00
|
|
|
self.names[p[1]] = p[3]
|
|
|
|
|
2016-09-07 20:10:58 +02:00
|
|
|
@_('expression')
|
|
|
|
def statement(self, p):
|
2016-09-02 21:07:32 +02:00
|
|
|
print(p[1])
|
|
|
|
|
2016-09-07 20:10:58 +02:00
|
|
|
@_('expression "+" expression',
|
|
|
|
'expression "-" expression',
|
|
|
|
'expression "*" expression',
|
|
|
|
'expression "/" expression')
|
|
|
|
def expression(self, p):
|
2016-09-02 21:07:32 +02:00
|
|
|
if p[2] == '+':
|
|
|
|
p[0] = p[1] + p[3]
|
|
|
|
elif p[2] == '-':
|
|
|
|
p[0] = p[1] - p[3]
|
|
|
|
elif p[2] == '*':
|
|
|
|
p[0] = p[1] * p[3]
|
|
|
|
elif p[2] == '/':
|
|
|
|
p[0] = p[1] / p[3]
|
|
|
|
|
2016-09-07 20:10:58 +02:00
|
|
|
@_('"-" expression %prec UMINUS')
|
|
|
|
def expression(self, p):
|
2016-09-02 21:07:32 +02:00
|
|
|
p[0] = -p[2]
|
|
|
|
|
2016-09-07 20:10:58 +02:00
|
|
|
@_('"(" expression ")"')
|
|
|
|
def expression(self, p):
|
2016-09-02 21:07:32 +02:00
|
|
|
p[0] = p[2]
|
|
|
|
|
2016-09-07 20:10:58 +02:00
|
|
|
@_('NUMBER')
|
|
|
|
def expression(self, p):
|
2016-09-02 21:07:32 +02:00
|
|
|
p[0] = p[1]
|
|
|
|
|
2016-09-07 20:10:58 +02:00
|
|
|
@_('NAME')
|
|
|
|
def expression(self, p):
|
2016-09-02 21:07:32 +02:00
|
|
|
try:
|
|
|
|
p[0] = self.names[p[1]]
|
|
|
|
except LookupError:
|
|
|
|
print("Undefined name '%s'" % p[1])
|
|
|
|
p[0] = 0
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2016-09-06 21:38:40 +02:00
|
|
|
lexer = CalcLexer()
|
2016-09-02 21:07:32 +02:00
|
|
|
parser = CalcParser()
|
|
|
|
while True:
|
|
|
|
try:
|
2016-09-06 21:38:40 +02:00
|
|
|
text = input('calc > ')
|
2016-09-02 21:07:32 +02:00
|
|
|
except EOFError:
|
|
|
|
break
|
2016-09-06 21:38:40 +02:00
|
|
|
if text:
|
|
|
|
parser.parse(lexer.tokenize(text))
|