2016-09-02 21:07:32 +02:00
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# calc.py
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
import sys
|
|
|
|
sys.path.insert(0, "../..")
|
|
|
|
|
|
|
|
from sly import Lexer, Parser
|
|
|
|
|
|
|
|
class CalcLexer(Lexer):
|
2016-09-14 21:21:33 +02:00
|
|
|
# Set of token names. This is always required
|
|
|
|
tokens = {
|
|
|
|
'ID',
|
|
|
|
'NUMBER',
|
|
|
|
'PLUS',
|
|
|
|
'MINUS',
|
|
|
|
'TIMES',
|
|
|
|
'DIVIDE',
|
|
|
|
'ASSIGN',
|
|
|
|
'LPAREN',
|
|
|
|
'RPAREN',
|
|
|
|
}
|
|
|
|
|
|
|
|
# String containing ignored characters between tokens
|
2016-09-02 21:07:32 +02:00
|
|
|
ignore = ' \t'
|
|
|
|
|
2016-09-14 21:21:33 +02:00
|
|
|
# Regular expression rules for tokens
|
|
|
|
ID = r'[a-zA-Z_][a-zA-Z0-9_]*'
|
|
|
|
PLUS = r'\+'
|
|
|
|
MINUS = r'-'
|
|
|
|
TIMES = r'\*'
|
|
|
|
DIVIDE = r'/'
|
|
|
|
ASSIGN = r'='
|
|
|
|
LPAREN = r'\('
|
|
|
|
RPAREN = r'\)'
|
2016-09-02 21:07:32 +02:00
|
|
|
|
|
|
|
@_(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')
|
|
|
|
|
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):
|
2016-09-14 21:21:33 +02:00
|
|
|
# Get the token list from the lexer (required)
|
2016-09-02 21:07:32 +02:00
|
|
|
tokens = CalcLexer.tokens
|
2016-09-14 21:21:33 +02:00
|
|
|
|
|
|
|
# Grammar rules and actions
|
|
|
|
@_('expr PLUS term')
|
|
|
|
def expr(self, p):
|
|
|
|
return p.expr + p.term
|
|
|
|
|
|
|
|
@_('expr MINUS term')
|
|
|
|
def expr(self, p):
|
|
|
|
return p.expr - p.term
|
|
|
|
|
|
|
|
@_('term')
|
|
|
|
def expr(self, p):
|
|
|
|
return p.term
|
|
|
|
|
2017-02-01 20:15:34 +01:00
|
|
|
@_('term TIMES factor')
|
2016-09-14 21:21:33 +02:00
|
|
|
def term(self, p):
|
|
|
|
return p.term * p.factor
|
|
|
|
|
|
|
|
@_('term DIVIDE factor')
|
|
|
|
def term(self, p):
|
|
|
|
return p.term / p.factor
|
|
|
|
|
|
|
|
@_('factor')
|
|
|
|
def term(self, p):
|
|
|
|
return p.factor
|
2016-09-02 21:07:32 +02:00
|
|
|
|
2016-09-07 20:10:58 +02:00
|
|
|
@_('NUMBER')
|
2016-09-14 21:21:33 +02:00
|
|
|
def factor(self, p):
|
2016-09-08 22:05:03 +02:00
|
|
|
return p.NUMBER
|
2016-09-02 21:07:32 +02:00
|
|
|
|
2016-09-14 21:21:33 +02:00
|
|
|
@_('LPAREN expr RPAREN')
|
|
|
|
def factor(self, p):
|
|
|
|
return p.expr
|
2016-09-02 21:07:32 +02:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2016-09-06 21:38:40 +02:00
|
|
|
lexer = CalcLexer()
|
2016-09-02 21:07:32 +02:00
|
|
|
parser = CalcParser()
|
2016-09-14 21:21:33 +02:00
|
|
|
|
2016-09-02 21:07:32 +02:00
|
|
|
while True:
|
|
|
|
try:
|
2016-09-06 21:38:40 +02:00
|
|
|
text = input('calc > ')
|
2016-09-14 21:21:33 +02:00
|
|
|
result = parser.parse(lexer.tokenize(text))
|
|
|
|
print(result)
|
2016-09-02 21:07:32 +02:00
|
|
|
except EOFError:
|
|
|
|
break
|