Skip to content

Commit

Permalink
[test] upgrade keyword_test to pytest
Browse files Browse the repository at this point in the history
  • Loading branch information
apalala committed Mar 18, 2024
1 parent 4aedb3e commit 82adafd
Showing 1 changed file with 130 additions and 124 deletions.
254 changes: 130 additions & 124 deletions test/grammar/keyword_test.py
Original file line number Diff line number Diff line change
@@ -1,152 +1,158 @@
import unittest
from ast import parse

import pytest

from tatsu.exceptions import FailedParse
from tatsu.ngcodegen import codegen
from tatsu.tool import compile


class KeywordTests(unittest.TestCase):
def test_keywords_in_rule_names(self):
grammar = """
start
=
whitespace
;
def test_keywords_in_rule_names():
grammar = """
start
=
whitespace
=
{'x'}+
;
"""
m = compile(grammar, 'Keywords')
m.parse('x')

def test_python_keywords_in_rule_names(self):
# This is a regression test for
# https://bitbucket.org/neogeny/tatsu/issues/59
# (semantic actions not called for rules with the same name as a python
# keyword).
grammar = """
not = 'x' ;
"""
m = compile(grammar, 'Keywords')

class Semantics:
def __init__(self):
self.called = False

def not_(self, ast):
self.called = True

semantics = Semantics()
m.parse('x', semantics=semantics)
assert semantics.called

def test_define_keywords(self):
grammar = """
@@keyword :: B C
@@keyword :: 'A'
start = ('a' 'b').{'x'}+ ;
"""
model = compile(grammar, 'test')
c = codegen(model)
parse(c)

grammar2 = str(model)
model2 = compile(grammar2, 'test')
c2 = codegen(model2)
parse(c2)

self.assertEqual(grammar2, str(model2))

def test_check_keywords(self):
grammar = r"""
@@keyword :: A
start = {id}+ $ ;
@name
id = /\w+/ ;
"""
model = compile(grammar, 'test')
c = codegen(model)
print(c)
parse(c)

ast = model.parse('hello world')
self.assertEqual(['hello', 'world'], ast)
;
try:
ast = model.parse('hello A world')
self.assertEqual(['hello', 'A', 'world'], ast)
self.fail('accepted keyword as name')
except FailedParse as e:
self.assertTrue('"A" is a reserved word' in str(e))
whitespace
=
{'x'}+
;
"""
m = compile(grammar, 'Keywords')
m.parse('x')


def test_python_keywords_in_rule_names():
# This is a regression test for
# https://bitbucket.org/neogeny/tatsu/issues/59
# (semantic actions not called for rules with the same name as a python
# keyword).
grammar = """
not = 'x' ;
"""
m = compile(grammar, 'Keywords')

class Semantics:
def __init__(self):
self.called = False

def not_(self, ast):
self.called = True

semantics = Semantics()
m.parse('x', semantics=semantics)
assert semantics.called


def test_define_keywords():
grammar = """
@@keyword :: B C
@@keyword :: 'A'
start = ('a' 'b').{'x'}+ ;
"""
model = compile(grammar, 'test')
c = codegen(model)
parse(c)

grammar2 = str(model)
model2 = compile(grammar2, 'test')
c2 = codegen(model2)
parse(c2)

def test_check_unicode_name(self):
grammar = r"""
@@keyword :: A
assert grammar2 == str(model2)

start = {id}+ $ ;

@name
id = /\w+/ ;
"""
model = compile(grammar, 'test')
model.parse('hello Øresund')
def test_check_keywords():
grammar = r"""
@@keyword :: A
def test_sparse_keywords(self):
grammar = r"""
@@keyword :: A
start = {id}+ $ ;
@@ignorecase :: False
@name
id = /\w+/ ;
"""
model = compile(grammar, 'test')
c = codegen(model)
print(c)
parse(c)

start = {id}+ $ ;
ast = model.parse('hello world')
assert ast == ['hello', 'world']

@@keyword :: B
try:
ast = model.parse('hello A world')
assert ast == ['hello', 'A', 'world']
pytest.fail('accepted keyword as name')
except FailedParse as e:
assert '"A" is a reserved word' in str(e)

@name
id = /\w+/ ;
"""
model = compile(grammar, 'test', trace=False, colorize=True)
c = codegen(model)
parse(c)

ast = model.parse('hello world')
self.assertEqual(['hello', 'world'], ast)
def test_check_unicode_name():
grammar = r"""
@@keyword :: A
start = {id}+ $ ;
@name
id = /\w+/ ;
"""
model = compile(grammar, 'test')
model.parse('hello Øresund')


def test_sparse_keywords():
grammar = r"""
@@keyword :: A
@@ignorecase :: False
start = {id}+ $ ;
@@keyword :: B
@name
id = /\w+/ ;
"""
model = compile(grammar, 'test', trace=False, colorize=True)
c = codegen(model)
parse(c)

ast = model.parse('hello world')
assert ast == ['hello', 'world']

for k in ('A', 'B'):
try:
ast = model.parse('hello %s world' % k)
assert ['hello', k, 'world'] == ast
pytest.fail('accepted keyword "%s" as name' % k)
except FailedParse as e:
assert '"%s" is a reserved word' % k in str(e)

for k in ('A', 'B'):
try:
ast = model.parse('hello %s world' % k)
self.assertEqual(['hello', k, 'world'], ast)
self.fail('accepted keyword "%s" as name' % k)
except FailedParse as e:
self.assertTrue('"%s" is a reserved word' % k in str(e))

def test_ignorecase_keywords(self):
grammar = r"""
@@ignorecase :: True
@@keyword :: if
def test_ignorecase_keywords():
grammar = r"""
@@ignorecase :: True
@@keyword :: if
start = rule ;
start = rule ;
@name
rule = @:word if_exp $ ;
@name
rule = @:word if_exp $ ;
if_exp = 'if' digit ;
if_exp = 'if' digit ;
word = /\w+/ ;
digit = /\d/ ;
"""
word = /\w+/ ;
digit = /\d/ ;
"""

model = compile(grammar, 'test')
model = compile(grammar, 'test')

model.parse('nonIF if 1', trace=False)
model.parse('nonIF if 1', trace=False)

with self.assertRaises(FailedParse):
model.parse('i rf if 1', trace=False)
with pytest.raises(FailedParse):
model.parse('i rf if 1', trace=False)

with self.assertRaises(FailedParse):
model.parse('IF if 1', trace=False)
with pytest.raises(FailedParse):
model.parse('IF if 1', trace=False)

0 comments on commit 82adafd

Please sign in to comment.