1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
# ruff: noqa: S102
import unittest
from tatsu import synth
from tatsu.model import Node
from tatsu.semantics import ModelBuilderSemantics
from tatsu.tool import compile
class MyNode:
def __init__(self, ast):
pass
class SemanticsTests(unittest.TestCase):
def test_builder_semantics(self):
grammar = r"""
start::sum = {number}+ $ ;
number::int = /\d+/ ;
"""
text = '5 4 3 2 1'
semantics = ModelBuilderSemantics()
model = compile(grammar, 'test')
ast = model.parse(text, semantics=semantics)
self.assertEqual(15, ast)
import functools
dotted = functools.partial(str.join, '.')
dotted.__name__ = 'dotted'
grammar = r"""
start::dotted = {number}+ $ ;
number = /\d+/ ;
"""
semantics = ModelBuilderSemantics(types=[dotted])
model = compile(grammar, 'test')
ast = model.parse(text, semantics=semantics)
self.assertEqual('5.4.3.2.1', ast)
def test_builder_subclassing(self):
registry = getattr(synth, '__REGISTRY')
grammar = """
@@grammar :: Test
start::A::B::C = $ ;
"""
model = compile(grammar, asmodel=True)
model.parse('')
print(f'{registry=}')
A = registry['A']
B = registry['B']
C = registry['C']
self.assertTrue(
issubclass(A, B)
and issubclass(A, synth._Synthetic)
and issubclass(A, Node),
)
self.assertTrue(
issubclass(B, C)
and issubclass(B, synth._Synthetic)
and issubclass(A, Node),
)
self.assertTrue(
issubclass(C, synth._Synthetic) and issubclass(C, Node),
)
def test_builder_basetype_codegen(self):
grammar = """
@@grammar :: Test
start::A::B::C = a:() b:() $ ;
second::D::A = ();
third = ();
"""
from tatsu.tool import to_python_model
src = to_python_model(grammar, base_type=MyNode)
print(src)
globals = {}
exec(src, globals) # pylint: disable=W0122
semantics = globals['TestModelBuilderSemantics']()
A = globals['A']
B = globals['B']
C = globals['C']
D = globals['D']
model = compile(grammar, semantics=semantics)
ast = model.parse('', semantics=semantics)
self.assertIsInstance(ast, MyNode)
self.assertIsInstance(ast, (A, B, C))
self.assertTrue(hasattr(ast, 'a'))
self.assertTrue(hasattr(ast, 'b'))
self.assertTrue(issubclass(D, A | B | C))
def test_optional_attributes(self):
grammar = r"""
foo::Foo = left:identifier [ ':' right:identifier ] $ ;
identifier = /\w+/ ;
"""
grammar = compile(grammar)
a = grammar.parse('foo : bar', semantics=ModelBuilderSemantics())
assert a.left == 'foo'
assert a.right == 'bar'
b = grammar.parse('foo', semantics=ModelBuilderSemantics())
self.assertEqual(b.left, 'foo')
self.assertIsNone(b.right)
|