Created
September 14, 2016 20:35
-
-
Save dabeaz/309a35a29d97fd4c1a8e0dfafcf3bf0b to your computer and use it in GitHub Desktop.
SLY (Sly Lex-Yacc) Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See: https://github.com/dabeaz/sly | |
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 NAME(self, t): | |
t.value = t.value.upper() | |
return t | |
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 = { } | |
@_('NAME "=" expr') | |
def statement(self, p): | |
self.names[p.NAME] = p.expr | |
@_('expr') | |
def statement(self, p): | |
print(p.expr) | |
@_('expr "+" expr') | |
def expr(self, p): | |
return p.expr0 + p.expr1 | |
@_('expr "-" expr') | |
def expr(self, p): | |
return p.expr0 - p.expr1 | |
@_('expr "*" expr') | |
def expr(self, p): | |
return p.expr0 * p.expr1 | |
@_('expr "/" expr') | |
def expr(self, p): | |
return p.expr0 / p.expr1 | |
@_('"-" expr %prec UMINUS') | |
def expr(self, p): | |
return -p.expr | |
@_('"(" expr ")"') | |
def expr(self, p): | |
return p.expr | |
@_('NUMBER') | |
def expr(self, p): | |
return p.NUMBER | |
@_('NAME') | |
def expr(self, p): | |
try: | |
return self.names[p.NAME] | |
except LookupError: | |
print("Undefined name '%s'" % p.NAME) | |
return 0 | |
if __name__ == '__main__': | |
lexer = CalcLexer() | |
parser = CalcParser() | |
while True: | |
try: | |
text = input('calc > ') | |
except EOFError: | |
break | |
if text: | |
parser.parse(lexer.tokenize(text)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment