Path: blob/main/third_party/ply/test/testlex.py
6169 views
# testlex.py12import unittest3try:4import StringIO5except ImportError:6import io as StringIO78import sys9import os10import imp11import warnings1213sys.path.insert(0,"..")14sys.tracebacklimit = 01516import ply.lex1718def make_pymodule_path(filename):19path = os.path.dirname(filename)20file = os.path.basename(filename)21mod, ext = os.path.splitext(file)2223if sys.hexversion >= 0x3020000:24modname = mod+"."+imp.get_tag()+ext25fullpath = os.path.join(path,'__pycache__',modname)26else:27fullpath = filename28return fullpath2930def pymodule_out_exists(filename):31return os.path.exists(make_pymodule_path(filename))3233def pymodule_out_remove(filename):34os.remove(make_pymodule_path(filename))3536def check_expected(result,expected):37if sys.version_info[0] >= 3:38if isinstance(result,str):39result = result.encode('ascii')40if isinstance(expected,str):41expected = expected.encode('ascii')42resultlines = result.splitlines()43expectedlines = expected.splitlines()444546if len(resultlines) != len(expectedlines):47return False4849for rline,eline in zip(resultlines,expectedlines):50if not rline.endswith(eline):51return False52return True5354def run_import(module):55code = "import "+module56exec(code)57del sys.modules[module]5859# Tests related to errors and warnings when building lexers60class LexErrorWarningTests(unittest.TestCase):61def setUp(self):62sys.stderr = StringIO.StringIO()63sys.stdout = StringIO.StringIO()64if sys.hexversion >= 0x3020000:65warnings.filterwarnings('ignore',category=ResourceWarning)6667def tearDown(self):68sys.stderr = sys.__stderr__69sys.stdout = sys.__stdout__70def test_lex_doc1(self):71self.assertRaises(SyntaxError,run_import,"lex_doc1")72result = sys.stderr.getvalue()73self.assert_(check_expected(result,74"lex_doc1.py:18: No regular expression defined for rule 't_NUMBER'\n"))75def test_lex_dup1(self):76self.assertRaises(SyntaxError,run_import,"lex_dup1")77result = sys.stderr.getvalue()78self.assert_(check_expected(result,79"lex_dup1.py:20: Rule t_NUMBER redefined. Previously defined on line 18\n" ))8081def test_lex_dup2(self):82self.assertRaises(SyntaxError,run_import,"lex_dup2")83result = sys.stderr.getvalue()84self.assert_(check_expected(result,85"lex_dup2.py:22: Rule t_NUMBER redefined. Previously defined on line 18\n" ))8687def test_lex_dup3(self):88self.assertRaises(SyntaxError,run_import,"lex_dup3")89result = sys.stderr.getvalue()90self.assert_(check_expected(result,91"lex_dup3.py:20: Rule t_NUMBER redefined. Previously defined on line 18\n" ))9293def test_lex_empty(self):94self.assertRaises(SyntaxError,run_import,"lex_empty")95result = sys.stderr.getvalue()96self.assert_(check_expected(result,97"No rules of the form t_rulename are defined\n"98"No rules defined for state 'INITIAL'\n"))99100def test_lex_error1(self):101run_import("lex_error1")102result = sys.stderr.getvalue()103self.assert_(check_expected(result,104"No t_error rule is defined\n"))105106def test_lex_error2(self):107self.assertRaises(SyntaxError,run_import,"lex_error2")108result = sys.stderr.getvalue()109self.assert_(check_expected(result,110"Rule 't_error' must be defined as a function\n")111)112113def test_lex_error3(self):114self.assertRaises(SyntaxError,run_import,"lex_error3")115result = sys.stderr.getvalue()116self.assert_(check_expected(result,117"lex_error3.py:20: Rule 't_error' requires an argument\n"))118119def test_lex_error4(self):120self.assertRaises(SyntaxError,run_import,"lex_error4")121result = sys.stderr.getvalue()122self.assert_(check_expected(result,123"lex_error4.py:20: Rule 't_error' has too many arguments\n"))124125def test_lex_ignore(self):126self.assertRaises(SyntaxError,run_import,"lex_ignore")127result = sys.stderr.getvalue()128self.assert_(check_expected(result,129"lex_ignore.py:20: Rule 't_ignore' must be defined as a string\n"))130131def test_lex_ignore2(self):132run_import("lex_ignore2")133result = sys.stderr.getvalue()134self.assert_(check_expected(result,135"t_ignore contains a literal backslash '\\'\n"))136137138def test_lex_re1(self):139self.assertRaises(SyntaxError,run_import,"lex_re1")140result = sys.stderr.getvalue()141self.assert_(check_expected(result,142"Invalid regular expression for rule 't_NUMBER'. unbalanced parenthesis\n"))143144def test_lex_re2(self):145self.assertRaises(SyntaxError,run_import,"lex_re2")146result = sys.stderr.getvalue()147self.assert_(check_expected(result,148"Regular expression for rule 't_PLUS' matches empty string\n"))149150def test_lex_re3(self):151self.assertRaises(SyntaxError,run_import,"lex_re3")152result = sys.stderr.getvalue()153self.assert_(check_expected(result,154"Invalid regular expression for rule 't_POUND'. unbalanced parenthesis\n"155"Make sure '#' in rule 't_POUND' is escaped with '\\#'\n"))156157def test_lex_rule1(self):158self.assertRaises(SyntaxError,run_import,"lex_rule1")159result = sys.stderr.getvalue()160self.assert_(check_expected(result,161"t_NUMBER not defined as a function or string\n"))162163def test_lex_rule2(self):164self.assertRaises(SyntaxError,run_import,"lex_rule2")165result = sys.stderr.getvalue()166self.assert_(check_expected(result,167"lex_rule2.py:18: Rule 't_NUMBER' requires an argument\n"))168169def test_lex_rule3(self):170self.assertRaises(SyntaxError,run_import,"lex_rule3")171result = sys.stderr.getvalue()172self.assert_(check_expected(result,173"lex_rule3.py:18: Rule 't_NUMBER' has too many arguments\n"))174175176def test_lex_state1(self):177self.assertRaises(SyntaxError,run_import,"lex_state1")178result = sys.stderr.getvalue()179self.assert_(check_expected(result,180"states must be defined as a tuple or list\n"))181182def test_lex_state2(self):183self.assertRaises(SyntaxError,run_import,"lex_state2")184result = sys.stderr.getvalue()185self.assert_(check_expected(result,186"Invalid state specifier 'comment'. Must be a tuple (statename,'exclusive|inclusive')\n"187"Invalid state specifier 'example'. Must be a tuple (statename,'exclusive|inclusive')\n"))188189def test_lex_state3(self):190self.assertRaises(SyntaxError,run_import,"lex_state3")191result = sys.stderr.getvalue()192self.assert_(check_expected(result,193"State name 1 must be a string\n"194"No rules defined for state 'example'\n"))195196def test_lex_state4(self):197self.assertRaises(SyntaxError,run_import,"lex_state4")198result = sys.stderr.getvalue()199self.assert_(check_expected(result,200"State type for state comment must be 'inclusive' or 'exclusive'\n"))201202203def test_lex_state5(self):204self.assertRaises(SyntaxError,run_import,"lex_state5")205result = sys.stderr.getvalue()206self.assert_(check_expected(result,207"State 'comment' already defined\n"))208209def test_lex_state_noerror(self):210run_import("lex_state_noerror")211result = sys.stderr.getvalue()212self.assert_(check_expected(result,213"No error rule is defined for exclusive state 'comment'\n"))214215def test_lex_state_norule(self):216self.assertRaises(SyntaxError,run_import,"lex_state_norule")217result = sys.stderr.getvalue()218self.assert_(check_expected(result,219"No rules defined for state 'example'\n"))220221def test_lex_token1(self):222self.assertRaises(SyntaxError,run_import,"lex_token1")223result = sys.stderr.getvalue()224self.assert_(check_expected(result,225"No token list is defined\n"226"Rule 't_NUMBER' defined for an unspecified token NUMBER\n"227"Rule 't_PLUS' defined for an unspecified token PLUS\n"228"Rule 't_MINUS' defined for an unspecified token MINUS\n"229))230231def test_lex_token2(self):232self.assertRaises(SyntaxError,run_import,"lex_token2")233result = sys.stderr.getvalue()234self.assert_(check_expected(result,235"tokens must be a list or tuple\n"236"Rule 't_NUMBER' defined for an unspecified token NUMBER\n"237"Rule 't_PLUS' defined for an unspecified token PLUS\n"238"Rule 't_MINUS' defined for an unspecified token MINUS\n"239))240241def test_lex_token3(self):242self.assertRaises(SyntaxError,run_import,"lex_token3")243result = sys.stderr.getvalue()244self.assert_(check_expected(result,245"Rule 't_MINUS' defined for an unspecified token MINUS\n"))246247248def test_lex_token4(self):249self.assertRaises(SyntaxError,run_import,"lex_token4")250result = sys.stderr.getvalue()251self.assert_(check_expected(result,252"Bad token name '-'\n"))253254255def test_lex_token5(self):256try:257run_import("lex_token5")258except ply.lex.LexError:259e = sys.exc_info()[1]260self.assert_(check_expected(str(e),"lex_token5.py:19: Rule 't_NUMBER' returned an unknown token type 'NUM'"))261262def test_lex_token_dup(self):263run_import("lex_token_dup")264result = sys.stderr.getvalue()265self.assert_(check_expected(result,266"Token 'MINUS' multiply defined\n"))267268269def test_lex_literal1(self):270self.assertRaises(SyntaxError,run_import,"lex_literal1")271result = sys.stderr.getvalue()272self.assert_(check_expected(result,273"Invalid literal '**'. Must be a single character\n"))274275def test_lex_literal2(self):276self.assertRaises(SyntaxError,run_import,"lex_literal2")277result = sys.stderr.getvalue()278self.assert_(check_expected(result,279"Invalid literals specification. literals must be a sequence of characters\n"))280281import os282import subprocess283import shutil284285# Tests related to various build options associated with lexers286class LexBuildOptionTests(unittest.TestCase):287def setUp(self):288sys.stderr = StringIO.StringIO()289sys.stdout = StringIO.StringIO()290def tearDown(self):291sys.stderr = sys.__stderr__292sys.stdout = sys.__stdout__293try:294shutil.rmtree("lexdir")295except OSError:296pass297298def test_lex_module(self):299run_import("lex_module")300result = sys.stdout.getvalue()301self.assert_(check_expected(result,302"(NUMBER,3,1,0)\n"303"(PLUS,'+',1,1)\n"304"(NUMBER,4,1,2)\n"))305306def test_lex_object(self):307run_import("lex_object")308result = sys.stdout.getvalue()309self.assert_(check_expected(result,310"(NUMBER,3,1,0)\n"311"(PLUS,'+',1,1)\n"312"(NUMBER,4,1,2)\n"))313314def test_lex_closure(self):315run_import("lex_closure")316result = sys.stdout.getvalue()317self.assert_(check_expected(result,318"(NUMBER,3,1,0)\n"319"(PLUS,'+',1,1)\n"320"(NUMBER,4,1,2)\n"))321def test_lex_optimize(self):322try:323os.remove("lextab.py")324except OSError:325pass326try:327os.remove("lextab.pyc")328except OSError:329pass330try:331os.remove("lextab.pyo")332except OSError:333pass334run_import("lex_optimize")335336result = sys.stdout.getvalue()337self.assert_(check_expected(result,338"(NUMBER,3,1,0)\n"339"(PLUS,'+',1,1)\n"340"(NUMBER,4,1,2)\n"))341self.assert_(os.path.exists("lextab.py"))342343344p = subprocess.Popen([sys.executable,'-O','lex_optimize.py'],345stdout=subprocess.PIPE)346result = p.stdout.read()347348self.assert_(check_expected(result,349"(NUMBER,3,1,0)\n"350"(PLUS,'+',1,1)\n"351"(NUMBER,4,1,2)\n"))352self.assert_(pymodule_out_exists("lextab.pyo"))353354pymodule_out_remove("lextab.pyo")355p = subprocess.Popen([sys.executable,'-OO','lex_optimize.py'],356stdout=subprocess.PIPE)357result = p.stdout.read()358self.assert_(check_expected(result,359"(NUMBER,3,1,0)\n"360"(PLUS,'+',1,1)\n"361"(NUMBER,4,1,2)\n"))362self.assert_(pymodule_out_exists("lextab.pyo"))363try:364os.remove("lextab.py")365except OSError:366pass367try:368pymodule_out_remove("lextab.pyc")369except OSError:370pass371try:372pymodule_out_remove("lextab.pyo")373except OSError:374pass375376def test_lex_optimize2(self):377try:378os.remove("opt2tab.py")379except OSError:380pass381try:382os.remove("opt2tab.pyc")383except OSError:384pass385try:386os.remove("opt2tab.pyo")387except OSError:388pass389run_import("lex_optimize2")390result = sys.stdout.getvalue()391self.assert_(check_expected(result,392"(NUMBER,3,1,0)\n"393"(PLUS,'+',1,1)\n"394"(NUMBER,4,1,2)\n"))395self.assert_(os.path.exists("opt2tab.py"))396397p = subprocess.Popen([sys.executable,'-O','lex_optimize2.py'],398stdout=subprocess.PIPE)399result = p.stdout.read()400self.assert_(check_expected(result,401"(NUMBER,3,1,0)\n"402"(PLUS,'+',1,1)\n"403"(NUMBER,4,1,2)\n"))404self.assert_(pymodule_out_exists("opt2tab.pyo"))405pymodule_out_remove("opt2tab.pyo")406p = subprocess.Popen([sys.executable,'-OO','lex_optimize2.py'],407stdout=subprocess.PIPE)408result = p.stdout.read()409self.assert_(check_expected(result,410"(NUMBER,3,1,0)\n"411"(PLUS,'+',1,1)\n"412"(NUMBER,4,1,2)\n"))413self.assert_(pymodule_out_exists("opt2tab.pyo"))414try:415os.remove("opt2tab.py")416except OSError:417pass418try:419pymodule_out_remove("opt2tab.pyc")420except OSError:421pass422try:423pymodule_out_remove("opt2tab.pyo")424except OSError:425pass426427def test_lex_optimize3(self):428try:429shutil.rmtree("lexdir")430except OSError:431pass432433os.mkdir("lexdir")434os.mkdir("lexdir/sub")435open("lexdir/__init__.py","w").write("")436open("lexdir/sub/__init__.py","w").write("")437run_import("lex_optimize3")438result = sys.stdout.getvalue()439self.assert_(check_expected(result,440"(NUMBER,3,1,0)\n"441"(PLUS,'+',1,1)\n"442"(NUMBER,4,1,2)\n"))443self.assert_(os.path.exists("lexdir/sub/calctab.py"))444445p = subprocess.Popen([sys.executable,'-O','lex_optimize3.py'],446stdout=subprocess.PIPE)447result = p.stdout.read()448self.assert_(check_expected(result,449"(NUMBER,3,1,0)\n"450"(PLUS,'+',1,1)\n"451"(NUMBER,4,1,2)\n"))452self.assert_(pymodule_out_exists("lexdir/sub/calctab.pyo"))453pymodule_out_remove("lexdir/sub/calctab.pyo")454p = subprocess.Popen([sys.executable,'-OO','lex_optimize3.py'],455stdout=subprocess.PIPE)456result = p.stdout.read()457self.assert_(check_expected(result,458"(NUMBER,3,1,0)\n"459"(PLUS,'+',1,1)\n"460"(NUMBER,4,1,2)\n"))461self.assert_(pymodule_out_exists("lexdir/sub/calctab.pyo"))462try:463shutil.rmtree("lexdir")464except OSError:465pass466467def test_lex_opt_alias(self):468try:469os.remove("aliastab.py")470except OSError:471pass472try:473os.remove("aliastab.pyc")474except OSError:475pass476try:477os.remove("aliastab.pyo")478except OSError:479pass480run_import("lex_opt_alias")481result = sys.stdout.getvalue()482self.assert_(check_expected(result,483"(NUMBER,3,1,0)\n"484"(+,'+',1,1)\n"485"(NUMBER,4,1,2)\n"))486self.assert_(os.path.exists("aliastab.py"))487488p = subprocess.Popen([sys.executable,'-O','lex_opt_alias.py'],489stdout=subprocess.PIPE)490result = p.stdout.read()491self.assert_(check_expected(result,492"(NUMBER,3,1,0)\n"493"(+,'+',1,1)\n"494"(NUMBER,4,1,2)\n"))495self.assert_(pymodule_out_exists("aliastab.pyo"))496pymodule_out_remove("aliastab.pyo")497p = subprocess.Popen([sys.executable,'-OO','lex_opt_alias.py'],498stdout=subprocess.PIPE)499result = p.stdout.read()500self.assert_(check_expected(result,501"(NUMBER,3,1,0)\n"502"(+,'+',1,1)\n"503"(NUMBER,4,1,2)\n"))504self.assert_(pymodule_out_exists("aliastab.pyo"))505try:506os.remove("aliastab.py")507except OSError:508pass509try:510pymodule_out_remove("aliastab.pyc")511except OSError:512pass513try:514pymodule_out_remove("aliastab.pyo")515except OSError:516pass517518def test_lex_many_tokens(self):519try:520os.remove("manytab.py")521except OSError:522pass523try:524os.remove("manytab.pyc")525except OSError:526pass527try:528os.remove("manytab.pyo")529except OSError:530pass531run_import("lex_many_tokens")532result = sys.stdout.getvalue()533self.assert_(check_expected(result,534"(TOK34,'TOK34:',1,0)\n"535"(TOK143,'TOK143:',1,7)\n"536"(TOK269,'TOK269:',1,15)\n"537"(TOK372,'TOK372:',1,23)\n"538"(TOK452,'TOK452:',1,31)\n"539"(TOK561,'TOK561:',1,39)\n"540"(TOK999,'TOK999:',1,47)\n"541))542543self.assert_(os.path.exists("manytab.py"))544545p = subprocess.Popen([sys.executable,'-O','lex_many_tokens.py'],546stdout=subprocess.PIPE)547result = p.stdout.read()548self.assert_(check_expected(result,549"(TOK34,'TOK34:',1,0)\n"550"(TOK143,'TOK143:',1,7)\n"551"(TOK269,'TOK269:',1,15)\n"552"(TOK372,'TOK372:',1,23)\n"553"(TOK452,'TOK452:',1,31)\n"554"(TOK561,'TOK561:',1,39)\n"555"(TOK999,'TOK999:',1,47)\n"556))557558self.assert_(pymodule_out_exists("manytab.pyo"))559pymodule_out_remove("manytab.pyo")560try:561os.remove("manytab.py")562except OSError:563pass564try:565os.remove("manytab.pyc")566except OSError:567pass568try:569os.remove("manytab.pyo")570except OSError:571pass572573# Tests related to run-time behavior of lexers574class LexRunTests(unittest.TestCase):575def setUp(self):576sys.stderr = StringIO.StringIO()577sys.stdout = StringIO.StringIO()578def tearDown(self):579sys.stderr = sys.__stderr__580sys.stdout = sys.__stdout__581582def test_lex_hedit(self):583run_import("lex_hedit")584result = sys.stdout.getvalue()585self.assert_(check_expected(result,586"(H_EDIT_DESCRIPTOR,'abc',1,0)\n"587"(H_EDIT_DESCRIPTOR,'abcdefghij',1,6)\n"588"(H_EDIT_DESCRIPTOR,'xy',1,20)\n"))589590def test_lex_state_try(self):591run_import("lex_state_try")592result = sys.stdout.getvalue()593self.assert_(check_expected(result,594"(NUMBER,'3',1,0)\n"595"(PLUS,'+',1,2)\n"596"(NUMBER,'4',1,4)\n"597"Entering comment state\n"598"comment body LexToken(body_part,'This is a comment */',1,9)\n"599"(PLUS,'+',1,30)\n"600"(NUMBER,'10',1,32)\n"601))602603604605unittest.main()606607608