Skip to content

Instantly share code, notes, and snippets.

@taotao54321
Last active December 20, 2017 13:18
Show Gist options
  • Save taotao54321/5ac3f9b3c138b0a978aaedc63152d4fb to your computer and use it in GitHub Desktop.
Save taotao54321/5ac3f9b3c138b0a978aaedc63152d4fb to your computer and use it in GitHub Desktop.
tatsu calc example bug?
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
import json
from codecs import open
from pprint import pprint
import tatsu
from tatsu.ast import AST
from tatsu.walkers import NodeWalker
from codegen import PostfixCodeGenerator
def simple_parse():
grammar = open('grammars/calc_cut.ebnf').read()
parser = tatsu.compile(grammar)
#ast = parser.parse('3 + 5 * ( 10 - 20 )', trace=False, colorize=True)
ast = parser.parse('1 * 2 + 3 - 4', trace=False, colorize=True)
print()
print('# SIMPLE PARSE')
print('# AST')
pprint(ast, width=20, indent=4)
print()
print('# JSON')
print(json.dumps(ast, indent=4))
print()
def annotated_parse():
grammar = open('grammars/calc_annotated.ebnf').read()
parser = tatsu.compile(grammar)
#ast = parser.parse('3 + 5 * ( 10 - 20 )')
ast = parser.parse('1 * 2 + 3 - 4')
print()
print('# ANNOTATED AST')
pprint(ast, width=20, indent=4)
print()
class CalcBasicSemantics(object):
def number(self, ast):
return int(ast)
def term(self, ast):
if not isinstance(ast, AST):
return ast
elif ast.op == '*':
return ast.left * ast.right
elif ast.op == '/':
return ast.left / ast.right
else:
raise Exception('Unknown operator', ast.op)
def expression(self, ast):
if not isinstance(ast, AST):
return ast
elif ast.op == '+':
return ast.left + ast.right
elif ast.op == '-':
return ast.left - ast.right
else:
raise Exception('Unknown operator', ast.op)
def parse_with_basic_semantics():
grammar = open('grammars/calc_annotated.ebnf').read()
parser = tatsu.compile(grammar)
result = parser.parse(
#'3 + 5 * ( 10 - 20 )',
'1 * 2 + 3 - 4',
semantics=CalcBasicSemantics()
)
print()
print('# BASIC SEMANTICS RESULT')
#assert result == -47
assert result == 1
print(result)
print()
class CalcSemantics(object):
def number(self, ast):
return int(ast)
def addition(self, ast):
return ast.left + ast.right
def subtraction(self, ast):
return ast.left - ast.right
def multiplication(self, ast):
return ast.left * ast.right
def division(self, ast):
return ast.left / ast.right
def parse_factored():
grammar = open('grammars/calc_factored.ebnf').read()
parser = tatsu.compile(grammar)
ast = parser.parse(
#'3 + 5 * ( 10 - 20 )',
'1 * 2 + 3 - 4',
semantics=CalcSemantics()
)
print()
print('# FACTORED SEMANTICS RESULT')
pprint(ast, width=20, indent=4)
print()
def parse_to_model():
grammar = open('grammars/calc_model.ebnf').read()
parser = tatsu.compile(grammar, asmodel=True)
#model = parser.parse('3 + 5 * ( 10 - 20 )')
model = parser.parse('1 * 2 + 3 - 4')
print()
print('# MODEL TYPE IS:', type(model).__name__)
print(json.dumps(model.asjson(), indent=4))
print()
class CalcWalker(NodeWalker):
def walk_object(self, node):
return node
def walk__add(self, node):
return self.walk(node.left) + self.walk(node.right)
def walk__subtract(self, node):
return self.walk(node.left) - self.walk(node.right)
def walk__multiply(self, node):
return self.walk(node.left) * self.walk(node.right)
def walk__divide(self, node):
return self.walk(node.left) / self.walk(node.right)
def parse_and_walk_model():
grammar = open('grammars/calc_model.ebnf').read()
parser = tatsu.compile(grammar, asmodel=True)
#model = parser.parse('3 + 5 * ( 10 - 20 )')
model = parser.parse('1 * 2 + 3 - 4')
print()
print('# WALKER RESULT')
result = CalcWalker().walk(model)
assert result == -47
print(result)
print()
def parse_and_translate():
grammar = open('grammars/calc_model.ebnf').read()
parser = tatsu.compile(grammar, asmodel=True)
#model = parser.parse('3 + 5 * ( 10 - 20 )')
model = parser.parse('1 * 2 + 3 - 4')
postfix = PostfixCodeGenerator().render(model)
print()
print('# TRANSLATED TO POSTFIX')
print(postfix)
def main():
simple_parse()
annotated_parse()
parse_with_basic_semantics()
parse_factored()
parse_to_model()
parse_and_walk_model()
parse_and_translate()
if __name__ == '__main__':
main()
Traceback (most recent call last):
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 203, in parse
result = rule()
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 693, in parse
result = self._parse_rhs(ctx, self.exp)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 700, in _parse_rhs
result = ctx._call(ruleinfo)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 509, in _call
result = self._recursive_call(ruleinfo)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 540, in _recursive_call
result = self._invoke_rule(ruleinfo, key)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 573, in _invoke_rule
ruleinfo.impl(self)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 348, in parse
ctx.last_node = [s.parse(ctx) for s in self.sequence]
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 348, in <listcomp>
ctx.last_node = [s.parse(ctx) for s in self.sequence]
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 203, in parse
ctx._check_eof()
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 642, in _check_eof
self._error('Expecting end of text', exclass=FailedExpectingEndOfText)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 435, in _error
raise self._make_exception(item, exclass=exclass)
tatsu.exceptions.FailedExpectingEndOfText: (1:11) Expecting end of text :
1 * 2 + 3 - 4
^
start
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "calc.py", line 192, in <module>
main()
File "calc.py", line 185, in main
parse_factored()
File "calc.py", line 113, in parse_factored
semantics=CalcSemantics()
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 945, in parse
**kwargs
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 211, in parse
raise self._furthest_exception
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 672, in _option
yield
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 394, in parse
ctx.last_node = o.parse(ctx)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 649, in parse
return rule()
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 693, in parse
result = self._parse_rhs(ctx, self.exp)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 700, in _parse_rhs
result = ctx._call(ruleinfo)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 509, in _call
result = self._recursive_call(ruleinfo)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 540, in _recursive_call
result = self._invoke_rule(ruleinfo, key)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 573, in _invoke_rule
ruleinfo.impl(self)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 348, in parse
ctx.last_node = [s.parse(ctx) for s in self.sequence]
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 348, in <listcomp>
ctx.last_node = [s.parse(ctx) for s in self.sequence]
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 586, in parse
value = self.exp.parse(ctx)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/grammars.py", line 266, in parse
return ctx._token(self.token)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 610, in _token
self._error(token, exclass=FailedToken)
File "/home/lain/.local/lib/python3.6/site-packages/tatsu/contexts.py", line 435, in _error
raise self._make_exception(item, exclass=exclass)
tatsu.exceptions.FailedToken: (1:11) expecting '*' :
1 * 2 + 3 - 4
^
multiplication
term
addition
expression
start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment