#!/usr/bin/env python
import re
import sys
import unittest
import tpg
print "*"*70
print "*"
print "* Unit tests for %(__name__)s %(__version__)s (%(__date__)s)"%tpg.__dict__
print "*"
print "* Platform : %s"%sys.platform.replace('\n', ' ')
print "* Version : %s"%sys.version.replace('\n', ' ')
print "*"
print "* Please report bug to %(__author__)s (%(__email__)s)"%tpg.__dict__
print "* for further detail read %(__url__)s"%tpg.__dict__
print "*"
print "*"*70
for PARSER, VERBOSE in ( (tpg.Parser, None),
(tpg.VerboseParser, 0),
(tpg.VerboseParser, 1),
(tpg.VerboseParser, 2),
):
for LEXER in tpg.TPGParser.Options.option_dict['lexer'][0].keys():
print "*"*70
if VERBOSE is None:
print "* %s %s"%(PARSER.__name__, LEXER)
else:
print "* %s verbose=%s %s"%(PARSER.__name__, VERBOSE, LEXER)
print "*"*70
class LexerOptionsTestCase(unittest.TestCase):
class WordBounded(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set word_boundary = True
separator spaces '\s+' ;
token a 'a' ;
token b 'b' ;
token w '\w+' ;
START/lst -> $ lst = []
( a/t $ lst.append(t)
| b/t $ lst.append(t)
| w/t $ lst.append(t)
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testWordBound(self):
p = self.WordBounded()
self.assertEquals(p('abcabc a b c'), ['abcabc', 'a', 'b', 'c'])
self.assertEquals(p('abc abc a b c'), ['abc', 'abc', 'a', 'b', 'c'])
class NotWordBounded(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set word_boundary = False
separator spaces '\s+' ;
token a 'a' ;
token b 'b' ;
token w '\w+' ;
START/lst -> $ lst = []
( a/t $ lst.append(t)
| b/t $ lst.append(t)
| w/t $ lst.append(t)
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testNotWordBound(self):
p = self.NotWordBounded()
if LEXER in ('Lexer', 'CacheLexer'):
self.assertEquals(p('abcabc a b c'), ['abcabc', 'a', 'b', 'c'])
self.assertEquals(p('abc abc a b c'), ['abc', 'abc', 'a', 'b', 'c'])
else:
self.assertEquals(p('abcabc a b c'), ['a', 'b', 'cabc', 'a', 'b', 'c'])
self.assertEquals(p('abc abc a b c'), ['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'])
class WordBounded2(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set word_boundary = True
separator spaces '\s+' ;
token abc 'abc' ;
token def 'def:' ;
token ghi ':ghi' ;
token other '\w+|:' ;
START/lst -> $ lst = []
( abc/t $ lst.append(t)
| def/t $ lst.append(t)
| ghi/t $ lst.append(t)
| other
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testWordBounded2(self):
p = self.WordBounded2()
self.assertEquals(p("abc :titi: :def: toto :ghi:"), ['abc', 'def:', ':ghi'])
self.assertEquals(p(":abc:def:ghi:"), ['abc', 'def:'])
self.assertEquals(p(":abc:ghi:def:"), ['abc', ':ghi', 'def:'])
self.assertEquals(p("::abc::def::ghi::"), ['abc', 'def:', ':ghi'])
self.assertEquals(p("::abc::ghi::def::"), ['abc', ':ghi', 'def:'])
class IgnoreCase(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set lexer_ignorecase = True
separator spaces '\s+' ;
token a 'a' ;
token b 'B' ;
START/lst -> $ lst = []
( a/t $ lst.append(t)
| b/t $ lst.append(t)
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testIgnoreCase(self):
p = self.IgnoreCase()
self.assertEquals(p('a A b B'), ['a', 'A', 'b', 'B'])
class NotIgnoreCase(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set lexer_ignorecase = False
separator spaces '\s+' ;
token a 'a' ;
token b 'B' ;
START/lst -> $ lst = []
( a/t $ lst.append(t)
| b/t $ lst.append(t)
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testNotIgnoreCase(self):
p = self.NotIgnoreCase()
if LEXER in ('ContextSensitiveLexer',):
self.assertRaises(tpg.SyntacticError, p, 'a A b B')
else:
self.assertRaises(tpg.LexicalError, p, 'a A b B')
self.assertEquals(p('a B a B'), ['a', 'B', 'a', 'B'])
class Multiline(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set lexer_multiline = True
token b '^b' ;
token e 'e$' ;
token w '\w' ;
separator spaces '\s+' ;
START/$nb,nw,ne$ -> $ nb, nw, ne = 0, 0, 0
( b $ nb += 1
| e $ ne += 1
| w $ nw += 1
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testMultiline(self):
p = self.Multiline()
self.assertEquals(p('b b w e e\nb b w e e\nb b w e e'), (3, 9, 3))
class NotMultiline(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set lexer_multiline = False
token b '^b' ;
token e 'e$' ;
token w '\w' ;
separator spaces '\s+' ;
START/$nb,nw,ne$ -> $ nb, nw, ne = 0, 0, 0
( b $ nb += 1
| e $ ne += 1
| w $ nw += 1
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testNotMultiline(self):
p = self.NotMultiline()
self.assertEquals(p('b b w e e\nb b w e e\nb b w e e'), (1, 13, 1))
class DotAll(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set lexer_dotall = True
token ch '.' ;
token nl '\n' ;
START/$c,n$ -> $ c, n = 0, 0
( ch $ c += 1
| nl $ n += 1
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testDotAll(self):
p = self.DotAll()
self.assertEquals(p('a\nb\nc\n'), (6, 0))
class NotDotAll(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set lexer_dotall = False
token ch '.' ;
token nl '\n' ;
START/$c,n$ -> $ c, n = 0, 0
( ch $ c += 1
| nl $ n += 1
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testNotDotAll(self):
p = self.NotDotAll()
self.assertEquals(p('a\nb\nc\n'), (3, 3))
class Verbose(PARSER):
__doc__ = (r"""
set lexer = %(LEXER)s
set lexer_verbose = True
token foobar "foo bar" ;
token foo "foo" ;
token bar "bar" ;
token triple_quoted_1 '''
"{3}
( \\.
| "{0,2} [^"\\]+
)*
"{3}
''' ;
""" + r'''
token triple_quoted_2 """
'{3}
( \\.
| '{0,2} [^'\\]+
)*
'{3}
""" ;
''' + r"""
separator spaces '\s+' ;
START/lst -> $ lst = []
( foobar $ lst.append(1)
| foo $ lst.append(2)
| bar $ lst.append(3)
| triple_quoted_1 $ lst.append(4)
| triple_quoted_2 $ lst.append(5)
)*
;
""")%tpg.Py()
verbose = VERBOSE
def testVerbose(self):
p = self.Verbose()
self.assertEquals(p('''
foobar foo bar foo bar """ hello 'world' """ \''' ''hello'' ""universe"" \'''
'''), [1, 2, 3, 2, 3, 4, 5])
class NotVerbose(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set lexer_verbose = False
token foobar "foo bar" ;
token foo "foo" ;
token bar "bar" ;
separator spaces '\s+' ;
START/lst -> $ lst = []
( foobar $ lst.append(1)
| foo $ lst.append(2)
| bar $ lst.append(3)
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testNotVerbose(self):
p = self.NotVerbose()
if LEXER in ('ContextSensitiveLexer',):
self.assertRaises(tpg.SyntacticError, p, 'foobar foo bar foo bar')
else:
self.assertRaises(tpg.LexicalError, p, 'foobar foo bar foo bar')
self.assertEquals(p('foo bar foo bar'), [1, 2, 3])
class LexersTestCase(unittest.TestCase):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set lexer = NamedGroupLexer
token float '\d+\.\d+' $ float
token int '\d+' int
token text '\w+' ;
token str '".*?"' $ lambda s: s[1:-1]
token brackets '\{(.|\n)*?\}' "{}"
separator spaces '\s+' ;
separator comments '\(.*?\)' ;
START/$t, type(t)$ ->
( float/t
| int/t
| text/t
| str/t
| brackets/t
)
;
POSITIONS/lst -> $ lst = []
( $ line, column = self.line(), self.column()
( text text int $ lst.append(None)
| text int $ lst.append(None)
| text/t $ lst.append((t, line, column))
| brackets/t $ lst.append((t, line, column))
)
)*
;
"""%tpg.Py()
verbose = VERBOSE
def testLexers(self):
p = self.Parser()
self.assertEquals(p(' 314'), (314, int))
self.assertEquals(p('3.14 '), (3.14, float))
self.assertEquals(p(' (one identifier) cool'), ('cool', str))
self.assertEquals(p('"Super cool" (!!!) '), ('Super cool', str))
self.assertEquals(p(' { ... } (!!!) '), ('{}', str))
def testPositions(self):
p = self.Parser()
s = r"""a b c
d e f
{ ...
... } y
z
"""
self.assertEquals(p.parse('POSITIONS',s), [('a', 1, 1), ('b', 1, 3), ('c', 1, 5),
('d', 2, 17), ('e', 2, 19), ('f', 2, 21),
('{}', 3, 17), ('y', 4, 23), ('z', 5, 17),
])
class BacktrackingTestCase(unittest.TestCase):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set word_boundary = False
START/n ->
( 'a' 'b' 'c' 'd' $ n = 1
| 'a' 'b' 'd' 'c' $ n = 2
| 'a'
( 'c' 'b' 'd' $ n = 3
| 'c' 'd' 'b' $ n = 4
| 'd'
( 'b' 'c' $ n = 5
| 'c' 'b' $ n = 6
)
)
| 'b'
( 'a'
( 'c' 'd' $ n = 7
| 'd' 'c' $ n = 8
)
| 'c'
( 'a' 'd' $ n = 9
| 'd' 'a' $ n = 10
)
)
| 'e' $ n = 11
)
;
"""%tpg.Py()
def testBacktracking(self):
p = self.Parser()
self.assertEquals(p('abcd'), 1)
self.assertEquals(p('abdc'), 2)
self.assertEquals(p('acbd'), 3)
self.assertEquals(p('acdb'), 4)
self.assertEquals(p('adbc'), 5)
self.assertEquals(p('adcb'), 6)
self.assertEquals(p('bacd'), 7)
self.assertEquals(p('badc'), 8)
self.assertEquals(p('bcad'), 9)
self.assertEquals(p('bcda'), 10)
self.assertEquals(p('e'), 11)
self.assertRaises(tpg.SyntacticError, p, 'abce')
self.assertRaises(tpg.SyntacticError, p, 'abec')
self.assertRaises(tpg.SyntacticError, p, 'aebc')
self.assertRaises(tpg.SyntacticError, p, 'eabd')
self.assertRaises(tpg.SyntacticError, p, 'cabd')
class ExtractTestCase(unittest.TestCase):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
separator spaces '\s+' ;
START/lst -> $ lst = []
@start
(
'\('
@start1
'\w+'*
@stop1
'\)' $ lst.append(self.extract(start1, stop1))
)*
@stop $ lst.append(self.extract(start, stop))
;
"""%tpg.Py()
def testExtract(self):
p = self.Parser()
self.assertEquals(p(''), [''])
self.assertEquals(p('() ()'), ['', '', '() ()'])
self.assertEquals(p(' ( ) ( ) '), ['', '', '( ) ( )'])
self.assertEquals(p('(a b) (c d)'), ['a b', 'c d', '(a b) (c d)'])
self.assertEquals(p(' (a b) ( c d ) '), ['a b', 'c d', '(a b) ( c d )'])
class AxiomTestCase(unittest.TestCase):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
token word '\w+' ;
START/"Axiom == START" -> ;
SYMBOL1/"Axiom == SYMBOL1" -> ;
SYMBOL2/"Axiom == SYMBOL2" -> ;
"""%tpg.Py()
def testAxiom(self):
p = self.Parser()
self.assertEquals(p(''), "Axiom == START")
self.assertEquals(p.parse('START', ''), "Axiom == START")
self.assertEquals(p.parse('SYMBOL1', ''), "Axiom == SYMBOL1")
self.assertEquals(p.parse('SYMBOL2', ''), "Axiom == SYMBOL2")
self.assertRaises(AttributeError, p.parse, 'SYMBOL3', '')
self.assertRaises(tpg.SyntacticError, p, 'x')
self.assertRaises(tpg.SyntacticError, p.parse ,'START', 'x')
self.assertRaises(tpg.SyntacticError, p.parse ,'SYMBOL1', 'x')
self.assertRaises(tpg.SyntacticError, p.parse ,'SYMBOL2', 'x')
self.assertRaises(AttributeError, p.parse ,'SYMBOL3', 'x')
class TokenInfoTestCase(unittest.TestCase):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
set lexer_dotall = True
separator spaces '\s+' ;
token tok "\(.*?\)" ;
START/lst -> $ lst = []
( $ lst.append((self.line(), self.column()))
@t $ lst.append((t.line, t.column))
tok $ lst.append((self.line(t), self.column(t)))
@t $ lst.append((t.line, t.column))
)*
;
"""%tpg.Py()
def testTokenInfo(self):
p = self.Parser()
if LEXER in ('ContextSensitiveLexer', ):
self.assertEquals(p(''), [(1,1), (1,1)])
self.assertEquals(p(' ( ) (\n) (w)'), [(1,1), (1,1), (1,1), (1,2),
(1,2), (1,2), (1,2), (1,6),
(1,6), (1,6), (1,6), (2,3),
(2,3), (2,3)
])
else:
self.assertEquals(p(''), [(1,1), (1,1)])
self.assertEquals(p(' ( ) (\n) (w)'), [(1,2), (1,2), (1,2), (1,6),
(1,6), (1,6), (1,6), (2,3),
(2,3), (2,3), (2,3), (2,6),
(2,6), (2,6)
])
class CheckErrorTestCase(unittest.TestCase):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
separator spaces '\s+' ;
token int '\-?\d+' int ;
POSITIVE_1/i -> int/i check $i>0$ ;
POSITIVE_2/i -> int/i $self.check(i>0)$ ;
POSITIVE_3/i -> int/i ( check $i>0$ | error "i <= 0" ) ;
POSITIVE_4/i -> int/i ( check $i>0$ | error $"%%d <= 0"%%i$ ) ;
POSITIVE_5/i -> int/i ( check $i>0$ | $self.error("%%d <= 0"%%i)$ );
POSITIVE_6/i -> int/i ( check $i>0$ | $i=None$ ) ;
POSITIVE_7/i -> int/i ( $self.check(i>0)$ | $i=None$ ) ;
"""%tpg.Py()
def testCheckError(self):
p = self.Parser()
for x in ("1", "18"):
self.assertEquals(p.parse('POSITIVE_1', x), int(x))
self.assertEquals(p.parse('POSITIVE_2', x), int(x))
self.assertEquals(p.parse('POSITIVE_3', x), int(x))
self.assertEquals(p.parse('POSITIVE_4', x), int(x))
self.assertEquals(p.parse('POSITIVE_5', x), int(x))
self.assertEquals(p.parse('POSITIVE_6', x), int(x))
self.assertEquals(p.parse('POSITIVE_7', x), int(x))
for x in ("0", "-36"):
self.assertRaises(tpg.SyntacticError, p.parse, 'POSITIVE_1', x)
self.assertRaises(tpg.SyntacticError, p.parse, 'POSITIVE_2', x)
self.assertRaises(tpg.SemanticError, p.parse, 'POSITIVE_3', x)
self.assertRaises(tpg.SemanticError, p.parse, 'POSITIVE_4', x)
self.assertRaises(tpg.SemanticError, p.parse, 'POSITIVE_5', x)
self.assertEquals(p.parse('POSITIVE_6', x), None)
self.assertEquals(p.parse('POSITIVE_7', x), None)
class RepetitionTestCase(unittest.TestCase):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
separator spaces '\s+' ;
token w '\w+' ;
STAR/n -> $n=0$ ( w $n=n+1$ )* ;
PLUS/n -> $n=0$ ( w $n=n+1$ )+ ;
QUES/n -> $n=0$ ( w $n=n+1$ )? ;
REP1/n -> $n=0$ ( w $n=n+1$ ){} ;
REP2/n -> $n=0$ ( w $n=n+1$ ){3} ;
REP3/n -> $n=0$ ( w $n=n+1$ ){,} ;
REP4/n -> $n=0$ ( w $n=n+1$ ){,3} ;
REP5/n -> $n=0$ ( w $n=n+1$ ){2,} ;
REP6/n -> $n=0$ ( w $n=n+1$ ){2,5} ;
"""%tpg.Py()
def testStar(self):
p = self.Parser()
self.assertEquals(p.parse('STAR', ''), 0)
self.assertEquals(p.parse('STAR', 'a'), 1)
self.assertEquals(p.parse('STAR', 'a b'), 2)
self.assertEquals(p.parse('STAR', 'a b c d e f'), 6)
def testPlus(self):
p = self.Parser()
self.assertRaises(tpg.SyntacticError, p.parse, 'PLUS', '')
self.assertEquals(p.parse('PLUS', 'a'), 1)
self.assertEquals(p.parse('PLUS', 'a b'), 2)
self.assertEquals(p.parse('PLUS', 'a b c d e f'), 6)
def testQuestion(self):
p = self.Parser()
self.assertEquals(p.parse('QUES', ''), 0)
self.assertEquals(p.parse('QUES', 'a'), 1)
self.assertRaises(tpg.SyntacticError, p.parse, 'QUES', 'a b')
self.assertRaises(tpg.SyntacticError, p.parse, 'QUES', 'a b c d e f')
def testREP1(self):
p = self.Parser()
self.assertEquals(p.parse('REP1', ''), 0)
self.assertRaises(tpg.SyntacticError, p.parse, 'REP1', '1')
self.assertRaises(tpg.SyntacticError, p.parse, 'REP1', '1 2')
self.assertRaises(tpg.SyntacticError, p.parse, 'REP1', '1 2 3 4 5 6')
def testREP2(self):
p = self.Parser()
self.assertRaises(tpg.SyntacticError, p.parse, 'REP2', '1')
self.assertRaises(tpg.SyntacticError, p.parse, 'REP2', '1 2')
self.assertEquals(p.parse('REP2', '1 2 3'), 3)
self.assertRaises(tpg.SyntacticError, p.parse, 'REP2', '1 2 3 4')
self.assertRaises(tpg.SyntacticError, p.parse, 'REP2', '1 2 3 4 5 6')
def testREP3(self):
p = self.Parser()
self.assertEquals(p.parse('REP3', ''), 0)
self.assertEquals(p.parse('REP3', '1'), 1)
self.assertEquals(p.parse('REP3', '1 2'), 2)
self.assertEquals(p.parse('REP3', '1 2 3'), 3)
self.assertEquals(p.parse('REP3', '1 2 3 4'), 4)
self.assertEquals(p.parse('REP3', '1 2 3 4 5'), 5)
self.assertEquals(p.parse('REP3', '1 2 3 4 5 6'), 6)
def testREP4(self):
p = self.Parser()
self.assertEquals(p.parse('REP4', ''), 0)
self.assertEquals(p.parse('REP4', '1'), 1)
self.assertEquals(p.parse('REP4', '1 2'), 2)
self.assertEquals(p.parse('REP4', '1 2 3'), 3)
self.assertRaises(tpg.SyntacticError, p.parse, 'REP4', '1 2 3 4')
self.assertRaises(tpg.SyntacticError, p.parse, 'REP4', '1 2 3 4 5')
self.assertRaises(tpg.SyntacticError, p.parse, 'REP4', '1 2 3 4 5 6')
def testREP5(self):
p = self.Parser()
self.assertRaises(tpg.SyntacticError, p.parse, 'REP5', '')
self.assertRaises(tpg.SyntacticError, p.parse, 'REP5', '1')
self.assertEquals(p.parse('REP5', '1 2'), 2)
self.assertEquals(p.parse('REP5', '1 2 3'), 3)
self.assertEquals(p.parse('REP5', '1 2 3 4 5 6'), 6)
def testREP6(self):
p = self.Parser()
self.assertRaises(tpg.SyntacticError, p.parse, 'REP6', '')
self.assertRaises(tpg.SyntacticError, p.parse, 'REP6', '1')
self.assertEquals(p.parse('REP6', '1 2'), 2)
self.assertEquals(p.parse('REP6', '1 2 3'), 3)
self.assertEquals(p.parse('REP6', '1 2 3 4'), 4)
self.assertEquals(p.parse('REP6', '1 2 3 4 5'), 5)
self.assertRaises(tpg.SyntacticError, p.parse, 'REP6', '1 2 3 4 5 6')
class ArgsTestCase(unittest.TestCase):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
separator spaces '\s+' ;
START/ -> S/ ;
S/ -> ;
"""%tpg.Py()
def testArgs(self):
p = self.Parser()
self.assertRaises(TypeError, p, '', 'a')
self.assertEquals(p('', 'a', 'b'), ('a', 'b', (), {}))
self.assertEquals(p('', 'a', 'b', 'c'), ('a', 'b', ('c',), {}))
self.assertEquals(p('', 'a', 'b', 'c', 'd'), ('a', 'b', ('c', 'd'), {}))
self.assertEquals(p('', 'a', 'b', 'c', 'd', e='e'), ('a', 'b', ('c', 'd'), {'e':'e'}))
self.assertEquals(p('', 'a', 'b', 'c', 'd', e='e', f='f'), ('a', 'b', ('c', 'd'), {'e':'e', 'f':'f'}))
self.assertEquals(p('', 'a', 'b', **({'e':'e', 'f':'f'})), ('a', 'b', (), {'e':'e', 'f':'f'}))
self.assertEquals(p('', 'a', 'b', *('c', 'd')), ('a', 'b', ('c', 'd'), {}))
self.assertEquals(p('', 'a', 'b', *('c', 'd'), **({'e':'e', 'f':'f'})), ('a', 'b', ('c', 'd'), {'e':'e', 'f':'f'}))
class PyExprTestCase(unittest.TestCase):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
START/x ->
$ foo = "*foo*"
( "1" IDENT/x1 IDENT<314>/x2 $ x = x1, x2 $
| "2" STRING<"2">/x
| "3" CODE<$"a"+"b"$>/x
)
;
IDENT/i -> ;
STRING/"a string" -> check $s=="2"$ ;
CODE/$1+2$ -> check $x=="ab"$ ;
"""%tpg.Py()
def testExpr(self):
p = self.Parser()
self.assertEquals(p("1"), ("*foo*", 314))
self.assertEquals(p("2"), "a string")
self.assertEquals(p("3"), 3)
class EmptyChoiceTestCase(unittest.TestCase):
def OK(self):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
A ->
( x # not empty
| x y # not empty
)
;
B ->
( x # not empty
| x y # not empty
| # empty
)
;
C ->
( x # not empty
| x y # not empty
| ( ) # empty
)
;
"""%tpg.Py()
def NOK1(self):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
A ->
( # empty !!!
| x # not empty
| x y # not empty
)
;
"""%tpg.Py()
def NOK2(self):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
B ->
( ( ( ) ) # empty !!!
| x # not empty
| x y # not empty
)
;
"""%tpg.Py()
def NOK3(self):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
C ->
( x # not empty
| # empty !!!
| x y # not empty
)
;
"""%tpg.Py()
def NOK4(self):
class Parser(PARSER):
__doc__ = r"""
set lexer = %(LEXER)s
D ->
( x # not empty
| ( ) # empty !!!
| x y # not empty
)
;
"""%tpg.Py()
def testEmptyLast(self):
self.assertEquals(self.OK(), None)
def testEmptyNonLast(self):
self.assertRaises(tpg.SyntacticError, self.NOK1)
self.assertRaises(tpg.SyntacticError, self.NOK2)
self.assertRaises(tpg.SyntacticError, self.NOK3)
self.assertRaises(tpg.SyntacticError, self.NOK4)
try:
unittest.main()
except SystemExit, failed:
if failed.args[0]:
raise