unitTests.py 196 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054
  1. # -*- coding: utf-8 -*-
  2. #
  3. # unitTests.py
  4. #
  5. # Unit tests for pyparsing module
  6. #
  7. # Copyright 2002-2018, Paul McGuire
  8. #
  9. #
  10. from __future__ import division
  11. from unittest import TestCase, TestSuite, TextTestRunner
  12. import datetime
  13. from pyparsing import ParseException, pyparsing_test as ppt
  14. import pyparsing as pp
  15. import sys
  16. PY_3 = sys.version.startswith('3')
  17. if PY_3:
  18. import builtins
  19. print_ = getattr(builtins, "print")
  20. # catch calls to builtin print(), should be print_
  21. def printX(*args, **kwargs):
  22. raise Exception("Test coding error: using print() directly, should use print_()")
  23. globals()['print'] = printX
  24. from io import StringIO
  25. else:
  26. def _print(*args, **kwargs):
  27. if 'end' in kwargs:
  28. sys.stdout.write(' '.join(map(str,args)) + kwargs['end'])
  29. else:
  30. sys.stdout.write(' '.join(map(str,args)) + '\n')
  31. print_ = _print
  32. from cStringIO import StringIO
  33. # see which Python implementation we are running
  34. CPYTHON_ENV = (sys.platform == "win32")
  35. IRON_PYTHON_ENV = (sys.platform == "cli")
  36. JYTHON_ENV = sys.platform.startswith("java")
  37. TEST_USING_PACKRAT = True
  38. #~ TEST_USING_PACKRAT = False
  39. VERBOSE = True
  40. # simple utility for flattening nested lists
  41. def flatten(L):
  42. if type(L) is not list: return [L]
  43. if L == []: return L
  44. return flatten(L[0]) + flatten(L[1:])
  45. """
  46. class ParseTest(TestCase):
  47. def setUp(self):
  48. pass
  49. def runTest(self):
  50. self.assertTrue(1==1, "we've got bigger problems...")
  51. def tearDown(self):
  52. pass
  53. """
  54. class AutoReset(object):
  55. def __init__(self, *args):
  56. ob = args[0]
  57. attrnames = args[1:]
  58. self.ob = ob
  59. self.save_attrs = attrnames
  60. self.save_values = [getattr(ob, attrname) for attrname in attrnames]
  61. def __enter__(self):
  62. pass
  63. def __exit__(self, *args):
  64. for attr, value in zip(self.save_attrs, self.save_values):
  65. setattr(self.ob, attr, value)
  66. BUFFER_OUTPUT = True
  67. class ParseTestCase(ppt.TestParseResultsAsserts, TestCase):
  68. def __init__(self):
  69. super(ParseTestCase, self).__init__(methodName='_runTest')
  70. self.expect_traceback = False
  71. self.expect_warning = False
  72. def _runTest(self):
  73. buffered_stdout = StringIO()
  74. try:
  75. with AutoReset(sys, 'stdout', 'stderr'):
  76. try:
  77. if BUFFER_OUTPUT:
  78. sys.stdout = buffered_stdout
  79. sys.stderr = buffered_stdout
  80. print_(">>>> Starting test",str(self))
  81. with ppt.reset_pyparsing_context():
  82. self.runTest()
  83. finally:
  84. print_("<<<< End of test",str(self))
  85. print_()
  86. output = buffered_stdout.getvalue()
  87. if "Traceback" in output and not self.expect_traceback:
  88. raise Exception("traceback in stdout")
  89. if "Warning" in output and not self.expect_warning:
  90. raise Exception("warning in stdout")
  91. except Exception as exc:
  92. if BUFFER_OUTPUT:
  93. print_()
  94. print_(buffered_stdout.getvalue())
  95. raise
  96. def runTest(self):
  97. pass
  98. def __str__(self):
  99. return self.__class__.__name__
  100. class PyparsingTestInit(ParseTestCase):
  101. def setUp(self):
  102. from pyparsing import __version__ as pyparsingVersion, __versionTime__ as pyparsingVersionTime
  103. print_("Beginning test of pyparsing, version", pyparsingVersion, pyparsingVersionTime)
  104. print_("Python version", sys.version)
  105. def tearDown(self):
  106. pass
  107. class ParseFourFnTest(ParseTestCase):
  108. def runTest(self):
  109. import examples.fourFn as fourFn
  110. def test(s,ans):
  111. fourFn.exprStack = []
  112. results = fourFn.BNF().parseString( s )
  113. resultValue = fourFn.evaluateStack( fourFn.exprStack )
  114. self.assertTrue(resultValue == ans, "failed to evaluate %s, got %f" % ( s, resultValue ))
  115. print_(s, "->", resultValue)
  116. from math import pi,exp
  117. e = exp(1)
  118. test( "9", 9 )
  119. test( "9 + 3 + 6", 18 )
  120. test( "9 + 3 / 11", 9.0+3.0/11.0)
  121. test( "(9 + 3)", 12 )
  122. test( "(9+3) / 11", (9.0+3.0)/11.0 )
  123. test( "9 - (12 - 6)", 3)
  124. test( "2*3.14159", 6.28318)
  125. test( "3.1415926535*3.1415926535 / 10", 3.1415926535*3.1415926535/10.0 )
  126. test( "PI * PI / 10", pi*pi/10.0 )
  127. test( "PI*PI/10", pi*pi/10.0 )
  128. test( "6.02E23 * 8.048", 6.02E23 * 8.048 )
  129. test( "e / 3", e/3.0 )
  130. test( "sin(PI/2)", 1.0 )
  131. test( "trunc(E)", 2.0 )
  132. test( "E^PI", e**pi )
  133. test( "2^3^2", 2**3**2)
  134. test( "2^3+2", 2**3+2)
  135. test( "2^9", 2**9 )
  136. test( "sgn(-2)", -1 )
  137. test( "sgn(0)", 0 )
  138. test( "sgn(0.1)", 1 )
  139. class ParseSQLTest(ParseTestCase):
  140. def runTest(self):
  141. import examples.simpleSQL as simpleSQL
  142. def test(s, numToks, errloc=-1):
  143. try:
  144. sqlToks = flatten(simpleSQL.simpleSQL.parseString(s).asList())
  145. print_(s,sqlToks,len(sqlToks))
  146. self.assertEqual(len(sqlToks), numToks,
  147. "invalid parsed tokens, expected {0}, found {1} ({2})".format(numToks,
  148. len(sqlToks),
  149. sqlToks))
  150. except ParseException as e:
  151. if errloc >= 0:
  152. self.assertEqual(e.loc, errloc, "expected error at {0}, found at {1}".format(errloc, e.loc))
  153. test( "SELECT * from XYZZY, ABC", 6 )
  154. test( "select * from SYS.XYZZY", 5 )
  155. test( "Select A from Sys.dual", 5 )
  156. test( "Select A,B,C from Sys.dual", 7 )
  157. test( "Select A, B, C from Sys.dual", 7 )
  158. test( "Select A, B, C from Sys.dual, Table2 ", 8 )
  159. test( "Xelect A, B, C from Sys.dual", 0, 0 )
  160. test( "Select A, B, C frox Sys.dual", 0, 15 )
  161. test( "Select", 0, 6 )
  162. test( "Select &&& frox Sys.dual", 0, 7 )
  163. test( "Select A from Sys.dual where a in ('RED','GREEN','BLUE')", 12 )
  164. test( "Select A from Sys.dual where a in ('RED','GREEN','BLUE') and b in (10,20,30)", 20 )
  165. test( "Select A,b from table1,table2 where table1.id eq table2.id -- test out comparison operators", 10 )
  166. class ParseConfigFileTest(ParseTestCase):
  167. def runTest(self):
  168. from examples import configParse
  169. def test(fnam,numToks,resCheckList):
  170. print_("Parsing",fnam,"...", end=' ')
  171. with open(fnam) as infile:
  172. iniFileLines = "\n".join(infile.read().splitlines())
  173. iniData = configParse.inifile_BNF().parseString( iniFileLines )
  174. print_(len(flatten(iniData.asList())))
  175. print_(list(iniData.keys()))
  176. self.assertEqual(len(flatten(iniData.asList())), numToks, "file %s not parsed correctly" % fnam)
  177. for chk in resCheckList:
  178. var = iniData
  179. for attr in chk[0].split('.'):
  180. var = getattr(var, attr)
  181. print_(chk[0], var, chk[1])
  182. self.assertEqual(var, chk[1],
  183. "ParseConfigFileTest: failed to parse ini {0!r} as expected {1}, found {2}".format(chk[0],
  184. chk[1],
  185. var))
  186. print_("OK")
  187. test("test/karthik.ini", 23,
  188. [ ("users.K","8"),
  189. ("users.mod_scheme","'QPSK'"),
  190. ("users.Na", "K+2") ]
  191. )
  192. test("examples/Setup.ini", 125,
  193. [ ("Startup.audioinf", "M3i"),
  194. ("Languages.key1", "0x0003"),
  195. ("test.foo","bar") ] )
  196. class ParseJSONDataTest(ParseTestCase):
  197. def runTest(self):
  198. from examples.jsonParser import jsonObject
  199. from test.jsonParserTests import test1,test2,test3,test4,test5
  200. expected = [
  201. [['glossary',
  202. [['title', 'example glossary'],
  203. ['GlossDiv',
  204. [['title', 'S'],
  205. ['GlossList',
  206. [[['ID', 'SGML'],
  207. ['SortAs', 'SGML'],
  208. ['GlossTerm', 'Standard Generalized Markup Language'],
  209. ['Acronym', 'SGML'],
  210. ['LargestPrimeLessThan100', 97],
  211. ['AvogadroNumber', 6.02e+23],
  212. ['EvenPrimesGreaterThan2', None],
  213. ['PrimesLessThan10', [2, 3, 5, 7]],
  214. ['WMDsFound', False],
  215. ['IraqAlQaedaConnections', None],
  216. ['Abbrev', 'ISO 8879:1986'],
  217. ['GlossDef',
  218. 'A meta-markup language, used to create markup languages such as '
  219. 'DocBook.'],
  220. ['GlossSeeAlso', ['GML', 'XML', 'markup']],
  221. ['EmptyDict', []],
  222. ['EmptyList', [[]]]]]]]]]
  223. ]]
  224. ,
  225. [['menu',
  226. [['id', 'file'],
  227. ['value', 'File:'],
  228. ['popup',
  229. [['menuitem',
  230. [[['value', 'New'], ['onclick', 'CreateNewDoc()']],
  231. [['value', 'Open'], ['onclick', 'OpenDoc()']],
  232. [['value', 'Close'], ['onclick', 'CloseDoc()']]]]]]]]]
  233. ,
  234. [['widget',
  235. [['debug', 'on'],
  236. ['window',
  237. [['title', 'Sample Konfabulator Widget'],
  238. ['name', 'main_window'],
  239. ['width', 500],
  240. ['height', 500]]],
  241. ['image',
  242. [['src', 'Images/Sun.png'],
  243. ['name', 'sun1'],
  244. ['hOffset', 250],
  245. ['vOffset', 250],
  246. ['alignment', 'center']]],
  247. ['text',
  248. [['data', 'Click Here'],
  249. ['size', 36],
  250. ['style', 'bold'],
  251. ['name', 'text1'],
  252. ['hOffset', 250],
  253. ['vOffset', 100],
  254. ['alignment', 'center'],
  255. ['onMouseUp', 'sun1.opacity = (sun1.opacity / 100) * 90;']]]]]]
  256. ,
  257. [['web-app',
  258. [['servlet',
  259. [[['servlet-name', 'cofaxCDS'],
  260. ['servlet-class', 'org.cofax.cds.CDSServlet'],
  261. ['init-param',
  262. [['configGlossary:installationAt', 'Philadelphia, PA'],
  263. ['configGlossary:adminEmail', 'ksm@pobox.com'],
  264. ['configGlossary:poweredBy', 'Cofax'],
  265. ['configGlossary:poweredByIcon', '/images/cofax.gif'],
  266. ['configGlossary:staticPath', '/content/static'],
  267. ['templateProcessorClass', 'org.cofax.WysiwygTemplate'],
  268. ['templateLoaderClass', 'org.cofax.FilesTemplateLoader'],
  269. ['templatePath', 'templates'],
  270. ['templateOverridePath', ''],
  271. ['defaultListTemplate', 'listTemplate.htm'],
  272. ['defaultFileTemplate', 'articleTemplate.htm'],
  273. ['useJSP', False],
  274. ['jspListTemplate', 'listTemplate.jsp'],
  275. ['jspFileTemplate', 'articleTemplate.jsp'],
  276. ['cachePackageTagsTrack', 200],
  277. ['cachePackageTagsStore', 200],
  278. ['cachePackageTagsRefresh', 60],
  279. ['cacheTemplatesTrack', 100],
  280. ['cacheTemplatesStore', 50],
  281. ['cacheTemplatesRefresh', 15],
  282. ['cachePagesTrack', 200],
  283. ['cachePagesStore', 100],
  284. ['cachePagesRefresh', 10],
  285. ['cachePagesDirtyRead', 10],
  286. ['searchEngineListTemplate', 'forSearchEnginesList.htm'],
  287. ['searchEngineFileTemplate', 'forSearchEngines.htm'],
  288. ['searchEngineRobotsDb', 'WEB-INF/robots.db'],
  289. ['useDataStore', True],
  290. ['dataStoreClass', 'org.cofax.SqlDataStore'],
  291. ['redirectionClass', 'org.cofax.SqlRedirection'],
  292. ['dataStoreName', 'cofax'],
  293. ['dataStoreDriver', 'com.microsoft.jdbc.sqlserver.SQLServerDriver'],
  294. ['dataStoreUrl',
  295. 'jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon'],
  296. ['dataStoreUser', 'sa'],
  297. ['dataStorePassword', 'dataStoreTestQuery'],
  298. ['dataStoreTestQuery', "SET NOCOUNT ON;select test='test';"],
  299. ['dataStoreLogFile', '/usr/local/tomcat/logs/datastore.log'],
  300. ['dataStoreInitConns', 10],
  301. ['dataStoreMaxConns', 100],
  302. ['dataStoreConnUsageLimit', 100],
  303. ['dataStoreLogLevel', 'debug'],
  304. ['maxUrlLength', 500]]]],
  305. [['servlet-name', 'cofaxEmail'],
  306. ['servlet-class', 'org.cofax.cds.EmailServlet'],
  307. ['init-param', [['mailHost', 'mail1'], ['mailHostOverride', 'mail2']]]],
  308. [['servlet-name', 'cofaxAdmin'],
  309. ['servlet-class', 'org.cofax.cds.AdminServlet']],
  310. [['servlet-name', 'fileServlet'],
  311. ['servlet-class', 'org.cofax.cds.FileServlet']],
  312. [['servlet-name', 'cofaxTools'],
  313. ['servlet-class', 'org.cofax.cms.CofaxToolsServlet'],
  314. ['init-param',
  315. [['templatePath', 'toolstemplates/'],
  316. ['log', 1],
  317. ['logLocation', '/usr/local/tomcat/logs/CofaxTools.log'],
  318. ['logMaxSize', ''],
  319. ['dataLog', 1],
  320. ['dataLogLocation', '/usr/local/tomcat/logs/dataLog.log'],
  321. ['dataLogMaxSize', ''],
  322. ['removePageCache', '/content/admin/remove?cache=pages&id='],
  323. ['removeTemplateCache', '/content/admin/remove?cache=templates&id='],
  324. ['fileTransferFolder',
  325. '/usr/local/tomcat/webapps/content/fileTransferFolder'],
  326. ['lookInContext', 1],
  327. ['adminGroupID', 4],
  328. ['betaServer', True]]]]]],
  329. ['servlet-mapping',
  330. [['cofaxCDS', '/'],
  331. ['cofaxEmail', '/cofaxutil/aemail/*'],
  332. ['cofaxAdmin', '/admin/*'],
  333. ['fileServlet', '/static/*'],
  334. ['cofaxTools', '/tools/*']]],
  335. ['taglib',
  336. [['taglib-uri', 'cofax.tld'],
  337. ['taglib-location', '/WEB-INF/tlds/cofax.tld']]]]]]
  338. ,
  339. [['menu',
  340. [['header', 'SVG Viewer'],
  341. ['items',
  342. [[['id', 'Open']],
  343. [['id', 'OpenNew'], ['label', 'Open New']],
  344. None,
  345. [['id', 'ZoomIn'], ['label', 'Zoom In']],
  346. [['id', 'ZoomOut'], ['label', 'Zoom Out']],
  347. [['id', 'OriginalView'], ['label', 'Original View']],
  348. None,
  349. [['id', 'Quality']],
  350. [['id', 'Pause']],
  351. [['id', 'Mute']],
  352. None,
  353. [['id', 'Find'], ['label', 'Find...']],
  354. [['id', 'FindAgain'], ['label', 'Find Again']],
  355. [['id', 'Copy']],
  356. [['id', 'CopyAgain'], ['label', 'Copy Again']],
  357. [['id', 'CopySVG'], ['label', 'Copy SVG']],
  358. [['id', 'ViewSVG'], ['label', 'View SVG']],
  359. [['id', 'ViewSource'], ['label', 'View Source']],
  360. [['id', 'SaveAs'], ['label', 'Save As']],
  361. None,
  362. [['id', 'Help']],
  363. [['id', 'About'], ['label', 'About Adobe CVG Viewer...']]]]]]]
  364. ,
  365. ]
  366. for t, exp in zip((test1,test2,test3,test4,test5), expected):
  367. result = jsonObject.parseString(t)
  368. result.pprint()
  369. self.assertEqual(result.asList(), exp, "failed test {0}".format(t))
  370. class ParseCommaSeparatedValuesTest(ParseTestCase):
  371. def runTest(self):
  372. from pyparsing import commaSeparatedList
  373. testData = [
  374. "a,b,c,100.2,,3",
  375. "d, e, j k , m ",
  376. "'Hello, World', f, g , , 5.1,x",
  377. "John Doe, 123 Main St., Cleveland, Ohio",
  378. "Jane Doe, 456 St. James St., Los Angeles , California ",
  379. "",
  380. ]
  381. testVals = [
  382. [ (3,'100.2'), (4,''), (5, '3') ],
  383. [ (2, 'j k'), (3, 'm') ],
  384. [ (0, "'Hello, World'"), (2, 'g'), (3, '') ],
  385. [ (0,'John Doe'), (1, '123 Main St.'), (2, 'Cleveland'), (3, 'Ohio') ],
  386. [ (0,'Jane Doe'), (1, '456 St. James St.'), (2, 'Los Angeles'), (3, 'California') ]
  387. ]
  388. for line,tests in zip(testData, testVals):
  389. print_("Parsing: \""+line+"\" ->", end=' ')
  390. results = commaSeparatedList.parseString(line)
  391. print_(results.asList())
  392. for t in tests:
  393. if not(len(results)>t[0] and results[t[0]] == t[1]):
  394. print_("$$$", results.dump())
  395. print_("$$$", results[0])
  396. self.assertTrue(len(results)>t[0] and results[t[0]] == t[1],
  397. "failed on %s, item %d s/b '%s', got '%s'" % (line, t[0], t[1], str(results.asList())))
  398. class ParseEBNFTest(ParseTestCase):
  399. def runTest(self):
  400. from examples import ebnf
  401. from pyparsing import Word, quotedString, alphas, nums
  402. print_('Constructing EBNF parser with pyparsing...')
  403. grammar = '''
  404. syntax = (syntax_rule), {(syntax_rule)};
  405. syntax_rule = meta_identifier, '=', definitions_list, ';';
  406. definitions_list = single_definition, {'|', single_definition};
  407. single_definition = syntactic_term, {',', syntactic_term};
  408. syntactic_term = syntactic_factor,['-', syntactic_factor];
  409. syntactic_factor = [integer, '*'], syntactic_primary;
  410. syntactic_primary = optional_sequence | repeated_sequence |
  411. grouped_sequence | meta_identifier | terminal_string;
  412. optional_sequence = '[', definitions_list, ']';
  413. repeated_sequence = '{', definitions_list, '}';
  414. grouped_sequence = '(', definitions_list, ')';
  415. (*
  416. terminal_string = "'", character - "'", {character - "'"}, "'" |
  417. '"', character - '"', {character - '"'}, '"';
  418. meta_identifier = letter, {letter | digit};
  419. integer = digit, {digit};
  420. *)
  421. '''
  422. table = {}
  423. table['terminal_string'] = quotedString
  424. table['meta_identifier'] = Word(alphas+"_", alphas+"_"+nums)
  425. table['integer'] = Word(nums)
  426. print_('Parsing EBNF grammar with EBNF parser...')
  427. parsers = ebnf.parse(grammar, table)
  428. ebnf_parser = parsers['syntax']
  429. print_("-","\n- ".join(parsers.keys()))
  430. self.assertEqual(len(list(parsers.keys())), 13, "failed to construct syntax grammar")
  431. print_('Parsing EBNF grammar with generated EBNF parser...')
  432. parsed_chars = ebnf_parser.parseString(grammar)
  433. parsed_char_len = len(parsed_chars)
  434. print_("],\n".join(str( parsed_chars.asList() ).split("],")))
  435. self.assertEqual(len(flatten(parsed_chars.asList())), 98, "failed to tokenize grammar correctly")
  436. class ParseIDLTest(ParseTestCase):
  437. def runTest(self):
  438. from examples import idlParse
  439. def test( strng, numToks, errloc=0 ):
  440. print_(strng)
  441. try:
  442. bnf = idlParse.CORBA_IDL_BNF()
  443. tokens = bnf.parseString( strng )
  444. print_("tokens = ")
  445. tokens.pprint()
  446. tokens = flatten( tokens.asList() )
  447. print_(len(tokens))
  448. self.assertEqual(len(tokens), numToks, "error matching IDL string, %s -> %s" % (strng, str(tokens)))
  449. except ParseException as err:
  450. print_(err.line)
  451. print_(" "*(err.column-1) + "^")
  452. print_(err)
  453. self.assertEqual(numToks, 0, "unexpected ParseException while parsing %s, %s" % (strng, str(err)))
  454. self.assertEqual(err.loc, errloc,
  455. "expected ParseException at %d, found exception at %d" % (errloc, err.loc))
  456. test(
  457. """
  458. /*
  459. * a block comment *
  460. */
  461. typedef string[10] tenStrings;
  462. typedef sequence<string> stringSeq;
  463. typedef sequence< sequence<string> > stringSeqSeq;
  464. interface QoSAdmin {
  465. stringSeq method1( in string arg1, inout long arg2 );
  466. stringSeqSeq method2( in string arg1, inout long arg2, inout long arg3);
  467. string method3();
  468. };
  469. """, 59
  470. )
  471. test(
  472. """
  473. /*
  474. * a block comment *
  475. */
  476. typedef string[10] tenStrings;
  477. typedef
  478. /** ** *** **** *
  479. * a block comment *
  480. */
  481. sequence<string> /*comment inside an And */ stringSeq;
  482. /* */ /**/ /***/ /****/
  483. typedef sequence< sequence<string> > stringSeqSeq;
  484. interface QoSAdmin {
  485. stringSeq method1( in string arg1, inout long arg2 );
  486. stringSeqSeq method2( in string arg1, inout long arg2, inout long arg3);
  487. string method3();
  488. };
  489. """, 59
  490. )
  491. test(
  492. r"""
  493. const string test="Test String\n";
  494. const long a = 0;
  495. const long b = -100;
  496. const float c = 3.14159;
  497. const long d = 0x007f7f7f;
  498. exception TestException
  499. {
  500. string msg;
  501. sequence<string> dataStrings;
  502. };
  503. interface TestInterface
  504. {
  505. void method1( in string arg1, inout long arg2 );
  506. };
  507. """, 60
  508. )
  509. test(
  510. """
  511. module Test1
  512. {
  513. exception TestException
  514. {
  515. string msg;
  516. ];
  517. interface TestInterface
  518. {
  519. void method1( in string arg1, inout long arg2 )
  520. raises ( TestException );
  521. };
  522. };
  523. """, 0, 56
  524. )
  525. test(
  526. """
  527. module Test1
  528. {
  529. exception TestException
  530. {
  531. string msg;
  532. };
  533. };
  534. """, 13
  535. )
  536. class ParseVerilogTest(ParseTestCase):
  537. def runTest(self):
  538. pass
  539. class ScanStringTest(ParseTestCase):
  540. def runTest(self):
  541. from pyparsing import Word, Combine, Suppress, CharsNotIn, nums, StringEnd
  542. testdata = """
  543. <table border="0" cellpadding="3" cellspacing="3" frame="" width="90%">
  544. <tr align="left" valign="top">
  545. <td><b>Name</b></td>
  546. <td><b>IP Address</b></td>
  547. <td><b>Location</b></td>
  548. </tr>
  549. <tr align="left" valign="top" bgcolor="#c7efce">
  550. <td>time-a.nist.gov</td>
  551. <td>129.6.15.28</td>
  552. <td>NIST, Gaithersburg, Maryland</td>
  553. </tr>
  554. <tr align="left" valign="top">
  555. <td>time-b.nist.gov</td>
  556. <td>129.6.15.29</td>
  557. <td>NIST, Gaithersburg, Maryland</td>
  558. </tr>
  559. <tr align="left" valign="top" bgcolor="#c7efce">
  560. <td>time-a.timefreq.bldrdoc.gov</td>
  561. <td>132.163.4.101</td>
  562. <td>NIST, Boulder, Colorado</td>
  563. </tr>
  564. <tr align="left" valign="top">
  565. <td>time-b.timefreq.bldrdoc.gov</td>
  566. <td>132.163.4.102</td>
  567. <td>NIST, Boulder, Colorado</td>
  568. </tr>
  569. <tr align="left" valign="top" bgcolor="#c7efce">
  570. <td>time-c.timefreq.bldrdoc.gov</td>
  571. <td>132.163.4.103</td>
  572. <td>NIST, Boulder, Colorado</td>
  573. </tr>
  574. </table>
  575. """
  576. integer = Word(nums)
  577. ipAddress = Combine( integer + "." + integer + "." + integer + "." + integer )
  578. tdStart = Suppress("<td>")
  579. tdEnd = Suppress("</td>")
  580. timeServerPattern = (tdStart + ipAddress("ipAddr") + tdEnd
  581. + tdStart + CharsNotIn("<")("loc") + tdEnd)
  582. servers = [srvr.ipAddr for srvr,startloc,endloc in timeServerPattern.scanString( testdata )]
  583. print_(servers)
  584. self.assertEqual(servers,
  585. ['129.6.15.28', '129.6.15.29', '132.163.4.101', '132.163.4.102', '132.163.4.103'],
  586. "failed scanString()")
  587. # test for stringEnd detection in scanString
  588. foundStringEnds = [ r for r in StringEnd().scanString("xyzzy") ]
  589. print_(foundStringEnds)
  590. self.assertTrue(foundStringEnds, "Failed to find StringEnd in scanString")
  591. class QuotedStringsTest(ParseTestCase):
  592. def runTest(self):
  593. from pyparsing import sglQuotedString,dblQuotedString,quotedString,QuotedString
  594. testData = \
  595. """
  596. 'a valid single quoted string'
  597. 'an invalid single quoted string
  598. because it spans lines'
  599. "a valid double quoted string"
  600. "an invalid double quoted string
  601. because it spans lines"
  602. """
  603. print_(testData)
  604. sglStrings = [(t[0],b,e) for (t,b,e) in sglQuotedString.scanString(testData)]
  605. print_(sglStrings)
  606. self.assertTrue(len(sglStrings) == 1 and (sglStrings[0][1] == 17 and sglStrings[0][2] == 47),
  607. "single quoted string failure")
  608. dblStrings = [(t[0],b,e) for (t,b,e) in dblQuotedString.scanString(testData)]
  609. print_(dblStrings)
  610. self.assertTrue(len(dblStrings) == 1 and (dblStrings[0][1] == 154 and dblStrings[0][2] == 184),
  611. "double quoted string failure")
  612. allStrings = [(t[0],b,e) for (t,b,e) in quotedString.scanString(testData)]
  613. print_(allStrings)
  614. self.assertTrue(len(allStrings) == 2
  615. and (allStrings[0][1] == 17
  616. and allStrings[0][2] == 47)
  617. and (allStrings[1][1] == 154
  618. and allStrings[1][2] == 184),
  619. "quoted string failure")
  620. escapedQuoteTest = \
  621. r"""
  622. 'This string has an escaped (\') quote character'
  623. "This string has an escaped (\") quote character"
  624. """
  625. sglStrings = [(t[0],b,e) for (t,b,e) in sglQuotedString.scanString(escapedQuoteTest)]
  626. print_(sglStrings)
  627. self.assertTrue(len(sglStrings) == 1 and (sglStrings[0][1]==17 and sglStrings[0][2]==66),
  628. "single quoted string escaped quote failure (%s)" % str(sglStrings[0]))
  629. dblStrings = [(t[0],b,e) for (t,b,e) in dblQuotedString.scanString(escapedQuoteTest)]
  630. print_(dblStrings)
  631. self.assertTrue(len(dblStrings) == 1 and (dblStrings[0][1]==83 and dblStrings[0][2]==132),
  632. "double quoted string escaped quote failure (%s)" % str(dblStrings[0]))
  633. allStrings = [(t[0],b,e) for (t,b,e) in quotedString.scanString(escapedQuoteTest)]
  634. print_(allStrings)
  635. self.assertTrue(len(allStrings) == 2
  636. and (allStrings[0][1] == 17
  637. and allStrings[0][2] == 66
  638. and allStrings[1][1] == 83
  639. and allStrings[1][2] == 132),
  640. "quoted string escaped quote failure (%s)" % ([str(s[0]) for s in allStrings]))
  641. dblQuoteTest = \
  642. r"""
  643. 'This string has an doubled ('') quote character'
  644. "This string has an doubled ("") quote character"
  645. """
  646. sglStrings = [(t[0],b,e) for (t,b,e) in sglQuotedString.scanString(dblQuoteTest)]
  647. print_(sglStrings)
  648. self.assertTrue(len(sglStrings) == 1 and (sglStrings[0][1]==17 and sglStrings[0][2]==66),
  649. "single quoted string escaped quote failure (%s)" % str(sglStrings[0]))
  650. dblStrings = [(t[0],b,e) for (t,b,e) in dblQuotedString.scanString(dblQuoteTest)]
  651. print_(dblStrings)
  652. self.assertTrue(len(dblStrings) == 1 and (dblStrings[0][1]==83 and dblStrings[0][2]==132),
  653. "double quoted string escaped quote failure (%s)" % str(dblStrings[0]))
  654. allStrings = [(t[0],b,e) for (t,b,e) in quotedString.scanString(dblQuoteTest)]
  655. print_(allStrings)
  656. self.assertTrue(len(allStrings) == 2
  657. and (allStrings[0][1] == 17
  658. and allStrings[0][2] == 66
  659. and allStrings[1][1] == 83
  660. and allStrings[1][2] == 132),
  661. "quoted string escaped quote failure (%s)" % ([str(s[0]) for s in allStrings]))
  662. print_("testing catastrophic RE backtracking in implementation of dblQuotedString")
  663. for expr, test_string in [
  664. (dblQuotedString, '"' + '\\xff' * 500),
  665. (sglQuotedString, "'" + '\\xff' * 500),
  666. (quotedString, '"' + '\\xff' * 500),
  667. (quotedString, "'" + '\\xff' * 500),
  668. (QuotedString('"'), '"' + '\\xff' * 500),
  669. (QuotedString("'"), "'" + '\\xff' * 500),
  670. ]:
  671. expr.parseString(test_string+test_string[0])
  672. try:
  673. expr.parseString(test_string)
  674. except Exception:
  675. continue
  676. class CaselessOneOfTest(ParseTestCase):
  677. def runTest(self):
  678. from pyparsing import oneOf,ZeroOrMore
  679. caseless1 = oneOf("d a b c aA B A C", caseless=True)
  680. caseless1str = str( caseless1 )
  681. print_(caseless1str)
  682. caseless2 = oneOf("d a b c Aa B A C", caseless=True)
  683. caseless2str = str( caseless2 )
  684. print_(caseless2str)
  685. self.assertEqual(caseless1str.upper(), caseless2str.upper(), "oneOf not handling caseless option properly")
  686. self.assertNotEqual(caseless1str, caseless2str, "Caseless option properly sorted")
  687. res = ZeroOrMore(caseless1).parseString("AAaaAaaA")
  688. print_(res)
  689. self.assertEqual(len(res), 4, "caseless1 oneOf failed")
  690. self.assertEqual("".join(res), "aA"*4,"caseless1 CaselessLiteral return failed")
  691. res = ZeroOrMore(caseless2).parseString("AAaaAaaA")
  692. print_(res)
  693. self.assertEqual(len(res), 4, "caseless2 oneOf failed")
  694. self.assertEqual("".join(res), "Aa"*4,"caseless1 CaselessLiteral return failed")
  695. class AsXMLTest(ParseTestCase):
  696. def runTest(self):
  697. # test asXML()
  698. aaa = pp.Word("a")("A")
  699. bbb = pp.Group(pp.Word("b"))("B")
  700. ccc = pp.Combine(":" + pp.Word("c"))("C")
  701. g1 = "XXX>&<" + pp.ZeroOrMore( aaa | bbb | ccc )
  702. teststring = "XXX>&< b b a b b a b :c b a"
  703. #~ print teststring
  704. print_("test including all items")
  705. xml = g1.parseString(teststring).asXML("TEST",namedItemsOnly=False)
  706. assert xml=="\n".join(["",
  707. "<TEST>",
  708. " <ITEM>XXX&gt;&amp;&lt;</ITEM>",
  709. " <B>",
  710. " <ITEM>b</ITEM>",
  711. " </B>",
  712. " <B>",
  713. " <ITEM>b</ITEM>",
  714. " </B>",
  715. " <A>a</A>",
  716. " <B>",
  717. " <ITEM>b</ITEM>",
  718. " </B>",
  719. " <B>",
  720. " <ITEM>b</ITEM>",
  721. " </B>",
  722. " <A>a</A>",
  723. " <B>",
  724. " <ITEM>b</ITEM>",
  725. " </B>",
  726. " <C>:c</C>",
  727. " <B>",
  728. " <ITEM>b</ITEM>",
  729. " </B>",
  730. " <A>a</A>",
  731. "</TEST>",
  732. ] ), \
  733. "failed to generate XML correctly showing all items: \n[" + xml + "]"
  734. print_("test filtering unnamed items")
  735. xml = g1.parseString(teststring).asXML("TEST",namedItemsOnly=True)
  736. assert xml=="\n".join(["",
  737. "<TEST>",
  738. " <B>",
  739. " <ITEM>b</ITEM>",
  740. " </B>",
  741. " <B>",
  742. " <ITEM>b</ITEM>",
  743. " </B>",
  744. " <A>a</A>",
  745. " <B>",
  746. " <ITEM>b</ITEM>",
  747. " </B>",
  748. " <B>",
  749. " <ITEM>b</ITEM>",
  750. " </B>",
  751. " <A>a</A>",
  752. " <B>",
  753. " <ITEM>b</ITEM>",
  754. " </B>",
  755. " <C>:c</C>",
  756. " <B>",
  757. " <ITEM>b</ITEM>",
  758. " </B>",
  759. " <A>a</A>",
  760. "</TEST>",
  761. ] ), \
  762. "failed to generate XML correctly, filtering unnamed items: " + xml
  763. class AsXMLTest2(ParseTestCase):
  764. def runTest(self):
  765. from pyparsing import Suppress,Optional,CharsNotIn,Combine,ZeroOrMore,Word,\
  766. Group,Literal,alphas,alphanums,delimitedList,OneOrMore
  767. EndOfLine = Word("\n").setParseAction(lambda s,l,t: [' '])
  768. whiteSpace=Word('\t ')
  769. Mexpr = Suppress(Optional(whiteSpace)) + CharsNotIn('\\"\t \n') + Optional(" ") + \
  770. Suppress(Optional(whiteSpace))
  771. reducedString = Combine(Mexpr + ZeroOrMore(EndOfLine + Mexpr))
  772. _bslash = "\\"
  773. _escapables = "tnrfbacdeghijklmopqsuvwxyz" + _bslash + "'" + '"'
  774. _octDigits = "01234567"
  775. _escapedChar = ( Word( _bslash, _escapables, exact=2 ) |
  776. Word( _bslash, _octDigits, min=2, max=4 ) )
  777. _sglQuote = Literal("'")
  778. _dblQuote = Literal('"')
  779. QuotedReducedString = Combine( Suppress(_dblQuote) + ZeroOrMore( reducedString |
  780. _escapedChar ) + \
  781. Suppress(_dblQuote )).streamline()
  782. Manifest_string = QuotedReducedString('manifest_string')
  783. Identifier = Word( alphas, alphanums+ '_$' )("identifier")
  784. Index_string = CharsNotIn('\\";\n')
  785. Index_string.setName('index_string')
  786. Index_term_list = (
  787. Group(delimitedList(Manifest_string, delim=',')) | \
  788. Index_string
  789. )('value')
  790. IndexKey = Identifier('key')
  791. IndexKey.setName('key')
  792. Index_clause = Group(IndexKey + Suppress(':') + Optional(Index_term_list))
  793. Index_clause.setName('index_clause')
  794. Index_list = Index_clause('index')
  795. Index_list.setName('index_list')
  796. Index_block = Group('indexing' + Group(OneOrMore(Index_list + Suppress(';'))))('indexes')
  797. class CommentParserTest(ParseTestCase):
  798. def runTest(self):
  799. print_("verify processing of C and HTML comments")
  800. testdata = """
  801. /* */
  802. /** **/
  803. /**/
  804. /***/
  805. /****/
  806. /* /*/
  807. /** /*/
  808. /*** /*/
  809. /*
  810. ablsjdflj
  811. */
  812. """
  813. foundLines = [ pp.lineno(s,testdata)
  814. for t,s,e in pp.cStyleComment.scanString(testdata) ]
  815. self.assertEqual(foundLines, list(range(11))[2:],"only found C comments on lines "+str(foundLines))
  816. testdata = """
  817. <!-- -->
  818. <!--- --->
  819. <!---->
  820. <!----->
  821. <!------>
  822. <!-- /-->
  823. <!--- /-->
  824. <!---- /-->
  825. <!---- /- ->
  826. <!---- / -- >
  827. <!--
  828. ablsjdflj
  829. -->
  830. """
  831. foundLines = [ pp.lineno(s,testdata)
  832. for t,s,e in pp.htmlComment.scanString(testdata) ]
  833. self.assertEqual(foundLines, list(range(11))[2:],"only found HTML comments on lines "+str(foundLines))
  834. # test C++ single line comments that have line terminated with '\' (should continue comment to following line)
  835. testSource = r"""
  836. // comment1
  837. // comment2 \
  838. still comment 2
  839. // comment 3
  840. """
  841. self.assertEqual(len(pp.cppStyleComment.searchString(testSource)[1][0]), 41,
  842. r"failed to match single-line comment with '\' at EOL")
  843. class ParseExpressionResultsTest(ParseTestCase):
  844. def runTest(self):
  845. from pyparsing import Word,alphas,OneOrMore,Optional,Group
  846. a = Word("a", alphas).setName("A")
  847. b = Word("b", alphas).setName("B")
  848. c = Word("c", alphas).setName("C")
  849. ab = (a + b).setName("AB")
  850. abc = (ab + c).setName("ABC")
  851. word = Word(alphas).setName("word")
  852. words = Group(OneOrMore(~a + word)).setName("words")
  853. phrase = (words("Head")
  854. + Group(a + Optional(b + Optional(c)))("ABC")
  855. + words("Tail"))
  856. results = phrase.parseString("xavier yeti alpha beta charlie will beaver")
  857. print_(results,results.Head, results.ABC,results.Tail)
  858. for key,ln in [("Head",2), ("ABC",3), ("Tail",2)]:
  859. self.assertEqual(len(results[key]), ln,
  860. "expected %d elements in %s, found %s" % (ln, key, str(results[key])))
  861. class ParseKeywordTest(ParseTestCase):
  862. def runTest(self):
  863. from pyparsing import Literal,Keyword
  864. kw = Keyword("if")
  865. lit = Literal("if")
  866. def test(s,litShouldPass,kwShouldPass):
  867. print_("Test",s)
  868. print_("Match Literal", end=' ')
  869. try:
  870. print_(lit.parseString(s))
  871. except Exception:
  872. print_("failed")
  873. if litShouldPass:
  874. self.assertTrue(False, "Literal failed to match %s, should have" % s)
  875. else:
  876. if not litShouldPass:
  877. self.assertTrue(False, "Literal matched %s, should not have" % s)
  878. print_("Match Keyword", end=' ')
  879. try:
  880. print_(kw.parseString(s))
  881. except Exception:
  882. print_("failed")
  883. if kwShouldPass:
  884. self.assertTrue(False, "Keyword failed to match %s, should have" % s)
  885. else:
  886. if not kwShouldPass:
  887. self.assertTrue(False, "Keyword matched %s, should not have" % s)
  888. test("ifOnlyIfOnly", True, False)
  889. test("if(OnlyIfOnly)", True, True)
  890. test("if (OnlyIf Only)", True, True)
  891. kw = Keyword("if",caseless=True)
  892. test("IFOnlyIfOnly", False, False)
  893. test("If(OnlyIfOnly)", False, True)
  894. test("iF (OnlyIf Only)", False, True)
  895. class ParseExpressionResultsAccumulateTest(ParseTestCase):
  896. def runTest(self):
  897. from pyparsing import Word,delimitedList,Combine,alphas,nums
  898. num=Word(nums).setName("num")("base10*")
  899. hexnum=Combine("0x"+ Word(nums)).setName("hexnum")("hex*")
  900. name = Word(alphas).setName("word")("word*")
  901. list_of_num=delimitedList( hexnum | num | name, "," )
  902. tokens = list_of_num.parseString('1, 0x2, 3, 0x4, aaa')
  903. for k,llen,lst in ( ("base10",2,['1','3']),
  904. ("hex",2,['0x2','0x4']),
  905. ("word",1,['aaa']) ):
  906. print_(k,tokens[k])
  907. self.assertEqual(len(tokens[k]), llen, "Wrong length for key %s, %s" % (k,str(tokens[k].asList())))
  908. self.assertEqual(lst, tokens[k].asList(),
  909. "Incorrect list returned for key %s, %s" % (k,str(tokens[k].asList())))
  910. self.assertEqual(tokens.base10.asList(), ['1','3'],
  911. "Incorrect list for attribute base10, %s" % str(tokens.base10.asList()))
  912. self.assertEqual(tokens.hex.asList(), ['0x2','0x4'],
  913. "Incorrect list for attribute hex, %s" % str(tokens.hex.asList()))
  914. self.assertEqual(tokens.word.asList(), ['aaa'],
  915. "Incorrect list for attribute word, %s" % str(tokens.word.asList()))
  916. from pyparsing import Literal, Word, nums, Group, Dict, alphas, \
  917. quotedString, oneOf, delimitedList, removeQuotes, alphanums
  918. lbrack = Literal("(").suppress()
  919. rbrack = Literal(")").suppress()
  920. integer = Word( nums ).setName("int")
  921. variable = Word( alphas, max=1 ).setName("variable")
  922. relation_body_item = variable | integer | quotedString.copy().setParseAction(removeQuotes)
  923. relation_name = Word( alphas+"_", alphanums+"_" )
  924. relation_body = lbrack + Group(delimitedList(relation_body_item)) + rbrack
  925. Goal = Dict(Group( relation_name + relation_body ))
  926. Comparison_Predicate = Group(variable + oneOf("< >") + integer)("pred*")
  927. Query = Goal("head") + ":-" + delimitedList(Goal | Comparison_Predicate)
  928. test="""Q(x,y,z):-Bloo(x,"Mitsis",y),Foo(y,z,1243),y>28,x<12,x>3"""
  929. queryRes = Query.parseString(test)
  930. print_("pred",queryRes.pred)
  931. self.assertEqual(queryRes.pred.asList(), [['y', '>', '28'], ['x', '<', '12'], ['x', '>', '3']],
  932. "Incorrect list for attribute pred, %s" % str(queryRes.pred.asList()))
  933. print_(queryRes.dump())
  934. class ReStringRangeTest(ParseTestCase):
  935. def runTest(self):
  936. testCases = (
  937. (r"[A-Z]"),
  938. (r"[A-A]"),
  939. (r"[A-Za-z]"),
  940. (r"[A-z]"),
  941. (r"[\ -\~]"),
  942. (r"[\0x20-0]"),
  943. (r"[\0x21-\0x7E]"),
  944. (r"[\0xa1-\0xfe]"),
  945. (r"[\040-0]"),
  946. (r"[A-Za-z0-9]"),
  947. (r"[A-Za-z0-9_]"),
  948. (r"[A-Za-z0-9_$]"),
  949. (r"[A-Za-z0-9_$\-]"),
  950. (r"[^0-9\\]"),
  951. (r"[a-zA-Z]"),
  952. (r"[/\^~]"),
  953. (r"[=\+\-!]"),
  954. (r"[A-]"),
  955. (r"[-A]"),
  956. (r"[\x21]"),
  957. #(r"[а-яА-ЯёЁA-Z$_\041α-ω]".decode('utf-8')),
  958. (u'[\u0430-\u044f\u0410-\u042f\u0451\u0401ABCDEFGHIJKLMNOPQRSTUVWXYZ$_\041\u03b1-\u03c9]'),
  959. )
  960. expectedResults = (
  961. "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
  962. "A",
  963. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
  964. "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz",
  965. " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~",
  966. " !\"#$%&'()*+,-./0",
  967. "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~",
  968. #~ "¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ",
  969. u'\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe',
  970. " !\"#$%&'()*+,-./0",
  971. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
  972. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_",
  973. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$",
  974. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$-",
  975. "0123456789\\",
  976. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
  977. "/^~",
  978. "=+-!",
  979. "A-",
  980. "-A",
  981. "!",
  982. u"абвгдежзийклмнопрстуфхцчшщъыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯёЁABCDEFGHIJKLMNOPQRSTUVWXYZ$_!αβγδεζηθικλμνξοπρςστυφχψω",
  983. )
  984. for test in zip( testCases, expectedResults ):
  985. t,exp = test
  986. res = pp.srange(t)
  987. #print_(t,"->",res)
  988. self.assertEqual(res, exp, "srange error, srange(%r)->'%r', expected '%r'" % (t, res, exp))
  989. class SkipToParserTests(ParseTestCase):
  990. def runTest(self):
  991. from pyparsing import Literal, SkipTo, cStyleComment, ParseBaseException, And, Word, alphas, nums, Optional, NotAny
  992. thingToFind = Literal('working')
  993. testExpr = SkipTo(Literal(';'), include=True, ignore=cStyleComment) + thingToFind
  994. def tryToParse (someText, fail_expected=False):
  995. try:
  996. print_(testExpr.parseString(someText))
  997. self.assertFalse(fail_expected, "expected failure but no exception raised")
  998. except Exception as e:
  999. print_("Exception %s while parsing string %s" % (e,repr(someText)))
  1000. self.assertTrue(fail_expected and isinstance(e,ParseBaseException),
  1001. "Exception %s while parsing string %s" % (e,repr(someText)))
  1002. # This first test works, as the SkipTo expression is immediately following the ignore expression (cStyleComment)
  1003. tryToParse('some text /* comment with ; in */; working')
  1004. # This second test previously failed, as there is text following the ignore expression, and before the SkipTo expression.
  1005. tryToParse('some text /* comment with ; in */some other stuff; working')
  1006. # tests for optional failOn argument
  1007. testExpr = SkipTo(Literal(';'), include=True, ignore=cStyleComment, failOn='other') + thingToFind
  1008. tryToParse('some text /* comment with ; in */; working')
  1009. tryToParse('some text /* comment with ; in */some other stuff; working', fail_expected=True)
  1010. # test that we correctly create named results
  1011. text = "prefixDATAsuffix"
  1012. data = Literal("DATA")
  1013. suffix = Literal("suffix")
  1014. expr = SkipTo(data + suffix)('prefix') + data + suffix
  1015. result = expr.parseString(text)
  1016. self.assertTrue(isinstance(result.prefix, str), "SkipTo created with wrong saveAsList attribute")
  1017. if PY_3:
  1018. def define_expr(s):
  1019. from pyparsing import Literal, And, Word, alphas, nums, Optional, NotAny
  1020. alpha_word = (~Literal("end") + Word(alphas, asKeyword=True)).setName("alpha")
  1021. num_word = Word(nums, asKeyword=True).setName("int")
  1022. ret = eval(s)
  1023. ret.streamline()
  1024. print_(ret)
  1025. return ret
  1026. def test(expr, test_string, expected_list, expected_dict):
  1027. try:
  1028. result = expr.parseString(test_string)
  1029. except Exception as pe:
  1030. if any(expected is not None for expected in (expected_list, expected_dict)):
  1031. self.assertTrue(False, "{} failed to parse {!r}".format(expr, test_string))
  1032. else:
  1033. self.assertEqual(result.asList(), expected_list)
  1034. self.assertEqual(result.asDict(), expected_dict)
  1035. # ellipses for SkipTo
  1036. # (use eval() to avoid syntax problems when running in Py2)
  1037. e = define_expr('... + Literal("end")')
  1038. test(e, "start 123 end", ['start 123 ', 'end'], {'_skipped': ['start 123 ']})
  1039. e = define_expr('Literal("start") + ... + Literal("end")')
  1040. test(e, "start 123 end", ['start', '123 ', 'end'], {'_skipped': ['123 ']})
  1041. e = define_expr('Literal("start") + ...')
  1042. test(e, "start 123 end", None, None)
  1043. e = define_expr('And(["start", ..., "end"])')
  1044. test(e, "start 123 end", ['start', '123 ', 'end'], {'_skipped': ['123 ']})
  1045. e = define_expr('And([..., "end"])')
  1046. test(e, "start 123 end", ['start 123 ', 'end'], {'_skipped': ['start 123 ']})
  1047. e = define_expr('"start" + (num_word | ...) + "end"')
  1048. test(e, "start 456 end", ['start', '456', 'end'], {})
  1049. test(e, "start 123 456 end", ['start', '123', '456 ', 'end'], {'_skipped': ['456 ']})
  1050. test(e, "start end", ['start', '', 'end'], {'_skipped': ['missing <int>']})
  1051. # e = define_expr('"start" + (num_word | ...)("inner") + "end"')
  1052. # test(e, "start 456 end", ['start', '456', 'end'], {'inner': '456'})
  1053. e = define_expr('"start" + (alpha_word[...] & num_word[...] | ...) + "end"')
  1054. test(e, "start 456 red end", ['start', '456', 'red', 'end'], {})
  1055. test(e, "start red 456 end", ['start', 'red', '456', 'end'], {})
  1056. test(e, "start 456 red + end", ['start', '456', 'red', '+ ', 'end'], {'_skipped': ['+ ']})
  1057. test(e, "start red end", ['start', 'red', 'end'], {})
  1058. test(e, "start 456 end", ['start', '456', 'end'], {})
  1059. test(e, "start end", ['start', 'end'], {})
  1060. test(e, "start 456 + end", ['start', '456', '+ ', 'end'], {'_skipped': ['+ ']})
  1061. e = define_expr('"start" + (alpha_word[1, ...] & num_word[1, ...] | ...) + "end"')
  1062. test(e, "start 456 red end", ['start', '456', 'red', 'end'], {})
  1063. test(e, "start red 456 end", ['start', 'red', '456', 'end'], {})
  1064. test(e, "start 456 red + end", ['start', '456', 'red', '+ ', 'end'], {'_skipped': ['+ ']})
  1065. test(e, "start red end", ['start', 'red ', 'end'], {'_skipped': ['red ']})
  1066. test(e, "start 456 end", ['start', '456 ', 'end'], {'_skipped': ['456 ']})
  1067. test(e, "start end", ['start', '', 'end'], {'_skipped': ['missing <{{alpha}... & {int}...}>']})
  1068. test(e, "start 456 + end", ['start', '456 + ', 'end'], {'_skipped': ['456 + ']})
  1069. e = define_expr('"start" + (alpha_word | ...) + (num_word | ...) + "end"')
  1070. test(e, "start red 456 end", ['start', 'red', '456', 'end'], {})
  1071. test(e, "start red end", ['start', 'red', '', 'end'], {'_skipped': ['missing <int>']})
  1072. test(e, "start end", ['start', '', '', 'end'], {'_skipped': ['missing <alpha>', 'missing <int>']})
  1073. e = define_expr('Literal("start") + ... + "+" + ... + "end"')
  1074. test(e, "start red + 456 end", ['start', 'red ', '+', '456 ', 'end'], {'_skipped': ['red ', '456 ']})
  1075. class EllipsisRepetionTest(ParseTestCase):
  1076. def runTest(self):
  1077. import pyparsing as pp
  1078. import re
  1079. word = pp.Word(pp.alphas).setName("word")
  1080. num = pp.Word(pp.nums).setName("num")
  1081. exprs = [
  1082. word[...] + num,
  1083. word[0, ...] + num,
  1084. word[1, ...] + num,
  1085. word[2, ...] + num,
  1086. word[..., 3] + num,
  1087. word[2] + num,
  1088. ]
  1089. expected_res = [
  1090. r"([abcd]+ )*\d+",
  1091. r"([abcd]+ )*\d+",
  1092. r"([abcd]+ )+\d+",
  1093. r"([abcd]+ ){2,}\d+",
  1094. r"([abcd]+ ){0,3}\d+",
  1095. r"([abcd]+ ){2}\d+",
  1096. ]
  1097. tests = [
  1098. "aa bb cc dd 123",
  1099. "bb cc dd 123",
  1100. "cc dd 123",
  1101. "dd 123",
  1102. "123",
  1103. ]
  1104. all_success = True
  1105. for expr, expected_re in zip(exprs, expected_res):
  1106. successful_tests = [t for t in tests if re.match(expected_re, t)]
  1107. failure_tests = [t for t in tests if not re.match(expected_re, t)]
  1108. success1, _ = expr.runTests(successful_tests)
  1109. success2, _ = expr.runTests(failure_tests, failureTests=True)
  1110. all_success = all_success and success1 and success2
  1111. if not all_success:
  1112. print_("Failed expression:", expr)
  1113. break
  1114. self.assertTrue(all_success, "failed getItem_ellipsis test")
  1115. class CustomQuotesTest(ParseTestCase):
  1116. def runTest(self):
  1117. self.expect_warning = True
  1118. from pyparsing import QuotedString
  1119. testString = r"""
  1120. sdlfjs :sdf\:jls::djf: sl:kfsjf
  1121. sdlfjs -sdf\:jls::--djf: sl-kfsjf
  1122. sdlfjs -sdf\:::jls::--djf: sl:::-kfsjf
  1123. sdlfjs ^sdf\:jls^^--djf^ sl-kfsjf
  1124. sdlfjs ^^^==sdf\:j=lz::--djf: sl=^^=kfsjf
  1125. sdlfjs ==sdf\:j=ls::--djf: sl==kfsjf^^^
  1126. """
  1127. colonQuotes = QuotedString(':','\\','::')
  1128. dashQuotes = QuotedString('-','\\', '--')
  1129. hatQuotes = QuotedString('^','\\')
  1130. hatQuotes1 = QuotedString('^','\\','^^')
  1131. dblEqQuotes = QuotedString('==','\\')
  1132. def test(quoteExpr, expected):
  1133. print_(quoteExpr.pattern)
  1134. print_(quoteExpr.searchString(testString))
  1135. print_(quoteExpr.searchString(testString)[0][0])
  1136. print_(expected)
  1137. self.assertEqual(quoteExpr.searchString(testString)[0][0],
  1138. expected,
  1139. "failed to match %s, expected '%s', got '%s'" % (quoteExpr, expected,
  1140. quoteExpr.searchString(testString)[0]))
  1141. print_()
  1142. test(colonQuotes, r"sdf:jls:djf")
  1143. test(dashQuotes, r"sdf:jls::-djf: sl")
  1144. test(hatQuotes, r"sdf:jls")
  1145. test(hatQuotes1, r"sdf:jls^--djf")
  1146. test(dblEqQuotes, r"sdf:j=ls::--djf: sl")
  1147. test(QuotedString(':::'), 'jls::--djf: sl')
  1148. test(QuotedString('==',endQuoteChar='--'), r'sdf\:j=lz::')
  1149. test(QuotedString('^^^',multiline=True), r"""==sdf\:j=lz::--djf: sl=^^=kfsjf
  1150. sdlfjs ==sdf\:j=ls::--djf: sl==kfsjf""")
  1151. try:
  1152. bad1 = QuotedString('','\\')
  1153. except SyntaxError as se:
  1154. pass
  1155. else:
  1156. self.assertTrue(False,"failed to raise SyntaxError with empty quote string")
  1157. class RepeaterTest(ParseTestCase):
  1158. def runTest(self):
  1159. from pyparsing import matchPreviousLiteral,matchPreviousExpr, Word, nums, ParserElement
  1160. if ParserElement._packratEnabled:
  1161. print_("skipping this test, not compatible with packratting")
  1162. return
  1163. first = Word("abcdef").setName("word1")
  1164. bridge = Word(nums).setName("number")
  1165. second = matchPreviousLiteral(first).setName("repeat(word1Literal)")
  1166. seq = first + bridge + second
  1167. tests = [
  1168. ( "abc12abc", True ),
  1169. ( "abc12aabc", False ),
  1170. ( "abc12cba", True ),
  1171. ( "abc12bca", True ),
  1172. ]
  1173. for tst,result in tests:
  1174. found = False
  1175. for tokens,start,end in seq.scanString(tst):
  1176. f,b,s = tokens
  1177. print_(f,b,s)
  1178. found = True
  1179. if not found:
  1180. print_("No literal match in", tst)
  1181. self.assertEqual(found, result, "Failed repeater for test: %s, matching %s" % (tst, str(seq)))
  1182. print_()
  1183. # retest using matchPreviousExpr instead of matchPreviousLiteral
  1184. second = matchPreviousExpr(first).setName("repeat(word1expr)")
  1185. seq = first + bridge + second
  1186. tests = [
  1187. ( "abc12abc", True ),
  1188. ( "abc12cba", False ),
  1189. ( "abc12abcdef", False ),
  1190. ]
  1191. for tst,result in tests:
  1192. found = False
  1193. for tokens,start,end in seq.scanString(tst):
  1194. print_(tokens.asList())
  1195. found = True
  1196. if not found:
  1197. print_("No expression match in", tst)
  1198. self.assertEqual(found, result, "Failed repeater for test: %s, matching %s" % (tst, str(seq)))
  1199. print_()
  1200. first = Word("abcdef").setName("word1")
  1201. bridge = Word(nums).setName("number")
  1202. second = matchPreviousExpr(first).setName("repeat(word1)")
  1203. seq = first + bridge + second
  1204. csFirst = seq.setName("word-num-word")
  1205. csSecond = matchPreviousExpr(csFirst)
  1206. compoundSeq = csFirst + ":" + csSecond
  1207. compoundSeq.streamline()
  1208. print_(compoundSeq)
  1209. tests = [
  1210. ( "abc12abc:abc12abc", True ),
  1211. ( "abc12cba:abc12abc", False ),
  1212. ( "abc12abc:abc12abcdef", False ),
  1213. ]
  1214. for tst, result in tests:
  1215. found = False
  1216. for tokens, start, end in compoundSeq.scanString(tst):
  1217. print_("match:", tokens.asList())
  1218. found = True
  1219. break
  1220. if not found:
  1221. print_("No expression match in", tst)
  1222. self.assertEqual(found, result, "Failed repeater for test: %s, matching %s" % (tst, str(seq)))
  1223. print_()
  1224. eFirst = Word(nums)
  1225. eSecond = matchPreviousExpr(eFirst)
  1226. eSeq = eFirst + ":" + eSecond
  1227. tests = [
  1228. ( "1:1A", True ),
  1229. ( "1:10", False ),
  1230. ]
  1231. for tst,result in tests:
  1232. found = False
  1233. for tokens,start,end in eSeq.scanString(tst):
  1234. print_(tokens.asList())
  1235. found = True
  1236. if not found:
  1237. print_("No match in", tst)
  1238. self.assertEqual(found, result, "Failed repeater for test: %s, matching %s" % (tst, str(seq)))
  1239. class RecursiveCombineTest(ParseTestCase):
  1240. def runTest(self):
  1241. from pyparsing import Forward,Word,alphas,nums,Optional,Combine
  1242. testInput = "myc(114)r(11)dd"
  1243. Stream=Forward()
  1244. Stream << Optional(Word(alphas))+Optional("("+Word(nums)+")"+Stream)
  1245. expected = Stream.parseString(testInput).asList()
  1246. print_(["".join(expected)])
  1247. Stream=Forward()
  1248. Stream << Combine(Optional(Word(alphas))+Optional("("+Word(nums)+")"+Stream))
  1249. testVal = Stream.parseString(testInput).asList()
  1250. print_(testVal)
  1251. self.assertEqual("".join(testVal), "".join(expected), "Failed to process Combine with recursive content")
  1252. class InfixNotationGrammarTest1(ParseTestCase):
  1253. def runTest(self):
  1254. from pyparsing import Word,nums,alphas,Literal,oneOf,infixNotation,opAssoc
  1255. import ast
  1256. integer = Word(nums).setParseAction(lambda t:int(t[0]))
  1257. variable = Word(alphas,exact=1)
  1258. operand = integer | variable
  1259. expop = Literal('^')
  1260. signop = oneOf('+ -')
  1261. multop = oneOf('* /')
  1262. plusop = oneOf('+ -')
  1263. factop = Literal('!')
  1264. expr = infixNotation( operand,
  1265. [(factop, 1, opAssoc.LEFT),
  1266. (expop, 2, opAssoc.RIGHT),
  1267. (signop, 1, opAssoc.RIGHT),
  1268. (multop, 2, opAssoc.LEFT),
  1269. (plusop, 2, opAssoc.LEFT),]
  1270. )
  1271. test = ["9 + 2 + 3",
  1272. "9 + 2 * 3",
  1273. "(9 + 2) * 3",
  1274. "(9 + -2) * 3",
  1275. "(9 + --2) * 3",
  1276. "(9 + -2) * 3^2^2",
  1277. "(9! + -2) * 3^2^2",
  1278. "M*X + B",
  1279. "M*(X + B)",
  1280. "1+2*-3^4*5+-+-6",
  1281. "3!!"]
  1282. expected = """[[9, '+', 2, '+', 3]]
  1283. [[9, '+', [2, '*', 3]]]
  1284. [[[9, '+', 2], '*', 3]]
  1285. [[[9, '+', ['-', 2]], '*', 3]]
  1286. [[[9, '+', ['-', ['-', 2]]], '*', 3]]
  1287. [[[9, '+', ['-', 2]], '*', [3, '^', [2, '^', 2]]]]
  1288. [[[[9, '!'], '+', ['-', 2]], '*', [3, '^', [2, '^', 2]]]]
  1289. [[['M', '*', 'X'], '+', 'B']]
  1290. [['M', '*', ['X', '+', 'B']]]
  1291. [[1, '+', [2, '*', ['-', [3, '^', 4]], '*', 5], '+', ['-', ['+', ['-', 6]]]]]
  1292. [[3, '!', '!']]""".split('\n')
  1293. expected = [ast.literal_eval(x.strip()) for x in expected]
  1294. for t,e in zip(test,expected):
  1295. print_(t,"->",e, "got", expr.parseString(t).asList())
  1296. self.assertEqual(expr.parseString(t).asList(), e,
  1297. "mismatched results for infixNotation: got %s, expected %s" % (expr.parseString(t).asList(),e))
  1298. class InfixNotationGrammarTest2(ParseTestCase):
  1299. def runTest(self):
  1300. from pyparsing import infixNotation, Word, alphas, oneOf, opAssoc
  1301. boolVars = { "True":True, "False":False }
  1302. class BoolOperand(object):
  1303. reprsymbol = ''
  1304. def __init__(self,t):
  1305. self.args = t[0][0::2]
  1306. def __str__(self):
  1307. sep = " %s " % self.reprsymbol
  1308. return "(" + sep.join(map(str,self.args)) + ")"
  1309. class BoolAnd(BoolOperand):
  1310. reprsymbol = '&'
  1311. def __bool__(self):
  1312. for a in self.args:
  1313. if isinstance(a,str):
  1314. v = boolVars[a]
  1315. else:
  1316. v = bool(a)
  1317. if not v:
  1318. return False
  1319. return True
  1320. class BoolOr(BoolOperand):
  1321. reprsymbol = '|'
  1322. def __bool__(self):
  1323. for a in self.args:
  1324. if isinstance(a,str):
  1325. v = boolVars[a]
  1326. else:
  1327. v = bool(a)
  1328. if v:
  1329. return True
  1330. return False
  1331. class BoolNot(BoolOperand):
  1332. def __init__(self,t):
  1333. self.arg = t[0][1]
  1334. def __str__(self):
  1335. return "~" + str(self.arg)
  1336. def __bool__(self):
  1337. if isinstance(self.arg,str):
  1338. v = boolVars[self.arg]
  1339. else:
  1340. v = bool(self.arg)
  1341. return not v
  1342. boolOperand = Word(alphas,max=1) | oneOf("True False")
  1343. boolExpr = infixNotation( boolOperand,
  1344. [
  1345. ("not", 1, opAssoc.RIGHT, BoolNot),
  1346. ("and", 2, opAssoc.LEFT, BoolAnd),
  1347. ("or", 2, opAssoc.LEFT, BoolOr),
  1348. ])
  1349. test = ["p and not q",
  1350. "not not p",
  1351. "not(p and q)",
  1352. "q or not p and r",
  1353. "q or not p or not r",
  1354. "q or not (p and r)",
  1355. "p or q or r",
  1356. "p or q or r and False",
  1357. "(p or q or r) and False",
  1358. ]
  1359. boolVars["p"] = True
  1360. boolVars["q"] = False
  1361. boolVars["r"] = True
  1362. print_("p =", boolVars["p"])
  1363. print_("q =", boolVars["q"])
  1364. print_("r =", boolVars["r"])
  1365. print_()
  1366. for t in test:
  1367. res = boolExpr.parseString(t)[0]
  1368. print_(t,'\n', res, '=', bool(res),'\n')
  1369. class InfixNotationGrammarTest3(ParseTestCase):
  1370. def runTest(self):
  1371. from pyparsing import infixNotation, Word, alphas, oneOf, opAssoc, nums, Literal
  1372. global count
  1373. count = 0
  1374. def evaluate_int(t):
  1375. global count
  1376. value = int(t[0])
  1377. print_("evaluate_int", value)
  1378. count += 1
  1379. return value
  1380. integer = Word(nums).setParseAction(evaluate_int)
  1381. variable = Word(alphas,exact=1)
  1382. operand = integer | variable
  1383. expop = Literal('^')
  1384. signop = oneOf('+ -')
  1385. multop = oneOf('* /')
  1386. plusop = oneOf('+ -')
  1387. factop = Literal('!')
  1388. expr = infixNotation( operand,
  1389. [
  1390. ("!", 1, opAssoc.LEFT),
  1391. ("^", 2, opAssoc.LEFT),
  1392. (signop, 1, opAssoc.RIGHT),
  1393. (multop, 2, opAssoc.LEFT),
  1394. (plusop, 2, opAssoc.LEFT),
  1395. ])
  1396. test = ["9"]
  1397. for t in test:
  1398. count = 0
  1399. print_("%r => %s (count=%d)" % (t, expr.parseString(t), count))
  1400. self.assertEqual(count, 1, "count evaluated too many times!")
  1401. class InfixNotationGrammarTest4(ParseTestCase):
  1402. def runTest(self):
  1403. word = pp.Word(pp.alphas)
  1404. def supLiteral(s):
  1405. """Returns the suppressed literal s"""
  1406. return pp.Literal(s).suppress()
  1407. def booleanExpr(atom):
  1408. ops = [
  1409. (supLiteral("!"), 1, pp.opAssoc.RIGHT, lambda s, l, t: ["!", t[0][0]]),
  1410. (pp.oneOf("= !="), 2, pp.opAssoc.LEFT, ),
  1411. (supLiteral("&"), 2, pp.opAssoc.LEFT, lambda s, l, t: ["&", t[0]]),
  1412. (supLiteral("|"), 2, pp.opAssoc.LEFT, lambda s, l, t: ["|", t[0]])]
  1413. return pp.infixNotation(atom, ops)
  1414. f = booleanExpr(word) + pp.StringEnd()
  1415. tests = [
  1416. ("bar = foo", "[['bar', '=', 'foo']]"),
  1417. ("bar = foo & baz = fee", "['&', [['bar', '=', 'foo'], ['baz', '=', 'fee']]]"),
  1418. ]
  1419. for test,expected in tests:
  1420. print_(test)
  1421. results = f.parseString(test)
  1422. print_(results)
  1423. self.assertEqual(str(results), expected, "failed to match expected results, got '%s'" % str(results))
  1424. print_()
  1425. class InfixNotationGrammarTest5(ParseTestCase):
  1426. def runTest(self):
  1427. from pyparsing import infixNotation, opAssoc, pyparsing_common as ppc, Literal, oneOf
  1428. expop = Literal('**')
  1429. signop = oneOf('+ -')
  1430. multop = oneOf('* /')
  1431. plusop = oneOf('+ -')
  1432. class ExprNode(object):
  1433. def __init__(self, tokens):
  1434. self.tokens = tokens[0]
  1435. def eval(self):
  1436. return None
  1437. class NumberNode(ExprNode):
  1438. def eval(self):
  1439. return self.tokens
  1440. class SignOp(ExprNode):
  1441. def eval(self):
  1442. mult = {'+': 1, '-': -1}[self.tokens[0]]
  1443. return mult * self.tokens[1].eval()
  1444. class BinOp(ExprNode):
  1445. def eval(self):
  1446. ret = self.tokens[0].eval()
  1447. for op, operand in zip(self.tokens[1::2], self.tokens[2::2]):
  1448. ret = self.opn_map[op](ret, operand.eval())
  1449. return ret
  1450. class ExpOp(BinOp):
  1451. opn_map = {'**': lambda a, b: b ** a}
  1452. class MultOp(BinOp):
  1453. import operator
  1454. opn_map = {'*': operator.mul, '/': operator.truediv}
  1455. class AddOp(BinOp):
  1456. import operator
  1457. opn_map = {'+': operator.add, '-': operator.sub}
  1458. operand = ppc.number().setParseAction(NumberNode)
  1459. expr = infixNotation(operand,
  1460. [
  1461. (expop, 2, opAssoc.LEFT, (lambda pr: [pr[0][::-1]], ExpOp)),
  1462. (signop, 1, opAssoc.RIGHT, SignOp),
  1463. (multop, 2, opAssoc.LEFT, MultOp),
  1464. (plusop, 2, opAssoc.LEFT, AddOp),
  1465. ])
  1466. tests = """\
  1467. 2+7
  1468. 2**3
  1469. 2**3**2
  1470. 3**9
  1471. 3**3**2
  1472. """
  1473. for t in tests.splitlines():
  1474. t = t.strip()
  1475. if not t:
  1476. continue
  1477. parsed = expr.parseString(t)
  1478. eval_value = parsed[0].eval()
  1479. self.assertEqual(eval_value, eval(t),
  1480. "Error evaluating %r, expected %r, got %r" % (t, eval(t), eval_value))
  1481. class PickleTest_Greeting():
  1482. def __init__(self, toks):
  1483. self.salutation = toks[0]
  1484. self.greetee = toks[1]
  1485. def __repr__(self):
  1486. return "%s: {%s}" % (self.__class__.__name__,
  1487. ', '.join('%r: %r' % (k, getattr(self,k)) for k in sorted(self.__dict__)))
  1488. class ParseResultsPickleTest(ParseTestCase):
  1489. def runTest(self):
  1490. from pyparsing import makeHTMLTags, ParseResults
  1491. import pickle
  1492. # test 1
  1493. body = makeHTMLTags("BODY")[0]
  1494. result = body.parseString("<BODY BGCOLOR='#00FFBB' FGCOLOR=black>")
  1495. if VERBOSE:
  1496. print_(result.dump())
  1497. print_()
  1498. for protocol in range(pickle.HIGHEST_PROTOCOL+1):
  1499. print_("Test pickle dump protocol", protocol)
  1500. try:
  1501. pickleString = pickle.dumps(result, protocol)
  1502. except Exception as e:
  1503. print_("dumps exception:", e)
  1504. newresult = ParseResults()
  1505. else:
  1506. newresult = pickle.loads(pickleString)
  1507. if VERBOSE:
  1508. print_(newresult.dump())
  1509. print_()
  1510. self.assertEqual(result.dump(), newresult.dump(),
  1511. "Error pickling ParseResults object (protocol=%d)" % protocol)
  1512. # test 2
  1513. import pyparsing as pp
  1514. word = pp.Word(pp.alphas+"'.")
  1515. salutation = pp.OneOrMore(word)
  1516. comma = pp.Literal(",")
  1517. greetee = pp.OneOrMore(word)
  1518. endpunc = pp.oneOf("! ?")
  1519. greeting = salutation + pp.Suppress(comma) + greetee + pp.Suppress(endpunc)
  1520. greeting.setParseAction(PickleTest_Greeting)
  1521. string = 'Good morning, Miss Crabtree!'
  1522. result = greeting.parseString(string)
  1523. for protocol in range(pickle.HIGHEST_PROTOCOL+1):
  1524. print_("Test pickle dump protocol", protocol)
  1525. try:
  1526. pickleString = pickle.dumps(result, protocol)
  1527. except Exception as e:
  1528. print_("dumps exception:", e)
  1529. newresult = ParseResults()
  1530. else:
  1531. newresult = pickle.loads(pickleString)
  1532. print_(newresult.dump())
  1533. self.assertEqual(newresult.dump(), result.dump(),
  1534. "failed to pickle/unpickle ParseResults: expected %r, got %r" % (result, newresult))
  1535. class ParseResultsWithNamedTupleTest(ParseTestCase):
  1536. def runTest(self):
  1537. from pyparsing import Literal,replaceWith
  1538. expr = Literal("A")("Achar")
  1539. expr.setParseAction(replaceWith(tuple(["A","Z"])))
  1540. res = expr.parseString("A")
  1541. print_(repr(res))
  1542. print_(res.Achar)
  1543. self.assertEqual(res.Achar, ("A","Z"),
  1544. "Failed accessing named results containing a tuple, got {0!r}".format(res.Achar))
  1545. class ParseHTMLTagsTest(ParseTestCase):
  1546. def runTest(self):
  1547. test = """
  1548. <BODY>
  1549. <BODY BGCOLOR="#00FFCC">
  1550. <BODY BGCOLOR="#00FFAA"/>
  1551. <BODY BGCOLOR='#00FFBB' FGCOLOR=black>
  1552. <BODY/>
  1553. </BODY>
  1554. """
  1555. results = [
  1556. ("startBody", False, "", ""),
  1557. ("startBody", False, "#00FFCC", ""),
  1558. ("startBody", True, "#00FFAA", ""),
  1559. ("startBody", False, "#00FFBB", "black"),
  1560. ("startBody", True, "", ""),
  1561. ("endBody", False, "", ""),
  1562. ]
  1563. bodyStart, bodyEnd = pp.makeHTMLTags("BODY")
  1564. resIter = iter(results)
  1565. for t,s,e in (bodyStart | bodyEnd).scanString( test ):
  1566. print_(test[s:e], "->", t.asList())
  1567. (expectedType, expectedEmpty, expectedBG, expectedFG) = next(resIter)
  1568. print_(t.dump())
  1569. if "startBody" in t:
  1570. self.assertEqual(bool(t.empty), expectedEmpty,
  1571. "expected %s token, got %s" % (expectedEmpty and "empty" or "not empty",
  1572. t.empty and "empty" or "not empty"))
  1573. self.assertEqual(t.bgcolor, expectedBG,
  1574. "failed to match BGCOLOR, expected %s, got %s" % (expectedBG, t.bgcolor))
  1575. self.assertEqual(t.fgcolor, expectedFG,
  1576. "failed to match FGCOLOR, expected %s, got %s" % (expectedFG, t.bgcolor))
  1577. elif "endBody" in t:
  1578. print_("end tag")
  1579. pass
  1580. else:
  1581. print_("BAD!!!")
  1582. class UpcaseDowncaseUnicode(ParseTestCase):
  1583. def runTest(self):
  1584. import pyparsing as pp
  1585. from pyparsing import pyparsing_unicode as ppu
  1586. import sys
  1587. if PY_3:
  1588. unichr = chr
  1589. else:
  1590. from __builtin__ import unichr
  1591. a = u'\u00bfC\u00f3mo esta usted?'
  1592. if not JYTHON_ENV:
  1593. ualphas = ppu.alphas
  1594. else:
  1595. ualphas = "".join( unichr(i) for i in list(range(0xd800)) + list(range(0xe000,sys.maxunicode))
  1596. if unichr(i).isalpha() )
  1597. uword = pp.Word(ualphas).setParseAction(pp.upcaseTokens)
  1598. print_ = lambda *args: None
  1599. print_(uword.searchString(a))
  1600. uword = pp.Word(ualphas).setParseAction(pp.downcaseTokens)
  1601. print_(uword.searchString(a))
  1602. kw = pp.Keyword('mykey', caseless=True).setParseAction(pp.upcaseTokens)('rname')
  1603. ret = kw.parseString('mykey')
  1604. print_(ret.rname)
  1605. self.assertEqual(ret.rname, 'MYKEY', "failed to upcase with named result")
  1606. kw = pp.Keyword('mykey', caseless=True).setParseAction(pp.pyparsing_common.upcaseTokens)('rname')
  1607. ret = kw.parseString('mykey')
  1608. print_(ret.rname)
  1609. self.assertEqual(ret.rname, 'MYKEY', "failed to upcase with named result (pyparsing_common)")
  1610. kw = pp.Keyword('MYKEY', caseless=True).setParseAction(pp.pyparsing_common.downcaseTokens)('rname')
  1611. ret = kw.parseString('mykey')
  1612. print_(ret.rname)
  1613. self.assertEqual(ret.rname, 'mykey', "failed to upcase with named result")
  1614. if not IRON_PYTHON_ENV:
  1615. #test html data
  1616. html = u"<TR class=maintxt bgColor=#ffffff> \
  1617. <TD vAlign=top>Производитель, модель</TD> \
  1618. <TD vAlign=top><STRONG>BenQ-Siemens CF61</STRONG></TD> \
  1619. "#.decode('utf-8')
  1620. # u'Manufacturer, model
  1621. text_manuf = u'Производитель, модель'
  1622. manufacturer = pp.Literal(text_manuf)
  1623. td_start, td_end = pp.makeHTMLTags("td")
  1624. manuf_body = td_start.suppress() + manufacturer + pp.SkipTo(td_end)("cells*") + td_end.suppress()
  1625. #~ manuf_body.setDebug()
  1626. #~ for tokens in manuf_body.scanString(html):
  1627. #~ print_(tokens)
  1628. class ParseUsingRegex(ParseTestCase):
  1629. def runTest(self):
  1630. self.expect_warning = True
  1631. import re
  1632. signedInt = pp.Regex(r'[-+][0-9]+')
  1633. unsignedInt = pp.Regex(r'[0-9]+')
  1634. simpleString = pp.Regex(r'("[^\"]*")|(\'[^\']*\')')
  1635. namedGrouping = pp.Regex(r'("(?P<content>[^\"]*)")')
  1636. compiledRE = pp.Regex(re.compile(r'[A-Z]+'))
  1637. def testMatch (expression, instring, shouldPass, expectedString=None):
  1638. if shouldPass:
  1639. try:
  1640. result = expression.parseString(instring)
  1641. print_('%s correctly matched %s' % (repr(expression), repr(instring)))
  1642. if expectedString != result[0]:
  1643. print_('\tbut failed to match the pattern as expected:')
  1644. print_('\tproduced %s instead of %s' % \
  1645. (repr(result[0]), repr(expectedString)))
  1646. return True
  1647. except pp.ParseException:
  1648. print_('%s incorrectly failed to match %s' % \
  1649. (repr(expression), repr(instring)))
  1650. else:
  1651. try:
  1652. result = expression.parseString(instring)
  1653. print_('%s incorrectly matched %s' % (repr(expression), repr(instring)))
  1654. print_('\tproduced %s as a result' % repr(result[0]))
  1655. except pp.ParseException:
  1656. print_('%s correctly failed to match %s' % \
  1657. (repr(expression), repr(instring)))
  1658. return True
  1659. return False
  1660. # These should fail
  1661. self.assertTrue(testMatch(signedInt, '1234 foo', False), "Re: (1) passed, expected fail")
  1662. self.assertTrue(testMatch(signedInt, ' +foo', False), "Re: (2) passed, expected fail")
  1663. self.assertTrue(testMatch(unsignedInt, 'abc', False), "Re: (3) passed, expected fail")
  1664. self.assertTrue(testMatch(unsignedInt, '+123 foo', False), "Re: (4) passed, expected fail")
  1665. self.assertTrue(testMatch(simpleString, 'foo', False), "Re: (5) passed, expected fail")
  1666. self.assertTrue(testMatch(simpleString, '"foo bar\'', False), "Re: (6) passed, expected fail")
  1667. self.assertTrue(testMatch(simpleString, '\'foo bar"', False), "Re: (7) passed, expected fail")
  1668. # These should pass
  1669. self.assertTrue(testMatch(signedInt, ' +123', True, '+123'), "Re: (8) failed, expected pass")
  1670. self.assertTrue(testMatch(signedInt, '+123', True, '+123'), "Re: (9) failed, expected pass")
  1671. self.assertTrue(testMatch(signedInt, '+123 foo', True, '+123'), "Re: (10) failed, expected pass")
  1672. self.assertTrue(testMatch(signedInt, '-0 foo', True, '-0'), "Re: (11) failed, expected pass")
  1673. self.assertTrue(testMatch(unsignedInt, '123 foo', True, '123'), "Re: (12) failed, expected pass")
  1674. self.assertTrue(testMatch(unsignedInt, '0 foo', True, '0'), "Re: (13) failed, expected pass")
  1675. self.assertTrue(testMatch(simpleString, '"foo"', True, '"foo"'), "Re: (14) failed, expected pass")
  1676. self.assertTrue(testMatch(simpleString, "'foo bar' baz", True, "'foo bar'"), "Re: (15) failed, expected pass")
  1677. self.assertTrue(testMatch(compiledRE, 'blah', False), "Re: (16) passed, expected fail")
  1678. self.assertTrue(testMatch(compiledRE, 'BLAH', True, 'BLAH'), "Re: (17) failed, expected pass")
  1679. self.assertTrue(testMatch(namedGrouping, '"foo bar" baz', True, '"foo bar"'), "Re: (16) failed, expected pass")
  1680. ret = namedGrouping.parseString('"zork" blah')
  1681. print_(ret.asList())
  1682. print_(list(ret.items()))
  1683. print_(ret.content)
  1684. self.assertEqual(ret.content, 'zork', "named group lookup failed")
  1685. self.assertEqual(ret[0], simpleString.parseString('"zork" blah')[0],
  1686. "Regex not properly returning ParseResults for named vs. unnamed groups")
  1687. try:
  1688. #~ print "lets try an invalid RE"
  1689. invRe = pp.Regex('("[^\"]*")|(\'[^\']*\'')
  1690. except Exception as e:
  1691. print_("successfully rejected an invalid RE:", end=' ')
  1692. print_(e)
  1693. else:
  1694. self.assertTrue(False, "failed to reject invalid RE")
  1695. invRe = pp.Regex('')
  1696. class RegexAsTypeTest(ParseTestCase):
  1697. def runTest(self):
  1698. import pyparsing as pp
  1699. test_str = "sldkjfj 123 456 lsdfkj"
  1700. print_("return as list of match groups")
  1701. expr = pp.Regex(r"\w+ (\d+) (\d+) (\w+)", asGroupList=True)
  1702. expected_group_list = [tuple(test_str.split()[1:])]
  1703. result = expr.parseString(test_str)
  1704. print_(result.dump())
  1705. print_(expected_group_list)
  1706. self.assertEqual(result.asList(), expected_group_list, "incorrect group list returned by Regex)")
  1707. print_("return as re.match instance")
  1708. expr = pp.Regex(r"\w+ (?P<num1>\d+) (?P<num2>\d+) (?P<last_word>\w+)", asMatch=True)
  1709. result = expr.parseString(test_str)
  1710. print_(result.dump())
  1711. print_(result[0].groups())
  1712. print_(expected_group_list)
  1713. self.assertEqual(result[0].groupdict(), {'num1': '123', 'num2': '456', 'last_word': 'lsdfkj'},
  1714. 'invalid group dict from Regex(asMatch=True)')
  1715. self.assertEqual(result[0].groups(), expected_group_list[0],
  1716. "incorrect group list returned by Regex(asMatch)")
  1717. class RegexSubTest(ParseTestCase):
  1718. def runTest(self):
  1719. self.expect_warning = True
  1720. import pyparsing as pp
  1721. print_("test sub with string")
  1722. expr = pp.Regex(r"<title>").sub("'Richard III'")
  1723. result = expr.transformString("This is the title: <title>")
  1724. print_(result)
  1725. self.assertEqual(result, "This is the title: 'Richard III'", "incorrect Regex.sub result with simple string")
  1726. print_("test sub with re string")
  1727. expr = pp.Regex(r"([Hh]\d):\s*(.*)").sub(r"<\1>\2</\1>")
  1728. result = expr.transformString("h1: This is the main heading\nh2: This is the sub-heading")
  1729. print_(result)
  1730. self.assertEqual(result, '<h1>This is the main heading</h1>\n<h2>This is the sub-heading</h2>',
  1731. "incorrect Regex.sub result with re string")
  1732. print_("test sub with re string (Regex returns re.match)")
  1733. expr = pp.Regex(r"([Hh]\d):\s*(.*)", asMatch=True).sub(r"<\1>\2</\1>")
  1734. result = expr.transformString("h1: This is the main heading\nh2: This is the sub-heading")
  1735. print_(result)
  1736. self.assertEqual(result, '<h1>This is the main heading</h1>\n<h2>This is the sub-heading</h2>',
  1737. "incorrect Regex.sub result with re string")
  1738. print_("test sub with callable that return str")
  1739. expr = pp.Regex(r"<(.*?)>").sub(lambda m: m.group(1).upper())
  1740. result = expr.transformString("I want this in upcase: <what? what?>")
  1741. print_(result)
  1742. self.assertEqual(result, 'I want this in upcase: WHAT? WHAT?', "incorrect Regex.sub result with callable")
  1743. try:
  1744. expr = pp.Regex(r"<(.*?)>", asMatch=True).sub(lambda m: m.group(1).upper())
  1745. except SyntaxError:
  1746. pass
  1747. else:
  1748. self.assertTrue(False, "failed to warn using a Regex.sub(callable) with asMatch=True")
  1749. try:
  1750. expr = pp.Regex(r"<(.*?)>", asGroupList=True).sub(lambda m: m.group(1).upper())
  1751. except SyntaxError:
  1752. pass
  1753. else:
  1754. self.assertTrue(False, "failed to warn using a Regex.sub() with asGroupList=True")
  1755. try:
  1756. expr = pp.Regex(r"<(.*?)>", asGroupList=True).sub("")
  1757. except SyntaxError:
  1758. pass
  1759. else:
  1760. self.assertTrue(False, "failed to warn using a Regex.sub() with asGroupList=True")
  1761. class PrecededByTest(ParseTestCase):
  1762. def runTest(self):
  1763. import pyparsing as pp
  1764. num = pp.Word(pp.nums).setParseAction(lambda t: int(t[0]))
  1765. interesting_num = pp.PrecededBy(pp.Char("abc")("prefix*")) + num
  1766. semi_interesting_num = pp.PrecededBy('_') + num
  1767. crazy_num = pp.PrecededBy(pp.Word("^", "$%^")("prefix*"), 10) + num
  1768. boring_num = ~pp.PrecededBy(pp.Char("abc_$%^" + pp.nums)) + num
  1769. very_boring_num = pp.PrecededBy(pp.WordStart()) + num
  1770. finicky_num = pp.PrecededBy(pp.Word("^", "$%^"), retreat=3) + num
  1771. s = "c384 b8324 _9293874 _293 404 $%^$^%$2939"
  1772. print_(s)
  1773. for expr, expected_list, expected_dict in [
  1774. (interesting_num, [384, 8324], {'prefix': ['c', 'b']}),
  1775. (semi_interesting_num, [9293874, 293], {}),
  1776. (boring_num, [404], {}),
  1777. (crazy_num, [2939], {'prefix': ['^%$']}),
  1778. (finicky_num, [2939], {}),
  1779. (very_boring_num, [404], {}),
  1780. ]:
  1781. print_(expr.searchString(s))
  1782. result = sum(expr.searchString(s))
  1783. print_(result)
  1784. self.assertEqual(result.asList(), expected_list,
  1785. "Erroneous tokens for {0}: expected {1}, got {2}".format(expr,
  1786. expected_list,
  1787. result.asList()))
  1788. self.assertEqual(result.asDict(), expected_dict,
  1789. "Erroneous named results for {0}: expected {1}, got {2}".format(expr,
  1790. expected_dict,
  1791. result.asDict()))
  1792. # infinite loop test - from Issue #127
  1793. string_test = 'notworking'
  1794. # negs = pp.Or(['not', 'un'])('negs')
  1795. negs_pb = pp.PrecededBy('not', retreat=100)('negs_lb')
  1796. # negs_pb = pp.PrecededBy(negs, retreat=100)('negs_lb')
  1797. pattern = pp.Group(negs_pb + pp.Literal('working'))('main')
  1798. results = pattern.searchString(string_test)
  1799. try:
  1800. print_(results.dump())
  1801. except RecursionError:
  1802. self.assertTrue(False, "got maximum excursion limit exception")
  1803. else:
  1804. self.assertTrue(True, "got maximum excursion limit exception")
  1805. class CountedArrayTest(ParseTestCase):
  1806. def runTest(self):
  1807. from pyparsing import Word,nums,OneOrMore,countedArray
  1808. testString = "2 5 7 6 0 1 2 3 4 5 0 3 5 4 3"
  1809. integer = Word(nums).setParseAction(lambda t: int(t[0]))
  1810. countedField = countedArray(integer)
  1811. r = OneOrMore(countedField).parseString( testString )
  1812. print_(testString)
  1813. print_(r.asList())
  1814. self.assertEqual(r.asList(), [[5,7],[0,1,2,3,4,5],[],[5,4,3]],
  1815. "Failed matching countedArray, got " + str(r.asList()))
  1816. class CountedArrayTest2(ParseTestCase):
  1817. # addresses bug raised by Ralf Vosseler
  1818. def runTest(self):
  1819. from pyparsing import Word,nums,OneOrMore,countedArray
  1820. testString = "2 5 7 6 0 1 2 3 4 5 0 3 5 4 3"
  1821. integer = Word(nums).setParseAction(lambda t: int(t[0]))
  1822. countedField = countedArray(integer)
  1823. dummy = Word("A")
  1824. r = OneOrMore(dummy ^ countedField).parseString( testString )
  1825. print_(testString)
  1826. print_(r.asList())
  1827. self.assertEqual(r.asList(), [[5,7],[0,1,2,3,4,5],[],[5,4,3]],
  1828. "Failed matching countedArray, got " + str(r.asList()))
  1829. class CountedArrayTest3(ParseTestCase):
  1830. # test case where counter is not a decimal integer
  1831. def runTest(self):
  1832. from pyparsing import Word,nums,OneOrMore,countedArray,alphas
  1833. int_chars = "_"+alphas
  1834. array_counter = Word(int_chars).setParseAction(lambda t: int_chars.index(t[0]))
  1835. # 123456789012345678901234567890
  1836. testString = "B 5 7 F 0 1 2 3 4 5 _ C 5 4 3"
  1837. integer = Word(nums).setParseAction(lambda t: int(t[0]))
  1838. countedField = countedArray(integer, intExpr=array_counter)
  1839. r = OneOrMore(countedField).parseString( testString )
  1840. print_(testString)
  1841. print_(r.asList())
  1842. self.assertEqual(r.asList(), [[5,7],[0,1,2,3,4,5],[],[5,4,3]],
  1843. "Failed matching countedArray, got " + str(r.asList()))
  1844. class LineStartTest(ParseTestCase):
  1845. def runTest(self):
  1846. import pyparsing as pp
  1847. pass_tests = [
  1848. """\
  1849. AAA
  1850. BBB
  1851. """,
  1852. """\
  1853. AAA...
  1854. BBB
  1855. """,
  1856. ]
  1857. fail_tests = [
  1858. """\
  1859. AAA...
  1860. ...BBB
  1861. """,
  1862. """\
  1863. AAA BBB
  1864. """,
  1865. ]
  1866. # cleanup test strings
  1867. pass_tests = ['\n'.join(s.lstrip() for s in t.splitlines()).replace('.', ' ') for t in pass_tests]
  1868. fail_tests = ['\n'.join(s.lstrip() for s in t.splitlines()).replace('.', ' ') for t in fail_tests]
  1869. test_patt = pp.Word('A') - pp.LineStart() + pp.Word('B')
  1870. print_(test_patt.streamline())
  1871. success = test_patt.runTests(pass_tests)[0]
  1872. self.assertTrue(success, "failed LineStart passing tests (1)")
  1873. success = test_patt.runTests(fail_tests, failureTests=True)[0]
  1874. self.assertTrue(success, "failed LineStart failure mode tests (1)")
  1875. with AutoReset(pp.ParserElement, "DEFAULT_WHITE_CHARS"):
  1876. print_(r'no \n in default whitespace chars')
  1877. pp.ParserElement.setDefaultWhitespaceChars(' ')
  1878. test_patt = pp.Word('A') - pp.LineStart() + pp.Word('B')
  1879. print_(test_patt.streamline())
  1880. # should fail the pass tests too, since \n is no longer valid whitespace and we aren't parsing for it
  1881. success = test_patt.runTests(pass_tests, failureTests=True)[0]
  1882. self.assertTrue(success, "failed LineStart passing tests (2)")
  1883. success = test_patt.runTests(fail_tests, failureTests=True)[0]
  1884. self.assertTrue(success, "failed LineStart failure mode tests (2)")
  1885. test_patt = pp.Word('A') - pp.LineEnd().suppress() + pp.LineStart() + pp.Word('B') + pp.LineEnd().suppress()
  1886. print_(test_patt.streamline())
  1887. success = test_patt.runTests(pass_tests)[0]
  1888. self.assertTrue(success, "failed LineStart passing tests (3)")
  1889. success = test_patt.runTests(fail_tests, failureTests=True)[0]
  1890. self.assertTrue(success, "failed LineStart failure mode tests (3)")
  1891. test = """\
  1892. AAA 1
  1893. AAA 2
  1894. AAA
  1895. B AAA
  1896. """
  1897. from textwrap import dedent
  1898. test = dedent(test)
  1899. print_(test)
  1900. for t, s, e in (pp.LineStart() + 'AAA').scanString(test):
  1901. print_(s, e, pp.lineno(s, test), pp.line(s, test), ord(test[s]))
  1902. print_()
  1903. self.assertEqual(test[s], 'A', 'failed LineStart with insignificant newlines')
  1904. with AutoReset(pp.ParserElement, "DEFAULT_WHITE_CHARS"):
  1905. pp.ParserElement.setDefaultWhitespaceChars(' ')
  1906. for t, s, e in (pp.LineStart() + 'AAA').scanString(test):
  1907. print_(s, e, pp.lineno(s, test), pp.line(s, test), ord(test[s]))
  1908. print_()
  1909. self.assertEqual(test[s], 'A', 'failed LineStart with insignificant newlines')
  1910. class LineAndStringEndTest(ParseTestCase):
  1911. def runTest(self):
  1912. from pyparsing import OneOrMore,lineEnd,alphanums,Word,stringEnd,delimitedList,SkipTo
  1913. NLs = OneOrMore(lineEnd)
  1914. bnf1 = delimitedList(Word(alphanums).leaveWhitespace(), NLs)
  1915. bnf2 = Word(alphanums) + stringEnd
  1916. bnf3 = Word(alphanums) + SkipTo(stringEnd)
  1917. tests = [
  1918. ("testA\ntestB\ntestC\n", ['testA', 'testB', 'testC']),
  1919. ("testD\ntestE\ntestF", ['testD', 'testE', 'testF']),
  1920. ("a", ['a']),
  1921. ]
  1922. for test,expected in tests:
  1923. res1 = bnf1.parseString(test)
  1924. print_(res1,'=?',expected)
  1925. self.assertEqual(res1.asList(), expected,
  1926. "Failed lineEnd/stringEnd test (1): "+repr(test)+ " -> "+str(res1.asList()))
  1927. res2 = bnf2.searchString(test)[0]
  1928. print_(res2.asList(),'=?',expected[-1:])
  1929. self.assertEqual(res2.asList(), expected[-1:],
  1930. "Failed lineEnd/stringEnd test (2): "+repr(test)+ " -> "+str(res2.asList()))
  1931. res3 = bnf3.parseString(test)
  1932. first = res3[0]
  1933. rest = res3[1]
  1934. #~ print res3.dump()
  1935. print_(repr(rest),'=?',repr(test[len(first)+1:]))
  1936. self.assertEqual(rest, test[len(first)+1:],
  1937. "Failed lineEnd/stringEnd test (3): " +repr(test)+ " -> "+str(res3.asList()))
  1938. print_()
  1939. from pyparsing import Regex
  1940. import re
  1941. k = Regex(r'a+',flags=re.S+re.M)
  1942. k = k.parseWithTabs()
  1943. k = k.leaveWhitespace()
  1944. tests = [
  1945. (r'aaa',['aaa']),
  1946. (r'\naaa',None),
  1947. (r'a\naa',None),
  1948. (r'aaa\n',None),
  1949. ]
  1950. for i,(src,expected) in enumerate(tests):
  1951. print_(i, repr(src).replace('\\\\','\\'), end=' ')
  1952. try:
  1953. res = k.parseString(src, parseAll=True).asList()
  1954. except ParseException as pe:
  1955. res = None
  1956. print_(res)
  1957. self.assertEqual(res, expected, "Failed on parseAll=True test %d" % i)
  1958. class VariableParseActionArgsTest(ParseTestCase):
  1959. def runTest(self):
  1960. pa3 = lambda s,l,t: t
  1961. pa2 = lambda l,t: t
  1962. pa1 = lambda t: t
  1963. pa0 = lambda : None
  1964. class Callable3(object):
  1965. def __call__(self,s,l,t):
  1966. return t
  1967. class Callable2(object):
  1968. def __call__(self,l,t):
  1969. return t
  1970. class Callable1(object):
  1971. def __call__(self,t):
  1972. return t
  1973. class Callable0(object):
  1974. def __call__(self):
  1975. return
  1976. class CallableS3(object):
  1977. #~ @staticmethod
  1978. def __call__(s,l,t):
  1979. return t
  1980. __call__=staticmethod(__call__)
  1981. class CallableS2(object):
  1982. #~ @staticmethod
  1983. def __call__(l,t):
  1984. return t
  1985. __call__=staticmethod(__call__)
  1986. class CallableS1(object):
  1987. #~ @staticmethod
  1988. def __call__(t):
  1989. return t
  1990. __call__=staticmethod(__call__)
  1991. class CallableS0(object):
  1992. #~ @staticmethod
  1993. def __call__():
  1994. return
  1995. __call__=staticmethod(__call__)
  1996. class CallableC3(object):
  1997. #~ @classmethod
  1998. def __call__(cls,s,l,t):
  1999. return t
  2000. __call__=classmethod(__call__)
  2001. class CallableC2(object):
  2002. #~ @classmethod
  2003. def __call__(cls,l,t):
  2004. return t
  2005. __call__=classmethod(__call__)
  2006. class CallableC1(object):
  2007. #~ @classmethod
  2008. def __call__(cls,t):
  2009. return t
  2010. __call__=classmethod(__call__)
  2011. class CallableC0(object):
  2012. #~ @classmethod
  2013. def __call__(cls):
  2014. return
  2015. __call__=classmethod(__call__)
  2016. class parseActionHolder(object):
  2017. #~ @staticmethod
  2018. def pa3(s,l,t):
  2019. return t
  2020. pa3=staticmethod(pa3)
  2021. #~ @staticmethod
  2022. def pa2(l,t):
  2023. return t
  2024. pa2=staticmethod(pa2)
  2025. #~ @staticmethod
  2026. def pa1(t):
  2027. return t
  2028. pa1=staticmethod(pa1)
  2029. #~ @staticmethod
  2030. def pa0():
  2031. return
  2032. pa0=staticmethod(pa0)
  2033. def paArgs(*args):
  2034. print_(args)
  2035. return args[2]
  2036. class ClassAsPA0(object):
  2037. def __init__(self):
  2038. pass
  2039. def __str__(self):
  2040. return "A"
  2041. class ClassAsPA1(object):
  2042. def __init__(self,t):
  2043. print_("making a ClassAsPA1")
  2044. self.t = t
  2045. def __str__(self):
  2046. return self.t[0]
  2047. class ClassAsPA2(object):
  2048. def __init__(self,l,t):
  2049. self.t = t
  2050. def __str__(self):
  2051. return self.t[0]
  2052. class ClassAsPA3(object):
  2053. def __init__(self,s,l,t):
  2054. self.t = t
  2055. def __str__(self):
  2056. return self.t[0]
  2057. class ClassAsPAStarNew(tuple):
  2058. def __new__(cls, *args):
  2059. print_("make a ClassAsPAStarNew", args)
  2060. return tuple.__new__(cls, *args[2].asList())
  2061. def __str__(self):
  2062. return ''.join(self)
  2063. from pyparsing import Literal,OneOrMore
  2064. A = Literal("A").setParseAction(pa0)
  2065. B = Literal("B").setParseAction(pa1)
  2066. C = Literal("C").setParseAction(pa2)
  2067. D = Literal("D").setParseAction(pa3)
  2068. E = Literal("E").setParseAction(Callable0())
  2069. F = Literal("F").setParseAction(Callable1())
  2070. G = Literal("G").setParseAction(Callable2())
  2071. H = Literal("H").setParseAction(Callable3())
  2072. I = Literal("I").setParseAction(CallableS0())
  2073. J = Literal("J").setParseAction(CallableS1())
  2074. K = Literal("K").setParseAction(CallableS2())
  2075. L = Literal("L").setParseAction(CallableS3())
  2076. M = Literal("M").setParseAction(CallableC0())
  2077. N = Literal("N").setParseAction(CallableC1())
  2078. O = Literal("O").setParseAction(CallableC2())
  2079. P = Literal("P").setParseAction(CallableC3())
  2080. Q = Literal("Q").setParseAction(paArgs)
  2081. R = Literal("R").setParseAction(parseActionHolder.pa3)
  2082. S = Literal("S").setParseAction(parseActionHolder.pa2)
  2083. T = Literal("T").setParseAction(parseActionHolder.pa1)
  2084. U = Literal("U").setParseAction(parseActionHolder.pa0)
  2085. V = Literal("V")
  2086. gg = OneOrMore( A | C | D | E | F | G | H |
  2087. I | J | K | L | M | N | O | P | Q | R | S | U | V | B | T)
  2088. testString = "VUTSRQPONMLKJIHGFEDCBA"
  2089. res = gg.parseString(testString)
  2090. print_(res.asList())
  2091. self.assertEqual(res.asList(), list(testString), "Failed to parse using variable length parse actions")
  2092. A = Literal("A").setParseAction(ClassAsPA0)
  2093. B = Literal("B").setParseAction(ClassAsPA1)
  2094. C = Literal("C").setParseAction(ClassAsPA2)
  2095. D = Literal("D").setParseAction(ClassAsPA3)
  2096. E = Literal("E").setParseAction(ClassAsPAStarNew)
  2097. gg = OneOrMore( A | B | C | D | E | F | G | H |
  2098. I | J | K | L | M | N | O | P | Q | R | S | T | U | V)
  2099. testString = "VUTSRQPONMLKJIHGFEDCBA"
  2100. res = gg.parseString(testString)
  2101. print_(list(map(str,res)))
  2102. self.assertEqual(list(map(str,res)), list(testString),
  2103. "Failed to parse using variable length parse actions "
  2104. "using class constructors as parse actions")
  2105. class EnablePackratParsing(ParseTestCase):
  2106. def runTest(self):
  2107. from pyparsing import ParserElement
  2108. ParserElement.enablePackrat()
  2109. class SingleArgExceptionTest(ParseTestCase):
  2110. def runTest(self):
  2111. from pyparsing import ParseBaseException,ParseFatalException
  2112. msg = ""
  2113. raisedMsg = ""
  2114. testMessage = "just one arg"
  2115. try:
  2116. raise ParseFatalException(testMessage)
  2117. except ParseBaseException as pbe:
  2118. print_("Received expected exception:", pbe)
  2119. raisedMsg = pbe.msg
  2120. self.assertEqual(raisedMsg, testMessage, "Failed to get correct exception message")
  2121. class OriginalTextForTest(ParseTestCase):
  2122. def runTest(self):
  2123. from pyparsing import makeHTMLTags, originalTextFor
  2124. def rfn(t):
  2125. return "%s:%d" % (t.src, len("".join(t)))
  2126. makeHTMLStartTag = lambda tag: originalTextFor(makeHTMLTags(tag)[0], asString=False)
  2127. # use the lambda, Luke
  2128. start = makeHTMLStartTag('IMG')
  2129. # don't replace our fancy parse action with rfn,
  2130. # append rfn to the list of parse actions
  2131. start.addParseAction(rfn)
  2132. text = '''_<img src="images/cal.png"
  2133. alt="cal image" width="16" height="15">_'''
  2134. s = start.transformString(text)
  2135. if VERBOSE:
  2136. print_(s)
  2137. self.assertTrue(s.startswith("_images/cal.png:"), "failed to preserve input s properly")
  2138. self.assertTrue(s.endswith("77_"),"failed to return full original text properly")
  2139. tag_fields = makeHTMLStartTag("IMG").searchString(text)[0]
  2140. if VERBOSE:
  2141. print_(sorted(tag_fields.keys()))
  2142. self.assertEqual(sorted(tag_fields.keys()),
  2143. ['alt', 'empty', 'height', 'src', 'startImg', 'tag', 'width'],
  2144. 'failed to preserve results names in originalTextFor')
  2145. class PackratParsingCacheCopyTest(ParseTestCase):
  2146. def runTest(self):
  2147. from pyparsing import Word,nums,delimitedList,Literal,Optional,alphas,alphanums,ZeroOrMore,empty
  2148. integer = Word(nums).setName("integer")
  2149. id = Word(alphas+'_',alphanums+'_')
  2150. simpleType = Literal('int');
  2151. arrayType= simpleType+ZeroOrMore('['+delimitedList(integer)+']')
  2152. varType = arrayType | simpleType
  2153. varDec = varType + delimitedList(id + Optional('='+integer))+';'
  2154. codeBlock = Literal('{}')
  2155. funcDef = Optional(varType | 'void')+id+'('+(delimitedList(varType+id)|'void'|empty)+')'+codeBlock
  2156. program = varDec | funcDef
  2157. input = 'int f(){}'
  2158. results = program.parseString(input)
  2159. print_("Parsed '%s' as %s" % (input, results.asList()))
  2160. self.assertEqual(results.asList(), ['int', 'f', '(', ')', '{}'], "Error in packrat parsing")
  2161. class PackratParsingCacheCopyTest2(ParseTestCase):
  2162. def runTest(self):
  2163. from pyparsing import Keyword,Word,Suppress,Forward,Optional,delimitedList,Group
  2164. DO,AA = list(map(Keyword, "DO AA".split()))
  2165. LPAR,RPAR = list(map(Suppress,"()"))
  2166. identifier = ~AA + Word("Z")
  2167. function_name = identifier.copy()
  2168. #~ function_name = ~AA + Word("Z") #identifier.copy()
  2169. expr = Forward().setName("expr")
  2170. expr << (Group(function_name + LPAR + Optional(delimitedList(expr)) + RPAR).setName("functionCall") |
  2171. identifier.setName("ident")#.setDebug()#.setBreak()
  2172. )
  2173. stmt = DO + Group(delimitedList(identifier + ".*" | expr))
  2174. result = stmt.parseString("DO Z")
  2175. print_(result.asList())
  2176. self.assertEqual(len(result[1]), 1, "packrat parsing is duplicating And term exprs")
  2177. class ParseResultsDelTest(ParseTestCase):
  2178. def runTest(self):
  2179. from pyparsing import OneOrMore, Word, alphas, nums
  2180. grammar = OneOrMore(Word(nums))("ints") + OneOrMore(Word(alphas))("words")
  2181. res = grammar.parseString("123 456 ABC DEF")
  2182. print_(res.dump())
  2183. origInts = res.ints.asList()
  2184. origWords = res.words.asList()
  2185. del res[1]
  2186. del res["words"]
  2187. print_(res.dump())
  2188. self.assertEqual(res[1], 'ABC',"failed to delete 0'th element correctly")
  2189. self.assertEqual(res.ints.asList(), origInts, "updated named attributes, should have updated list only")
  2190. self.assertEqual(res.words, "", "failed to update named attribute correctly")
  2191. self.assertEqual(res[-1], 'DEF', "updated list, should have updated named attributes only")
  2192. class WithAttributeParseActionTest(ParseTestCase):
  2193. def runTest(self):
  2194. """
  2195. This unit test checks withAttribute in these ways:
  2196. * Argument forms as keywords and tuples
  2197. * Selecting matching tags by attribute
  2198. * Case-insensitive attribute matching
  2199. * Correctly matching tags having the attribute, and rejecting tags not having the attribute
  2200. (Unit test written by voigts as part of the Google Highly Open Participation Contest)
  2201. """
  2202. from pyparsing import makeHTMLTags, Word, withAttribute, withClass, nums
  2203. data = """
  2204. <a>1</a>
  2205. <a b="x">2</a>
  2206. <a B="x">3</a>
  2207. <a b="X">4</a>
  2208. <a b="y">5</a>
  2209. <a class="boo">8</ a>
  2210. """
  2211. tagStart, tagEnd = makeHTMLTags("a")
  2212. expr = tagStart + Word(nums)("value") + tagEnd
  2213. expected = ([['a', ['b', 'x'], False, '2', '</a>'],
  2214. ['a', ['b', 'x'], False, '3', '</a>']],
  2215. [['a', ['b', 'x'], False, '2', '</a>'],
  2216. ['a', ['b', 'x'], False, '3', '</a>']],
  2217. [['a', ['class', 'boo'], False, '8', '</a>']],
  2218. )
  2219. for attrib, exp in zip([
  2220. withAttribute(b="x"),
  2221. #withAttribute(B="x"),
  2222. withAttribute(("b","x")),
  2223. #withAttribute(("B","x")),
  2224. withClass("boo"),
  2225. ], expected):
  2226. tagStart.setParseAction(attrib)
  2227. result = expr.searchString(data)
  2228. print_(result.dump())
  2229. self.assertEqual(result.asList(), exp, "Failed test, expected %s, got %s" % (expected, result.asList()))
  2230. class NestedExpressionsTest(ParseTestCase):
  2231. def runTest(self):
  2232. """
  2233. This unit test checks nestedExpr in these ways:
  2234. - use of default arguments
  2235. - use of non-default arguments (such as a pyparsing-defined comment
  2236. expression in place of quotedString)
  2237. - use of a custom content expression
  2238. - use of a pyparsing expression for opener and closer is *OPTIONAL*
  2239. - use of input data containing nesting delimiters
  2240. - correct grouping of parsed tokens according to nesting of opening
  2241. and closing delimiters in the input string
  2242. (Unit test written by christoph... as part of the Google Highly Open Participation Contest)
  2243. """
  2244. from pyparsing import nestedExpr, Literal, Regex, restOfLine, quotedString
  2245. #All defaults. Straight out of the example script. Also, qualifies for
  2246. #the bonus: note the fact that (Z | (E^F) & D) is not parsed :-).
  2247. # Tests for bug fixed in 1.4.10
  2248. print_("Test defaults:")
  2249. teststring = "(( ax + by)*C) (Z | (E^F) & D)"
  2250. expr = nestedExpr()
  2251. expected = [[['ax', '+', 'by'], '*C']]
  2252. result = expr.parseString(teststring)
  2253. print_(result.dump())
  2254. self.assertEqual(result.asList(), expected, "Defaults didn't work. That's a bad sign. Expected: %s, got: %s" % (expected, result))
  2255. #Going through non-defaults, one by one; trying to think of anything
  2256. #odd that might not be properly handled.
  2257. #Change opener
  2258. print_("\nNon-default opener")
  2259. opener = "["
  2260. teststring = test_string = "[[ ax + by)*C)"
  2261. expected = [[['ax', '+', 'by'], '*C']]
  2262. expr = nestedExpr("[")
  2263. result = expr.parseString(teststring)
  2264. print_(result.dump())
  2265. self.assertEqual(result.asList(), expected, "Non-default opener didn't work. Expected: %s, got: %s" % (expected, result))
  2266. #Change closer
  2267. print_("\nNon-default closer")
  2268. teststring = test_string = "(( ax + by]*C]"
  2269. expected = [[['ax', '+', 'by'], '*C']]
  2270. expr = nestedExpr(closer="]")
  2271. result = expr.parseString(teststring)
  2272. print_(result.dump())
  2273. self.assertEqual(result.asList(), expected, "Non-default closer didn't work. Expected: %s, got: %s" % (expected, result))
  2274. # #Multicharacter opener, closer
  2275. # opener = "bar"
  2276. # closer = "baz"
  2277. print_("\nLiteral expressions for opener and closer")
  2278. opener,closer = list(map(Literal, "bar baz".split()))
  2279. expr = nestedExpr(opener, closer,
  2280. content=Regex(r"([^b ]|b(?!a)|ba(?![rz]))+"))
  2281. teststring = "barbar ax + bybaz*Cbaz"
  2282. expected = [[['ax', '+', 'by'], '*C']]
  2283. # expr = nestedExpr(opener, closer)
  2284. result = expr.parseString(teststring)
  2285. print_(result.dump())
  2286. self.assertEqual(result.asList(), expected, "Multicharacter opener and closer didn't work. Expected: %s, got: %s" % (expected, result))
  2287. #Lisp-ish comments
  2288. print_("\nUse ignore expression (1)")
  2289. comment = Regex(r";;.*")
  2290. teststring = \
  2291. """
  2292. (let ((greeting "Hello, world!")) ;;(foo bar
  2293. (display greeting))
  2294. """
  2295. expected = [['let', [['greeting', '"Hello,', 'world!"']], ';;(foo bar',\
  2296. ['display', 'greeting']]]
  2297. expr = nestedExpr(ignoreExpr=comment)
  2298. result = expr.parseString(teststring)
  2299. print_(result.dump())
  2300. self.assertEqual(result.asList(), expected , "Lisp-ish comments (\";; <...> $\") didn't work. Expected: %s, got: %s" % (expected, result))
  2301. #Lisp-ish comments, using a standard bit of pyparsing, and an Or.
  2302. print_("\nUse ignore expression (2)")
  2303. comment = ';;' + restOfLine
  2304. teststring = \
  2305. """
  2306. (let ((greeting "Hello, )world!")) ;;(foo bar
  2307. (display greeting))
  2308. """
  2309. expected = [['let', [['greeting', '"Hello, )world!"']], ';;', '(foo bar',
  2310. ['display', 'greeting']]]
  2311. expr = nestedExpr(ignoreExpr=(comment ^ quotedString))
  2312. result = expr.parseString(teststring)
  2313. print_(result.dump())
  2314. self.assertEqual(result.asList(), expected ,
  2315. "Lisp-ish comments (\";; <...> $\") and quoted strings didn't work. Expected: %s, got: %s" % (expected, result))
  2316. class WordExcludeTest(ParseTestCase):
  2317. def runTest(self):
  2318. from pyparsing import Word, printables
  2319. allButPunc = Word(printables, excludeChars=".,:;-_!?")
  2320. test = "Hello, Mr. Ed, it's Wilbur!"
  2321. result = allButPunc.searchString(test).asList()
  2322. print_(result)
  2323. self.assertEqual(result, [['Hello'], ['Mr'], ['Ed'], ["it's"], ['Wilbur']], "failed WordExcludeTest")
  2324. class ParseAllTest(ParseTestCase):
  2325. def runTest(self):
  2326. from pyparsing import Word, cppStyleComment
  2327. testExpr = Word("A")
  2328. tests = [
  2329. ("AAAAA", False, True),
  2330. ("AAAAA", True, True),
  2331. ("AAABB", False, True),
  2332. ("AAABB", True, False),
  2333. ]
  2334. for s,parseAllFlag,shouldSucceed in tests:
  2335. try:
  2336. print_("'%s' parseAll=%s (shouldSuceed=%s)" % (s, parseAllFlag, shouldSucceed))
  2337. testExpr.parseString(s,parseAllFlag)
  2338. self.assertTrue(shouldSucceed, "successfully parsed when should have failed")
  2339. except ParseException as pe:
  2340. self.assertFalse(shouldSucceed, "failed to parse when should have succeeded")
  2341. # add test for trailing comments
  2342. testExpr.ignore(cppStyleComment)
  2343. tests = [
  2344. ("AAAAA //blah", False, True),
  2345. ("AAAAA //blah", True, True),
  2346. ("AAABB //blah", False, True),
  2347. ("AAABB //blah", True, False),
  2348. ]
  2349. for s,parseAllFlag,shouldSucceed in tests:
  2350. try:
  2351. print_("'%s' parseAll=%s (shouldSucceed=%s)" % (s, parseAllFlag, shouldSucceed))
  2352. testExpr.parseString(s,parseAllFlag)
  2353. self.assertTrue(shouldSucceed, "successfully parsed when should have failed")
  2354. except ParseException as pe:
  2355. self.assertFalse(shouldSucceed, "failed to parse when should have succeeded")
  2356. class GreedyQuotedStringsTest(ParseTestCase):
  2357. def runTest(self):
  2358. from pyparsing import QuotedString, sglQuotedString, dblQuotedString, quotedString, delimitedList
  2359. src = """\
  2360. "string1", "strin""g2"
  2361. 'string1', 'string2'
  2362. ^string1^, ^string2^
  2363. <string1>, <string2>"""
  2364. testExprs = (sglQuotedString, dblQuotedString, quotedString,
  2365. QuotedString('"', escQuote='""'), QuotedString("'", escQuote="''"),
  2366. QuotedString("^"), QuotedString("<",endQuoteChar=">"))
  2367. for expr in testExprs:
  2368. strs = delimitedList(expr).searchString(src)
  2369. print_(strs)
  2370. self.assertTrue(bool(strs), "no matches found for test expression '%s'" % expr)
  2371. for lst in strs:
  2372. self.assertEqual(len(lst), 2, "invalid match found for test expression '%s'" % expr)
  2373. from pyparsing import alphas, nums, Word
  2374. src = """'ms1',1,0,'2009-12-22','2009-12-22 10:41:22') ON DUPLICATE KEY UPDATE sent_count = sent_count + 1, mtime = '2009-12-22 10:41:22';"""
  2375. tok_sql_quoted_value = (
  2376. QuotedString("'", "\\", "''", True, False) ^
  2377. QuotedString('"', "\\", '""', True, False))
  2378. tok_sql_computed_value = Word(nums)
  2379. tok_sql_identifier = Word(alphas)
  2380. val = tok_sql_quoted_value | tok_sql_computed_value | tok_sql_identifier
  2381. vals = delimitedList(val)
  2382. print_(vals.parseString(src))
  2383. self.assertEqual(len(vals.parseString(src)), 5, "error in greedy quote escaping")
  2384. class WordBoundaryExpressionsTest(ParseTestCase):
  2385. def runTest(self):
  2386. from pyparsing import WordEnd, WordStart, oneOf
  2387. ws = WordStart()
  2388. we = WordEnd()
  2389. vowel = oneOf(list("AEIOUY"))
  2390. consonant = oneOf(list("BCDFGHJKLMNPQRSTVWXZ"))
  2391. leadingVowel = ws + vowel
  2392. trailingVowel = vowel + we
  2393. leadingConsonant = ws + consonant
  2394. trailingConsonant = consonant + we
  2395. internalVowel = ~ws + vowel + ~we
  2396. bnf = leadingVowel | trailingVowel
  2397. tests = """\
  2398. ABC DEF GHI
  2399. JKL MNO PQR
  2400. STU VWX YZ """.splitlines()
  2401. tests.append( "\n".join(tests) )
  2402. expectedResult = [
  2403. [['D', 'G'], ['A'], ['C', 'F'], ['I'], ['E'], ['A', 'I']],
  2404. [['J', 'M', 'P'], [], ['L', 'R'], ['O'], [], ['O']],
  2405. [['S', 'V'], ['Y'], ['X', 'Z'], ['U'], [], ['U', 'Y']],
  2406. [['D', 'G', 'J', 'M', 'P', 'S', 'V'],
  2407. ['A', 'Y'],
  2408. ['C', 'F', 'L', 'R', 'X', 'Z'],
  2409. ['I', 'O', 'U'],
  2410. ['E'],
  2411. ['A', 'I', 'O', 'U', 'Y']],
  2412. ]
  2413. for t,expected in zip(tests, expectedResult):
  2414. print_(t)
  2415. results = [flatten(e.searchString(t).asList()) for e in [
  2416. leadingConsonant,
  2417. leadingVowel,
  2418. trailingConsonant,
  2419. trailingVowel,
  2420. internalVowel,
  2421. bnf,
  2422. ]]
  2423. print_(results)
  2424. print_()
  2425. self.assertEqual(results, expected,"Failed WordBoundaryTest, expected %s, got %s" % (expected,results))
  2426. class RequiredEachTest(ParseTestCase):
  2427. def runTest(self):
  2428. from pyparsing import Keyword
  2429. parser = Keyword('bam') & Keyword('boo')
  2430. try:
  2431. res1 = parser.parseString('bam boo')
  2432. print_(res1.asList())
  2433. res2 = parser.parseString('boo bam')
  2434. print_(res2.asList())
  2435. except ParseException:
  2436. failed = True
  2437. else:
  2438. failed = False
  2439. self.assertFalse(failed, "invalid logic in Each")
  2440. self.assertEqual(set(res1), set(res2), "Failed RequiredEachTest, expected "
  2441. + str(res1.asList()) + " and " + str(res2.asList())
  2442. + "to contain same words in any order" )
  2443. class OptionalEachTest(ParseTestCase):
  2444. def runTest1(self):
  2445. from pyparsing import Optional, Keyword
  2446. for the_input in [
  2447. "Tal Weiss Major",
  2448. "Tal Major",
  2449. "Weiss Major",
  2450. "Major",
  2451. "Major Tal",
  2452. "Major Weiss",
  2453. "Major Tal Weiss",
  2454. ]:
  2455. print_(the_input)
  2456. parser1 = (Optional("Tal") + Optional("Weiss")) & Keyword("Major")
  2457. parser2 = Optional(Optional("Tal") + Optional("Weiss")) & Keyword("Major")
  2458. p1res = parser1.parseString(the_input)
  2459. p2res = parser2.parseString(the_input)
  2460. self.assertEqual(
  2461. p1res.asList(),
  2462. p2res.asList(),
  2463. "Each failed to match with nested Optionals, "
  2464. + str(p1res.asList())
  2465. + " should match "
  2466. + str(p2res.asList()),
  2467. )
  2468. def runTest2(self):
  2469. from pyparsing import Word, alphanums, OneOrMore, Group, Regex, Optional
  2470. word = Word(alphanums + '_').setName("word")
  2471. with_stmt = 'with' + OneOrMore(Group(word('key') + '=' + word('value')))('overrides')
  2472. using_stmt = 'using' + Regex('id-[0-9a-f]{8}')('id')
  2473. modifiers = Optional(with_stmt('with_stmt')) & Optional(using_stmt('using_stmt'))
  2474. self.assertEqual(modifiers, "with foo=bar bing=baz using id-deadbeef")
  2475. self.assertNotEqual(modifiers, "with foo=bar bing=baz using id-deadbeef using id-feedfeed")
  2476. def runTest3(self):
  2477. from pyparsing import Literal,Suppress,ZeroOrMore,OneOrMore
  2478. foo = Literal('foo')
  2479. bar = Literal('bar')
  2480. openBrace = Suppress(Literal("{"))
  2481. closeBrace = Suppress(Literal("}"))
  2482. exp = openBrace + (OneOrMore(foo)("foo") & ZeroOrMore(bar)("bar")) + closeBrace
  2483. tests = """\
  2484. {foo}
  2485. {bar foo bar foo bar foo}
  2486. """.splitlines()
  2487. for test in tests:
  2488. test = test.strip()
  2489. if not test:
  2490. continue
  2491. result = exp.parseString(test)
  2492. print_(test, '->', result.asList())
  2493. self.assertEqual(result.asList(), test.strip("{}").split(), "failed to parse Each expression %r" % test)
  2494. print_(result.dump())
  2495. try:
  2496. result = exp.parseString("{bar}")
  2497. self.assertTrue(False, "failed to raise exception when required element is missing")
  2498. except ParseException as pe:
  2499. pass
  2500. def runTest4(self):
  2501. from pyparsing import pyparsing_common, ZeroOrMore, Group
  2502. expr = ((~pyparsing_common.iso8601_date + pyparsing_common.integer("id"))
  2503. & ZeroOrMore(Group(pyparsing_common.iso8601_date)("date*")))
  2504. expr.runTests("""
  2505. 1999-12-31 100 2001-01-01
  2506. 42
  2507. """)
  2508. def testParseExpressionsWithRegex(self):
  2509. from itertools import product
  2510. match_empty_regex = pp.Regex(r"[a-z]*")
  2511. match_nonempty_regex = pp.Regex(r"[a-z]+")
  2512. parser_classes = pp.ParseExpression.__subclasses__()
  2513. test_string = "abc def"
  2514. expected = ["abc"]
  2515. for expr, cls in product((match_nonempty_regex, match_empty_regex), parser_classes):
  2516. print_(expr, cls)
  2517. parser = cls([expr])
  2518. parsed_result = parser.parseString(test_string)
  2519. print_(parsed_result.dump())
  2520. self.assertParseResultsEquals(parsed_result, expected)
  2521. for expr, cls in product((match_nonempty_regex, match_empty_regex), (pp.MatchFirst, pp.Or)):
  2522. parser = cls([expr, expr])
  2523. print_(parser)
  2524. parsed_result = parser.parseString(test_string)
  2525. print_(parsed_result.dump())
  2526. self.assertParseResultsEquals(parsed_result, expected)
  2527. def runTest(self):
  2528. self.runTest1()
  2529. self.runTest2()
  2530. self.runTest3()
  2531. self.runTest4()
  2532. self.testParseExpressionsWithRegex()
  2533. class SumParseResultsTest(ParseTestCase):
  2534. def runTest(self):
  2535. samplestr1 = "garbage;DOB 10-10-2010;more garbage\nID PARI12345678;more garbage"
  2536. samplestr2 = "garbage;ID PARI12345678;more garbage\nDOB 10-10-2010;more garbage"
  2537. samplestr3 = "garbage;DOB 10-10-2010"
  2538. samplestr4 = "garbage;ID PARI12345678;more garbage- I am cool"
  2539. res1 = "ID:PARI12345678 DOB:10-10-2010 INFO:"
  2540. res2 = "ID:PARI12345678 DOB:10-10-2010 INFO:"
  2541. res3 = "ID: DOB:10-10-2010 INFO:"
  2542. res4 = "ID:PARI12345678 DOB: INFO: I am cool"
  2543. from pyparsing import Regex, Word, alphanums, restOfLine
  2544. dob_ref = "DOB" + Regex(r"\d{2}-\d{2}-\d{4}")("dob")
  2545. id_ref = "ID" + Word(alphanums,exact=12)("id")
  2546. info_ref = "-" + restOfLine("info")
  2547. person_data = dob_ref | id_ref | info_ref
  2548. tests = (samplestr1,samplestr2,samplestr3,samplestr4,)
  2549. results = (res1, res2, res3, res4,)
  2550. for test,expected in zip(tests, results):
  2551. person = sum(person_data.searchString(test))
  2552. result = "ID:%s DOB:%s INFO:%s" % (person.id, person.dob, person.info)
  2553. print_(test)
  2554. print_(expected)
  2555. print_(result)
  2556. for pd in person_data.searchString(test):
  2557. print_(pd.dump())
  2558. print_()
  2559. self.assertEqual(expected, result,
  2560. "Failed to parse '%s' correctly, \nexpected '%s', got '%s'" % (test,expected,result))
  2561. class MarkInputLineTest(ParseTestCase):
  2562. def runTest(self):
  2563. samplestr1 = "DOB 100-10-2010;more garbage\nID PARI12345678;more garbage"
  2564. from pyparsing import Regex
  2565. dob_ref = "DOB" + Regex(r"\d{2}-\d{2}-\d{4}")("dob")
  2566. try:
  2567. res = dob_ref.parseString(samplestr1)
  2568. except ParseException as pe:
  2569. outstr = pe.markInputline()
  2570. print_(outstr)
  2571. self.assertEqual(outstr, "DOB >!<100-10-2010;more garbage", "did not properly create marked input line")
  2572. else:
  2573. self.assertEqual(False, "test construction failed - should have raised an exception")
  2574. class LocatedExprTest(ParseTestCase):
  2575. def runTest(self):
  2576. # 012345678901234567890123456789012345678901234567890
  2577. samplestr1 = "DOB 10-10-2010;more garbage;ID PARI12345678 ;more garbage"
  2578. from pyparsing import Word, alphanums, locatedExpr
  2579. id_ref = locatedExpr("ID" + Word(alphanums,exact=12)("id"))
  2580. res = id_ref.searchString(samplestr1)[0][0]
  2581. print_(res.dump())
  2582. self.assertEqual(samplestr1[res.locn_start:res.locn_end], 'ID PARI12345678', "incorrect location calculation")
  2583. class PopTest(ParseTestCase):
  2584. def runTest(self):
  2585. from pyparsing import Word, alphas, nums
  2586. source = "AAA 123 456 789 234"
  2587. patt = Word(alphas)("name") + Word(nums)*(1,)
  2588. result = patt.parseString(source)
  2589. tests = [
  2590. (0, 'AAA', ['123', '456', '789', '234']),
  2591. (None, '234', ['123', '456', '789']),
  2592. ('name', 'AAA', ['123', '456', '789']),
  2593. (-1, '789', ['123', '456']),
  2594. ]
  2595. for test in tests:
  2596. idx, val, remaining = test
  2597. if idx is not None:
  2598. ret = result.pop(idx)
  2599. else:
  2600. ret = result.pop()
  2601. print_("EXP:", val, remaining)
  2602. print_("GOT:", ret, result.asList())
  2603. print_(ret, result.asList())
  2604. self.assertEqual(ret, val, "wrong value returned, got %r, expected %r" % (ret, val))
  2605. self.assertEqual(remaining, result.asList(),
  2606. "list is in wrong state after pop, got %r, expected %r" % (result.asList(), remaining))
  2607. print_()
  2608. prevlist = result.asList()
  2609. ret = result.pop('name', default="noname")
  2610. print_(ret)
  2611. print_(result.asList())
  2612. self.assertEqual(ret, "noname",
  2613. "default value not successfully returned, got %r, expected %r" % (ret, "noname"))
  2614. self.assertEqual(result.asList(), prevlist,
  2615. "list is in wrong state after pop, got %r, expected %r" % (result.asList(), remaining))
  2616. class AddConditionTest(ParseTestCase):
  2617. def runTest(self):
  2618. from pyparsing import Word, nums, Suppress, ParseFatalException
  2619. numParser = Word(nums)
  2620. numParser.addParseAction(lambda s,l,t: int(t[0]))
  2621. numParser.addCondition(lambda s,l,t: t[0] % 2)
  2622. numParser.addCondition(lambda s,l,t: t[0] >= 7)
  2623. result = numParser.searchString("1 2 3 4 5 6 7 8 9 10")
  2624. print_(result.asList())
  2625. self.assertEqual(result.asList(), [[7],[9]], "failed to properly process conditions")
  2626. numParser = Word(nums)
  2627. numParser.addParseAction(lambda s,l,t: int(t[0]))
  2628. rangeParser = (numParser("from_") + Suppress('-') + numParser("to"))
  2629. result = rangeParser.searchString("1-4 2-4 4-3 5 6 7 8 9 10")
  2630. print_(result.asList())
  2631. self.assertEqual(result.asList(), [[1, 4], [2, 4], [4, 3]], "failed to properly process conditions")
  2632. rangeParser.addCondition(lambda t: t.to > t.from_, message="from must be <= to", fatal=False)
  2633. result = rangeParser.searchString("1-4 2-4 4-3 5 6 7 8 9 10")
  2634. print_(result.asList())
  2635. self.assertEqual(result.asList(), [[1, 4], [2, 4]], "failed to properly process conditions")
  2636. rangeParser = (numParser("from_") + Suppress('-') + numParser("to"))
  2637. rangeParser.addCondition(lambda t: t.to > t.from_, message="from must be <= to", fatal=True)
  2638. try:
  2639. result = rangeParser.searchString("1-4 2-4 4-3 5 6 7 8 9 10")
  2640. self.assertTrue(False, "failed to interrupt parsing on fatal condition failure")
  2641. except ParseFatalException:
  2642. print_("detected fatal condition")
  2643. class PatientOrTest(ParseTestCase):
  2644. def runTest(self):
  2645. import pyparsing as pp
  2646. # Two expressions and a input string which could - syntactically - be matched against
  2647. # both expressions. The "Literal" expression is considered invalid though, so this PE
  2648. # should always detect the "Word" expression.
  2649. def validate(token):
  2650. if token[0] == "def":
  2651. raise pp.ParseException("signalling invalid token")
  2652. return token
  2653. a = pp.Word("de").setName("Word")#.setDebug()
  2654. b = pp.Literal("def").setName("Literal").setParseAction(validate)#.setDebug()
  2655. c = pp.Literal("d").setName("d")#.setDebug()
  2656. # The "Literal" expressions's ParseAction is not executed directly after syntactically
  2657. # detecting the "Literal" Expression but only after the Or-decision has been made
  2658. # (which is too late)...
  2659. try:
  2660. result = (a ^ b ^ c).parseString("def")
  2661. self.assertEqual(result.asList(), ['de'], "failed to select longest match, chose %s" % result)
  2662. except ParseException:
  2663. failed = True
  2664. else:
  2665. failed = False
  2666. self.assertFalse(failed, "invalid logic in Or, fails on longest match with exception in parse action")
  2667. # from issue #93
  2668. word = pp.Word(pp.alphas).setName('word')
  2669. word_1 = pp.Word(pp.alphas).setName('word_1').addCondition(lambda t: len(t[0]) == 1)
  2670. a = word + (word_1 + word ^ word)
  2671. b = word * 3
  2672. c = a ^ b
  2673. c.streamline()
  2674. print_(c)
  2675. test_string = 'foo bar temp'
  2676. result = c.parseString(test_string)
  2677. print_(test_string, '->', result.asList())
  2678. self.assertEqual(result.asList(), test_string.split(), "failed to match longest choice")
  2679. class EachWithOptionalWithResultsNameTest(ParseTestCase):
  2680. def runTest(self):
  2681. from pyparsing import Optional
  2682. result = (Optional('foo')('one') & Optional('bar')('two')).parseString('bar foo')
  2683. print_(result.dump())
  2684. self.assertEqual(sorted(result.keys()), ['one','two'])
  2685. class UnicodeExpressionTest(ParseTestCase):
  2686. def runTest(self):
  2687. from pyparsing import Literal, ParseException
  2688. z = 'a' | Literal(u'\u1111')
  2689. z.streamline()
  2690. try:
  2691. z.parseString('b')
  2692. except ParseException as pe:
  2693. if not PY_3:
  2694. self.assertEqual(pe.msg, r'''Expected {"a" | "\u1111"}''',
  2695. "Invalid error message raised, got %r" % pe.msg)
  2696. else:
  2697. self.assertEqual(pe.msg, r'''Expected {"a" | "ᄑ"}''',
  2698. "Invalid error message raised, got %r" % pe.msg)
  2699. class SetNameTest(ParseTestCase):
  2700. def runTest(self):
  2701. from pyparsing import (oneOf,infixNotation,Word,nums,opAssoc,delimitedList,countedArray,
  2702. nestedExpr,makeHTMLTags,anyOpenTag,anyCloseTag,commonHTMLEntity,replaceHTMLEntity,
  2703. Forward,ZeroOrMore)
  2704. a = oneOf("a b c")
  2705. b = oneOf("d e f")
  2706. arith_expr = infixNotation(Word(nums),
  2707. [
  2708. (oneOf('* /'),2,opAssoc.LEFT),
  2709. (oneOf('+ -'),2,opAssoc.LEFT),
  2710. ])
  2711. arith_expr2 = infixNotation(Word(nums),
  2712. [
  2713. (('?',':'),3,opAssoc.LEFT),
  2714. ])
  2715. recursive = Forward()
  2716. recursive <<= a + ZeroOrMore(b + recursive)
  2717. tests = [
  2718. a,
  2719. b,
  2720. (a | b),
  2721. arith_expr,
  2722. arith_expr.expr,
  2723. arith_expr2,
  2724. arith_expr2.expr,
  2725. recursive,
  2726. delimitedList(Word(nums).setName("int")),
  2727. countedArray(Word(nums).setName("int")),
  2728. nestedExpr(),
  2729. makeHTMLTags('Z'),
  2730. (anyOpenTag,anyCloseTag),
  2731. commonHTMLEntity,
  2732. commonHTMLEntity.setParseAction(replaceHTMLEntity).transformString("lsdjkf &lt;lsdjkf&gt;&amp;&apos;&quot;&xyzzy;"),
  2733. ]
  2734. expected = map(str.strip, """\
  2735. a | b | c
  2736. d | e | f
  2737. {a | b | c | d | e | f}
  2738. Forward: + | - term
  2739. + | - term
  2740. Forward: ?: term
  2741. ?: term
  2742. Forward: {a | b | c [{d | e | f : ...}]...}
  2743. int [, int]...
  2744. (len) int...
  2745. nested () expression
  2746. (<Z>, </Z>)
  2747. (<any tag>, </any tag>)
  2748. common HTML entity
  2749. lsdjkf <lsdjkf>&'"&xyzzy;""".splitlines())
  2750. for t,e in zip(tests, expected):
  2751. tname = str(t)
  2752. print_(tname)
  2753. self.assertEqual(tname, e, "expression name mismatch, expected {0} got {1}".format(e, tname))
  2754. class TrimArityExceptionMaskingTest(ParseTestCase):
  2755. def runTest(self):
  2756. from pyparsing import Word
  2757. invalid_message = [
  2758. "<lambda>() takes exactly 1 argument (0 given)",
  2759. "<lambda>() missing 1 required positional argument: 't'"
  2760. ][PY_3]
  2761. try:
  2762. Word('a').setParseAction(lambda t: t[0]+1).parseString('aaa')
  2763. except Exception as e:
  2764. exc_msg = str(e)
  2765. self.assertNotEqual(exc_msg, invalid_message, "failed to catch TypeError thrown in _trim_arity")
  2766. class TrimArityExceptionMaskingTest2(ParseTestCase):
  2767. def runTest(self):
  2768. # construct deep call tree
  2769. def A():
  2770. import traceback
  2771. traceback.print_stack(limit=2)
  2772. from pyparsing import Word
  2773. invalid_message = [
  2774. "<lambda>() takes exactly 1 argument (0 given)",
  2775. "<lambda>() missing 1 required positional argument: 't'"
  2776. ][PY_3]
  2777. try:
  2778. Word('a').setParseAction(lambda t: t[0]+1).parseString('aaa')
  2779. except Exception as e:
  2780. exc_msg = str(e)
  2781. self.assertNotEqual(exc_msg, invalid_message, "failed to catch TypeError thrown in _trim_arity")
  2782. def B():
  2783. A()
  2784. def C():
  2785. B()
  2786. def D():
  2787. C()
  2788. def E():
  2789. D()
  2790. def F():
  2791. E()
  2792. def G():
  2793. F()
  2794. def H():
  2795. G()
  2796. def J():
  2797. H()
  2798. def K():
  2799. J()
  2800. K()
  2801. class ClearParseActionsTest(ParseTestCase):
  2802. def runTest(self):
  2803. import pyparsing as pp
  2804. ppc = pp.pyparsing_common
  2805. realnum = ppc.real()
  2806. self.assertEqual(realnum.parseString("3.14159")[0], 3.14159, "failed basic real number parsing")
  2807. # clear parse action that converts to float
  2808. realnum.setParseAction(None)
  2809. self.assertEqual(realnum.parseString("3.14159")[0], "3.14159", "failed clearing parse action")
  2810. # add a new parse action that tests if a '.' is prsent
  2811. realnum.addParseAction(lambda t: '.' in t[0])
  2812. self.assertEqual(realnum.parseString("3.14159")[0], True,
  2813. "failed setting new parse action after clearing parse action")
  2814. class OneOrMoreStopTest(ParseTestCase):
  2815. def runTest(self):
  2816. from pyparsing import (Word, OneOrMore, alphas, Keyword, CaselessKeyword,
  2817. nums, alphanums)
  2818. test = "BEGIN aaa bbb ccc END"
  2819. BEGIN,END = map(Keyword, "BEGIN,END".split(','))
  2820. body_word = Word(alphas).setName("word")
  2821. for ender in (END, "END", CaselessKeyword("END")):
  2822. expr = BEGIN + OneOrMore(body_word, stopOn=ender) + END
  2823. self.assertEqual(test, expr, "Did not successfully stop on ending expression %r" % ender)
  2824. if PY_3:
  2825. expr = eval('BEGIN + body_word[...].stopOn(ender) + END')
  2826. self.assertEqual(test, expr, "Did not successfully stop on ending expression %r" % ender)
  2827. number = Word(nums+',.()').setName("number with optional commas")
  2828. parser= (OneOrMore(Word(alphanums+'-/.'), stopOn=number)('id').setParseAction(' '.join)
  2829. + number('data'))
  2830. result = parser.parseString(' XXX Y/123 1,234.567890')
  2831. self.assertEqual(result.asList(), ['XXX Y/123', '1,234.567890'],
  2832. "Did not successfully stop on ending expression %r" % number)
  2833. class ZeroOrMoreStopTest(ParseTestCase):
  2834. def runTest(self):
  2835. from pyparsing import (Word, ZeroOrMore, alphas, Keyword, CaselessKeyword)
  2836. test = "BEGIN END"
  2837. BEGIN,END = map(Keyword, "BEGIN,END".split(','))
  2838. body_word = Word(alphas).setName("word")
  2839. for ender in (END, "END", CaselessKeyword("END")):
  2840. expr = BEGIN + ZeroOrMore(body_word, stopOn=ender) + END
  2841. self.assertEqual(test, expr, "Did not successfully stop on ending expression %r" % ender)
  2842. if PY_3:
  2843. expr = eval('BEGIN + body_word[0, ...].stopOn(ender) + END')
  2844. self.assertEqual(test, expr, "Did not successfully stop on ending expression %r" % ender)
  2845. class NestedAsDictTest(ParseTestCase):
  2846. def runTest(self):
  2847. from pyparsing import Literal, Forward, alphanums, Group, delimitedList, Dict, Word, Optional
  2848. equals = Literal("=").suppress()
  2849. lbracket = Literal("[").suppress()
  2850. rbracket = Literal("]").suppress()
  2851. lbrace = Literal("{").suppress()
  2852. rbrace = Literal("}").suppress()
  2853. value_dict = Forward()
  2854. value_list = Forward()
  2855. value_string = Word(alphanums + "@. ")
  2856. value = value_list ^ value_dict ^ value_string
  2857. values = Group(delimitedList(value, ","))
  2858. #~ values = delimitedList(value, ",").setParseAction(lambda toks: [toks.asList()])
  2859. value_list << lbracket + values + rbracket
  2860. identifier = Word(alphanums + "_.")
  2861. assignment = Group(identifier + equals + Optional(value))
  2862. assignments = Dict(delimitedList(assignment, ';'))
  2863. value_dict << lbrace + assignments + rbrace
  2864. response = assignments
  2865. rsp = 'username=goat; errors={username=[already taken, too short]}; empty_field='
  2866. result_dict = response.parseString(rsp).asDict()
  2867. print_(result_dict)
  2868. self.assertEqual(result_dict['username'], 'goat', "failed to process string in ParseResults correctly")
  2869. self.assertEqual(result_dict['errors']['username'], ['already taken', 'too short'],
  2870. "failed to process nested ParseResults correctly")
  2871. class TraceParseActionDecoratorTest(ParseTestCase):
  2872. def runTest(self):
  2873. from pyparsing import traceParseAction, Word, nums
  2874. @traceParseAction
  2875. def convert_to_int(t):
  2876. return int(t[0])
  2877. class Z(object):
  2878. def __call__(self, other):
  2879. return other[0] * 1000
  2880. integer = Word(nums).addParseAction(convert_to_int)
  2881. integer.addParseAction(traceParseAction(lambda t: t[0]*10))
  2882. integer.addParseAction(traceParseAction(Z()))
  2883. integer.parseString("132")
  2884. class RunTestsTest(ParseTestCase):
  2885. def runTest(self):
  2886. from pyparsing import Word, nums, delimitedList
  2887. integer = Word(nums).setParseAction(lambda t : int(t[0]))
  2888. intrange = integer("start") + '-' + integer("end")
  2889. intrange.addCondition(lambda t: t.end > t.start, message="invalid range, start must be <= end", fatal=True)
  2890. intrange.addParseAction(lambda t: list(range(t.start, t.end+1)))
  2891. indices = delimitedList(intrange | integer)
  2892. indices.addParseAction(lambda t: sorted(set(t)))
  2893. tests = """\
  2894. # normal data
  2895. 1-3,2-4,6,8-10,16
  2896. # lone integer
  2897. 11"""
  2898. results = indices.runTests(tests, printResults=False)[1]
  2899. expectedResults = [
  2900. [1, 2, 3, 4, 6, 8, 9, 10, 16],
  2901. [11],
  2902. ]
  2903. for res, expected in zip(results, expectedResults):
  2904. print_(res[1].asList())
  2905. print_(expected)
  2906. self.assertEqual(res[1].asList(), expected, "failed test: " + str(expected))
  2907. tests = """\
  2908. # invalid range
  2909. 1-2, 3-1, 4-6, 7, 12
  2910. """
  2911. success = indices.runTests(tests, printResults=False, failureTests=True)[0]
  2912. self.assertTrue(success, "failed to raise exception on improper range test")
  2913. class RunTestsPostParseTest(ParseTestCase):
  2914. def runTest(self):
  2915. import pyparsing as pp
  2916. integer = pp.pyparsing_common.integer
  2917. fraction = integer('numerator') + '/' + integer('denominator')
  2918. accum = []
  2919. def eval_fraction(test, result):
  2920. accum.append((test, result.asList()))
  2921. return "eval: {0}".format(result.numerator / result.denominator)
  2922. success = fraction.runTests("""\
  2923. 1/2
  2924. 1/0
  2925. """, postParse=eval_fraction)[0]
  2926. print_(success)
  2927. self.assertTrue(success, "failed to parse fractions in RunTestsPostParse")
  2928. expected_accum = [('1/2', [1, '/', 2]), ('1/0', [1, '/', 0])]
  2929. self.assertEqual(accum, expected_accum, "failed to call postParse method during runTests")
  2930. class CommonExpressionsTest(ParseTestCase):
  2931. def runTest(self):
  2932. from pyparsing import pyparsing_common
  2933. import ast
  2934. success = pyparsing_common.mac_address.runTests("""
  2935. AA:BB:CC:DD:EE:FF
  2936. AA.BB.CC.DD.EE.FF
  2937. AA-BB-CC-DD-EE-FF
  2938. """)[0]
  2939. self.assertTrue(success, "error in parsing valid MAC address")
  2940. success = pyparsing_common.mac_address.runTests("""
  2941. # mixed delimiters
  2942. AA.BB:CC:DD:EE:FF
  2943. """, failureTests=True)[0]
  2944. self.assertTrue( success, "error in detecting invalid mac address")
  2945. success = pyparsing_common.ipv4_address.runTests("""
  2946. 0.0.0.0
  2947. 1.1.1.1
  2948. 127.0.0.1
  2949. 1.10.100.199
  2950. 255.255.255.255
  2951. """)[0]
  2952. self.assertTrue(success, "error in parsing valid IPv4 address")
  2953. success = pyparsing_common.ipv4_address.runTests("""
  2954. # out of range value
  2955. 256.255.255.255
  2956. """, failureTests=True)[0]
  2957. self.assertTrue(success, "error in detecting invalid IPv4 address")
  2958. success = pyparsing_common.ipv6_address.runTests("""
  2959. 2001:0db8:85a3:0000:0000:8a2e:0370:7334
  2960. 2134::1234:4567:2468:1236:2444:2106
  2961. 0:0:0:0:0:0:A00:1
  2962. 1080::8:800:200C:417A
  2963. ::A00:1
  2964. # loopback address
  2965. ::1
  2966. # the null address
  2967. ::
  2968. # ipv4 compatibility form
  2969. ::ffff:192.168.0.1
  2970. """)[0]
  2971. self.assertTrue(success, "error in parsing valid IPv6 address")
  2972. success = pyparsing_common.ipv6_address.runTests("""
  2973. # too few values
  2974. 1080:0:0:0:8:800:200C
  2975. # too many ::'s, only 1 allowed
  2976. 2134::1234:4567::2444:2106
  2977. """, failureTests=True)[0]
  2978. self.assertTrue(success, "error in detecting invalid IPv6 address")
  2979. success = pyparsing_common.number.runTests("""
  2980. 100
  2981. -100
  2982. +100
  2983. 3.14159
  2984. 6.02e23
  2985. 1e-12
  2986. """)[0]
  2987. self.assertTrue(success, "error in parsing valid numerics")
  2988. success = pyparsing_common.sci_real.runTests("""
  2989. 1e12
  2990. -1e12
  2991. 3.14159
  2992. 6.02e23
  2993. """)[0]
  2994. self.assertTrue(success, "error in parsing valid scientific notation reals")
  2995. # any int or real number, returned as float
  2996. success = pyparsing_common.fnumber.runTests("""
  2997. 100
  2998. -100
  2999. +100
  3000. 3.14159
  3001. 6.02e23
  3002. 1e-12
  3003. """)[0]
  3004. self.assertTrue(success, "error in parsing valid numerics")
  3005. success, results = pyparsing_common.iso8601_date.runTests("""
  3006. 1997
  3007. 1997-07
  3008. 1997-07-16
  3009. """)
  3010. self.assertTrue(success, "error in parsing valid iso8601_date")
  3011. expected = [
  3012. ('1997', None, None),
  3013. ('1997', '07', None),
  3014. ('1997', '07', '16'),
  3015. ]
  3016. for r,exp in zip(results, expected):
  3017. self.assertTrue((r[1].year,r[1].month,r[1].day,) == exp, "failed to parse date into fields")
  3018. success, results = pyparsing_common.iso8601_date().addParseAction(pyparsing_common.convertToDate()).runTests("""
  3019. 1997-07-16
  3020. """)
  3021. self.assertTrue(success, "error in parsing valid iso8601_date with parse action")
  3022. self.assertTrue(results[0][1][0] == datetime.date(1997, 7, 16))
  3023. success, results = pyparsing_common.iso8601_datetime.runTests("""
  3024. 1997-07-16T19:20+01:00
  3025. 1997-07-16T19:20:30+01:00
  3026. 1997-07-16T19:20:30.45Z
  3027. 1997-07-16 19:20:30.45
  3028. """)
  3029. self.assertTrue(success, "error in parsing valid iso8601_datetime")
  3030. success, results = pyparsing_common.iso8601_datetime().addParseAction(pyparsing_common.convertToDatetime()).runTests("""
  3031. 1997-07-16T19:20:30.45
  3032. """)
  3033. self.assertTrue(success, "error in parsing valid iso8601_datetime")
  3034. self.assertTrue(results[0][1][0] == datetime.datetime(1997, 7, 16, 19, 20, 30, 450000))
  3035. success = pyparsing_common.uuid.runTests("""
  3036. 123e4567-e89b-12d3-a456-426655440000
  3037. """)[0]
  3038. self.assertTrue(success, "failed to parse valid uuid")
  3039. success = pyparsing_common.fraction.runTests("""
  3040. 1/2
  3041. -15/16
  3042. -3/-4
  3043. """)[0]
  3044. self.assertTrue(success, "failed to parse valid fraction")
  3045. success = pyparsing_common.mixed_integer.runTests("""
  3046. 1/2
  3047. -15/16
  3048. -3/-4
  3049. 1 1/2
  3050. 2 -15/16
  3051. 0 -3/-4
  3052. 12
  3053. """)[0]
  3054. self.assertTrue(success, "failed to parse valid mixed integer")
  3055. success, results = pyparsing_common.number.runTests("""
  3056. 100
  3057. -3
  3058. 1.732
  3059. -3.14159
  3060. 6.02e23""")
  3061. self.assertTrue(success, "failed to parse numerics")
  3062. for test,result in results:
  3063. expected = ast.literal_eval(test)
  3064. self.assertEqual(result[0], expected, "numeric parse failed (wrong value) (%s should be %s)" % (result[0], expected))
  3065. self.assertEqual(type(result[0]), type(expected), "numeric parse failed (wrong type) (%s should be %s)" % (type(result[0]), type(expected)))
  3066. class NumericExpressionsTest(ParseTestCase):
  3067. def runTest(self):
  3068. import pyparsing as pp
  3069. ppc = pp.pyparsing_common
  3070. # disable parse actions that do type conversion so we don't accidentally trigger
  3071. # conversion exceptions when what we want to check is the parsing expression
  3072. real = ppc.real().setParseAction(None)
  3073. sci_real = ppc.sci_real().setParseAction(None)
  3074. signed_integer = ppc.signed_integer().setParseAction(None)
  3075. from itertools import product
  3076. def make_tests():
  3077. leading_sign = ['+', '-', '']
  3078. leading_digit = ['0', '']
  3079. dot = ['.', '']
  3080. decimal_digit = ['1', '']
  3081. e = ['e', 'E', '']
  3082. e_sign = ['+', '-', '']
  3083. e_int = ['22', '']
  3084. stray = ['9', '.', '']
  3085. seen = set()
  3086. seen.add('')
  3087. for parts in product(leading_sign, stray, leading_digit, dot, decimal_digit, stray, e, e_sign, e_int,
  3088. stray):
  3089. parts_str = ''.join(parts).strip()
  3090. if parts_str in seen:
  3091. continue
  3092. seen.add(parts_str)
  3093. yield parts_str
  3094. print_(len(seen)-1, "tests produced")
  3095. # collect tests into valid/invalid sets, depending on whether they evaluate to valid Python floats or ints
  3096. valid_ints = set()
  3097. valid_reals = set()
  3098. valid_sci_reals = set()
  3099. invalid_ints = set()
  3100. invalid_reals = set()
  3101. invalid_sci_reals = set()
  3102. # check which strings parse as valid floats or ints, and store in related valid or invalid test sets
  3103. for test_str in make_tests():
  3104. if '.' in test_str or 'e' in test_str.lower():
  3105. try:
  3106. float(test_str)
  3107. except ValueError:
  3108. invalid_sci_reals.add(test_str)
  3109. if 'e' not in test_str.lower():
  3110. invalid_reals.add(test_str)
  3111. else:
  3112. valid_sci_reals.add(test_str)
  3113. if 'e' not in test_str.lower():
  3114. valid_reals.add(test_str)
  3115. try:
  3116. int(test_str)
  3117. except ValueError:
  3118. invalid_ints.add(test_str)
  3119. else:
  3120. valid_ints.add(test_str)
  3121. # now try all the test sets against their respective expressions
  3122. all_pass = True
  3123. suppress_results = {'printResults': False}
  3124. for expr, tests, is_fail, fn in zip([real, sci_real, signed_integer]*2,
  3125. [valid_reals, valid_sci_reals, valid_ints,
  3126. invalid_reals, invalid_sci_reals, invalid_ints],
  3127. [False, False, False, True, True, True],
  3128. [float, float, int]*2):
  3129. #
  3130. # success, test_results = expr.runTests(sorted(tests, key=len), failureTests=is_fail, **suppress_results)
  3131. # filter_result_fn = (lambda r: isinstance(r, Exception),
  3132. # lambda r: not isinstance(r, Exception))[is_fail]
  3133. # print_(expr, ('FAIL', 'PASS')[success], "{1}valid tests ({0})".format(len(tests),
  3134. # 'in' if is_fail else ''))
  3135. # if not success:
  3136. # all_pass = False
  3137. # for test_string, result in test_results:
  3138. # if filter_result_fn(result):
  3139. # try:
  3140. # test_value = fn(test_string)
  3141. # except ValueError as ve:
  3142. # test_value = str(ve)
  3143. # print_("{0!r}: {1} {2} {3}".format(test_string, result,
  3144. # expr.matches(test_string, parseAll=True), test_value))
  3145. success = True
  3146. for t in tests:
  3147. if expr.matches(t, parseAll=True):
  3148. if is_fail:
  3149. print_(t, "should fail but did not")
  3150. success = False
  3151. else:
  3152. if not is_fail:
  3153. print_(t, "should not fail but did")
  3154. success = False
  3155. print_(expr, ('FAIL', 'PASS')[success], "{1}valid tests ({0})".format(len(tests),
  3156. 'in' if is_fail else ''))
  3157. all_pass = all_pass and success
  3158. self.assertTrue(all_pass, "failed one or more numeric tests")
  3159. class TokenMapTest(ParseTestCase):
  3160. def runTest(self):
  3161. from pyparsing import tokenMap, Word, hexnums, OneOrMore
  3162. parser = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16))
  3163. success, results = parser.runTests("""
  3164. 00 11 22 aa FF 0a 0d 1a
  3165. """, printResults=False)
  3166. self.assertTrue(success, "failed to parse hex integers")
  3167. print_(results)
  3168. self.assertEqual(results[0][-1].asList(), [0, 17, 34, 170, 255, 10, 13, 26], "tokenMap parse action failed")
  3169. class ParseFileTest(ParseTestCase):
  3170. def runTest(self):
  3171. from pyparsing import pyparsing_common, OneOrMore
  3172. s = """
  3173. 123 456 789
  3174. """
  3175. input_file = StringIO(s)
  3176. integer = pyparsing_common.integer
  3177. results = OneOrMore(integer).parseFile(input_file)
  3178. print_(results)
  3179. results = OneOrMore(integer).parseFile('test/parsefiletest_input_file.txt')
  3180. print_(results)
  3181. class HTMLStripperTest(ParseTestCase):
  3182. def runTest(self):
  3183. from pyparsing import pyparsing_common, originalTextFor, OneOrMore, Word, printables
  3184. sample = """
  3185. <html>
  3186. Here is some sample <i>HTML</i> text.
  3187. </html>
  3188. """
  3189. read_everything = originalTextFor(OneOrMore(Word(printables)))
  3190. read_everything.addParseAction(pyparsing_common.stripHTMLTags)
  3191. result = read_everything.parseString(sample)
  3192. self.assertEqual(result[0].strip(), 'Here is some sample HTML text.')
  3193. class ExprSplitterTest(ParseTestCase):
  3194. def runTest(self):
  3195. from pyparsing import Literal, quotedString, pythonStyleComment, Empty
  3196. expr = Literal(';') + Empty()
  3197. expr.ignore(quotedString)
  3198. expr.ignore(pythonStyleComment)
  3199. sample = """
  3200. def main():
  3201. this_semi_does_nothing();
  3202. neither_does_this_but_there_are_spaces_afterward();
  3203. a = "a;b"; return a # this is a comment; it has a semicolon!
  3204. def b():
  3205. if False:
  3206. z=1000;b("; in quotes"); c=200;return z
  3207. return ';'
  3208. class Foo(object):
  3209. def bar(self):
  3210. '''a docstring; with a semicolon'''
  3211. a = 10; b = 11; c = 12
  3212. # this comment; has several; semicolons
  3213. if self.spam:
  3214. x = 12; return x # so; does; this; one
  3215. x = 15;;; y += x; return y
  3216. def baz(self):
  3217. return self.bar
  3218. """
  3219. expected = [
  3220. [' this_semi_does_nothing()', ''],
  3221. [' neither_does_this_but_there_are_spaces_afterward()', ''],
  3222. [' a = "a;b"', 'return a # this is a comment; it has a semicolon!'],
  3223. [' z=1000', 'b("; in quotes")', 'c=200', 'return z'],
  3224. [" return ';'"],
  3225. [" '''a docstring; with a semicolon'''"],
  3226. [' a = 10', 'b = 11', 'c = 12'],
  3227. [' # this comment; has several; semicolons'],
  3228. [' x = 12', 'return x # so; does; this; one'],
  3229. [' x = 15', '', '', 'y += x', 'return y'],
  3230. ]
  3231. exp_iter = iter(expected)
  3232. for line in filter(lambda ll: ';' in ll, sample.splitlines()):
  3233. print_(str(list(expr.split(line)))+',')
  3234. self.assertEqual(list(expr.split(line)), next(exp_iter), "invalid split on expression")
  3235. print_()
  3236. expected = [
  3237. [' this_semi_does_nothing()', ';', ''],
  3238. [' neither_does_this_but_there_are_spaces_afterward()', ';', ''],
  3239. [' a = "a;b"', ';', 'return a # this is a comment; it has a semicolon!'],
  3240. [' z=1000', ';', 'b("; in quotes")', ';', 'c=200', ';', 'return z'],
  3241. [" return ';'"],
  3242. [" '''a docstring; with a semicolon'''"],
  3243. [' a = 10', ';', 'b = 11', ';', 'c = 12'],
  3244. [' # this comment; has several; semicolons'],
  3245. [' x = 12', ';', 'return x # so; does; this; one'],
  3246. [' x = 15', ';', '', ';', '', ';', 'y += x', ';', 'return y'],
  3247. ]
  3248. exp_iter = iter(expected)
  3249. for line in filter(lambda ll: ';' in ll, sample.splitlines()):
  3250. print_(str(list(expr.split(line, includeSeparators=True)))+',')
  3251. self.assertEqual(list(expr.split(line, includeSeparators=True)), next(exp_iter),
  3252. "invalid split on expression")
  3253. print_()
  3254. expected = [
  3255. [' this_semi_does_nothing()', ''],
  3256. [' neither_does_this_but_there_are_spaces_afterward()', ''],
  3257. [' a = "a;b"', 'return a # this is a comment; it has a semicolon!'],
  3258. [' z=1000', 'b("; in quotes"); c=200;return z'],
  3259. [' a = 10', 'b = 11; c = 12'],
  3260. [' x = 12', 'return x # so; does; this; one'],
  3261. [' x = 15', ';; y += x; return y'],
  3262. ]
  3263. exp_iter = iter(expected)
  3264. for line in sample.splitlines():
  3265. pieces = list(expr.split(line, maxsplit=1))
  3266. print_(str(pieces)+',')
  3267. if len(pieces) == 2:
  3268. exp = next(exp_iter)
  3269. self.assertEqual(pieces, exp, "invalid split on expression with maxSplits=1")
  3270. elif len(pieces) == 1:
  3271. self.assertEqual(len(expr.searchString(line)), 0, "invalid split with maxSplits=1 when expr not present")
  3272. else:
  3273. print_("\n>>> " + line)
  3274. self.assertTrue(False, "invalid split on expression with maxSplits=1, corner case")
  3275. class ParseFatalExceptionTest(ParseTestCase):
  3276. def runTest(self):
  3277. from pyparsing import Word, nums, ParseFatalException
  3278. success = False
  3279. try:
  3280. expr = "ZZZ" - Word(nums)
  3281. expr.parseString("ZZZ bad")
  3282. except ParseFatalException as pfe:
  3283. print_('ParseFatalException raised correctly')
  3284. success = True
  3285. except Exception as e:
  3286. print_(type(e))
  3287. print_(e)
  3288. self.assertTrue(success, "bad handling of syntax error")
  3289. class InlineLiteralsUsingTest(ParseTestCase):
  3290. def runTest(self):
  3291. from pyparsing import ParserElement, Suppress, Literal, CaselessLiteral, Word, alphas, oneOf, CaselessKeyword, nums
  3292. with AutoReset(ParserElement, "_literalStringClass"):
  3293. ParserElement.inlineLiteralsUsing(Suppress)
  3294. wd = Word(alphas)
  3295. result = (wd + ',' + wd + oneOf("! . ?")).parseString("Hello, World!")
  3296. self.assertEqual(len(result), 3, "inlineLiteralsUsing(Suppress) failed!")
  3297. ParserElement.inlineLiteralsUsing(Literal)
  3298. result = (wd + ',' + wd + oneOf("! . ?")).parseString("Hello, World!")
  3299. self.assertEqual(len(result), 4, "inlineLiteralsUsing(Literal) failed!")
  3300. ParserElement.inlineLiteralsUsing(CaselessKeyword)
  3301. result = ("SELECT" + wd + "FROM" + wd).parseString("select color from colors")
  3302. self.assertEqual(result.asList(), "SELECT color FROM colors".split(),
  3303. "inlineLiteralsUsing(CaselessKeyword) failed!")
  3304. ParserElement.inlineLiteralsUsing(CaselessLiteral)
  3305. result = ("SELECT" + wd + "FROM" + wd).parseString("select color from colors")
  3306. self.assertEqual(result.asList(), "SELECT color FROM colors".split(),
  3307. "inlineLiteralsUsing(CaselessLiteral) failed!")
  3308. integer = Word(nums)
  3309. ParserElement.inlineLiteralsUsing(Literal)
  3310. date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
  3311. result = date_str.parseString("1999/12/31")
  3312. self.assertEqual(result.asList(), ['1999', '/', '12', '/', '31'], "inlineLiteralsUsing(example 1) failed!")
  3313. # change to Suppress
  3314. ParserElement.inlineLiteralsUsing(Suppress)
  3315. date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
  3316. result = date_str.parseString("1999/12/31") # -> ['1999', '12', '31']
  3317. self.assertEqual(result.asList(), ['1999', '12', '31'], "inlineLiteralsUsing(example 2) failed!")
  3318. class CloseMatchTest(ParseTestCase):
  3319. def runTest(self):
  3320. import pyparsing as pp
  3321. searchseq = pp.CloseMatch("ATCATCGAATGGA", 2)
  3322. _, results = searchseq.runTests("""
  3323. ATCATCGAATGGA
  3324. XTCATCGAATGGX
  3325. ATCATCGAAXGGA
  3326. ATCAXXGAATGGA
  3327. ATCAXXGAATGXA
  3328. ATCAXXGAATGG
  3329. """)
  3330. expected = (
  3331. [],
  3332. [0,12],
  3333. [9],
  3334. [4,5],
  3335. None,
  3336. None
  3337. )
  3338. for r, exp in zip(results, expected):
  3339. if exp is not None:
  3340. self.assertEqual(r[1].mismatches, exp,
  3341. "fail CloseMatch between %r and %r" % (searchseq.match_string, r[0]))
  3342. print_(r[0], 'exc: %s' % r[1] if exp is None and isinstance(r[1], Exception)
  3343. else ("no match", "match")[r[1].mismatches == exp])
  3344. class DefaultKeywordCharsTest(ParseTestCase):
  3345. def runTest(self):
  3346. import pyparsing as pp
  3347. try:
  3348. pp.Keyword("start").parseString("start1000")
  3349. except pp.ParseException:
  3350. pass
  3351. else:
  3352. self.assertTrue(False, "failed to fail on default keyword chars")
  3353. try:
  3354. pp.Keyword("start", identChars=pp.alphas).parseString("start1000")
  3355. except pp.ParseException:
  3356. self.assertTrue(False, "failed to match keyword using updated keyword chars")
  3357. else:
  3358. pass
  3359. with AutoReset(pp.Keyword, "DEFAULT_KEYWORD_CHARS"):
  3360. pp.Keyword.setDefaultKeywordChars(pp.alphas)
  3361. try:
  3362. pp.Keyword("start").parseString("start1000")
  3363. except pp.ParseException:
  3364. self.assertTrue(False, "failed to match keyword using updated keyword chars")
  3365. else:
  3366. pass
  3367. try:
  3368. pp.CaselessKeyword("START").parseString("start1000")
  3369. except pp.ParseException:
  3370. pass
  3371. else:
  3372. self.assertTrue(False, "failed to fail on default keyword chars")
  3373. try:
  3374. pp.CaselessKeyword("START", identChars=pp.alphas).parseString("start1000")
  3375. except pp.ParseException:
  3376. self.assertTrue(False, "failed to match keyword using updated keyword chars")
  3377. else:
  3378. pass
  3379. with AutoReset(pp.Keyword, "DEFAULT_KEYWORD_CHARS"):
  3380. pp.Keyword.setDefaultKeywordChars(pp.alphas)
  3381. try:
  3382. pp.CaselessKeyword("START").parseString("start1000")
  3383. except pp.ParseException:
  3384. self.assertTrue(False, "failed to match keyword using updated keyword chars")
  3385. else:
  3386. pass
  3387. class ColTest(ParseTestCase):
  3388. def runTest(self):
  3389. test = "*\n* \n* ALF\n*\n"
  3390. initials = [c for i, c in enumerate(test) if pp.col(i, test) == 1]
  3391. print_(initials)
  3392. self.assertTrue(len(initials) == 4 and all(c=='*' for c in initials), 'fail col test')
  3393. class LiteralExceptionTest(ParseTestCase):
  3394. def runTest(self):
  3395. import pyparsing as pp
  3396. for cls in (pp.Literal, pp.CaselessLiteral, pp.Keyword, pp.CaselessKeyword,
  3397. pp.Word, pp.Regex):
  3398. expr = cls('xyz')#.setName('{0}_expr'.format(cls.__name__.lower()))
  3399. try:
  3400. expr.parseString(' ')
  3401. except Exception as e:
  3402. print_(cls.__name__, str(e))
  3403. self.assertTrue(isinstance(e, pp.ParseBaseException),
  3404. "class {0} raised wrong exception type {1}".format(cls.__name__, type(e).__name__))
  3405. class ParseActionExceptionTest(ParseTestCase):
  3406. def runTest(self):
  3407. self.expect_traceback = True
  3408. import pyparsing as pp
  3409. import traceback
  3410. number = pp.Word(pp.nums)
  3411. def number_action():
  3412. raise IndexError # this is the important line!
  3413. number.setParseAction(number_action)
  3414. symbol = pp.Word('abcd', max=1)
  3415. expr = number | symbol
  3416. try:
  3417. expr.parseString('1 + 2')
  3418. except Exception as e:
  3419. self.assertTrue(hasattr(e, '__cause__'), "no __cause__ attribute in the raised exception")
  3420. self.assertTrue(e.__cause__ is not None, "__cause__ not propagated to outer exception")
  3421. self.assertTrue(type(e.__cause__) == IndexError, "__cause__ references wrong exception")
  3422. traceback.print_exc()
  3423. else:
  3424. self.assertTrue(False, "Expected ParseException not raised")
  3425. class ParseActionNestingTest(ParseTestCase):
  3426. # tests Issue #22
  3427. def runTest(self):
  3428. vals = pp.OneOrMore(pp.pyparsing_common.integer)("int_values")
  3429. def add_total(tokens):
  3430. tokens['total'] = sum(tokens)
  3431. return tokens
  3432. vals.addParseAction(add_total)
  3433. results = vals.parseString("244 23 13 2343")
  3434. print_(results.dump())
  3435. self.assertEqual(results.int_values.asDict(), {}, "noop parse action changed ParseResults structure")
  3436. name = pp.Word(pp.alphas)('name')
  3437. score = pp.Word(pp.nums + '.')('score')
  3438. nameScore = pp.Group(name + score)
  3439. line1 = nameScore('Rider')
  3440. result1 = line1.parseString('Mauney 46.5')
  3441. print_("### before parse action is added ###")
  3442. print_("result1.dump():\n" + result1.dump() + "\n")
  3443. before_pa_dict = result1.asDict()
  3444. line1.setParseAction(lambda t: t)
  3445. result1 = line1.parseString('Mauney 46.5')
  3446. after_pa_dict = result1.asDict()
  3447. print_("### after parse action was added ###")
  3448. print_("result1.dump():\n" + result1.dump() + "\n")
  3449. self.assertEqual(before_pa_dict, after_pa_dict, "noop parse action changed ParseResults structure")
  3450. class ParseResultsNameBelowUngroupedNameTest(ParseTestCase):
  3451. def runTest(self):
  3452. import pyparsing as pp
  3453. rule_num = pp.Regex("[0-9]+")("LIT_NUM*")
  3454. list_num = pp.Group(pp.Literal("[")("START_LIST")
  3455. + pp.delimitedList(rule_num)("LIST_VALUES")
  3456. + pp.Literal("]")("END_LIST"))("LIST")
  3457. test_string = "[ 1,2,3,4,5,6 ]"
  3458. list_num.runTests(test_string)
  3459. U = list_num.parseString(test_string)
  3460. self.assertTrue("LIT_NUM" not in U.LIST.LIST_VALUES, "results name retained as sub in ungrouped named result")
  3461. class ParseResultsNamesInGroupWithDictTest(ParseTestCase):
  3462. def runTest(self):
  3463. import pyparsing as pp
  3464. from pyparsing import pyparsing_common as ppc
  3465. key = ppc.identifier()
  3466. value = ppc.integer()
  3467. lat = ppc.real()
  3468. long = ppc.real()
  3469. EQ = pp.Suppress('=')
  3470. data = lat("lat") + long("long") + pp.Dict(pp.OneOrMore(pp.Group(key + EQ + value)))
  3471. site = pp.QuotedString('"')("name") + pp.Group(data)("data")
  3472. test_string = '"Golden Gate Bridge" 37.819722 -122.478611 height=746 span=4200'
  3473. site.runTests(test_string)
  3474. # U = list_num.parseString(test_string)
  3475. # self.assertTrue("LIT_NUM" not in U.LIST.LIST_VALUES, "results name retained as sub in ungrouped named result")
  3476. a, aEnd = pp.makeHTMLTags('a')
  3477. attrs = a.parseString("<a href='blah'>")
  3478. print_(attrs.dump())
  3479. self.assertEqual(attrs.startA.href, 'blah')
  3480. self.assertEqual(attrs.asDict(), {'startA': {'href': 'blah', 'tag': 'a', 'empty': False},
  3481. 'href': 'blah', 'tag': 'a', 'empty': False})
  3482. class FollowedByTest(ParseTestCase):
  3483. def runTest(self):
  3484. import pyparsing as pp
  3485. from pyparsing import pyparsing_common as ppc
  3486. expr = pp.Word(pp.alphas)("item") + pp.FollowedBy(ppc.integer("qty"))
  3487. result = expr.parseString("balloon 99")
  3488. print_(result.dump())
  3489. self.assertTrue('qty' in result, "failed to capture results name in FollowedBy")
  3490. self.assertEqual(result.asDict(), {'item': 'balloon', 'qty': 99},
  3491. "invalid results name structure from FollowedBy")
  3492. class SetBreakTest(ParseTestCase):
  3493. """
  3494. Test behavior of ParserElement.setBreak(), to invoke the debugger before parsing that element is attempted.
  3495. Temporarily monkeypatches pdb.set_trace.
  3496. """
  3497. def runTest(self):
  3498. was_called = []
  3499. def mock_set_trace():
  3500. was_called.append(True)
  3501. import pyparsing as pp
  3502. wd = pp.Word(pp.alphas)
  3503. wd.setBreak()
  3504. print_("Before parsing with setBreak:", was_called)
  3505. import pdb
  3506. with AutoReset(pdb, "set_trace"):
  3507. pdb.set_trace = mock_set_trace
  3508. wd.parseString("ABC")
  3509. print_("After parsing with setBreak:", was_called)
  3510. self.assertTrue(bool(was_called), "set_trace wasn't called by setBreak")
  3511. class UnicodeTests(ParseTestCase):
  3512. def runTest(self):
  3513. import pyparsing as pp
  3514. ppu = pp.pyparsing_unicode
  3515. ppc = pp.pyparsing_common
  3516. # verify proper merging of ranges by addition
  3517. kanji_printables = ppu.Japanese.Kanji.printables
  3518. katakana_printables = ppu.Japanese.Katakana.printables
  3519. hiragana_printables = ppu.Japanese.Hiragana.printables
  3520. japanese_printables = ppu.Japanese.printables
  3521. self.assertEqual(set(japanese_printables), set(kanji_printables
  3522. + katakana_printables
  3523. + hiragana_printables),
  3524. "failed to construct ranges by merging Japanese types")
  3525. # verify proper merging of ranges using multiple inheritance
  3526. cjk_printables = ppu.CJK.printables
  3527. self.assertEqual(len(cjk_printables), len(set(cjk_printables)),
  3528. "CJK contains duplicate characters - all should be unique")
  3529. chinese_printables = ppu.Chinese.printables
  3530. korean_printables = ppu.Korean.printables
  3531. print_(len(cjk_printables), len(set(chinese_printables
  3532. + korean_printables
  3533. + japanese_printables)))
  3534. self.assertEqual(len(cjk_printables), len(set(chinese_printables
  3535. + korean_printables
  3536. + japanese_printables)),
  3537. "failed to construct ranges by merging Chinese, Japanese and Korean")
  3538. alphas = ppu.Greek.alphas
  3539. greet = pp.Word(alphas) + ',' + pp.Word(alphas) + '!'
  3540. # input string
  3541. hello = u"Καλημέρα, κόσμε!"
  3542. result = greet.parseString(hello)
  3543. print_(result)
  3544. self.assertTrue(result.asList() == [u'Καλημέρα', ',', u'κόσμε', '!'],
  3545. "Failed to parse Greek 'Hello, World!' using pyparsing_unicode.Greek.alphas")
  3546. # define a custom unicode range using multiple inheritance
  3547. class Turkish_set(ppu.Latin1, ppu.LatinA):
  3548. pass
  3549. self.assertEqual(set(Turkish_set.printables),
  3550. set(ppu.Latin1.printables + ppu.LatinA.printables),
  3551. "failed to construct ranges by merging Latin1 and LatinA (printables)")
  3552. self.assertEqual(set(Turkish_set.alphas),
  3553. set(ppu.Latin1.alphas + ppu.LatinA.alphas),
  3554. "failed to construct ranges by merging Latin1 and LatinA (alphas)")
  3555. self.assertEqual(set(Turkish_set.nums),
  3556. set(ppu.Latin1.nums + ppu.LatinA.nums),
  3557. "failed to construct ranges by merging Latin1 and LatinA (nums)")
  3558. key = pp.Word(Turkish_set.alphas)
  3559. value = ppc.integer | pp.Word(Turkish_set.alphas, Turkish_set.alphanums)
  3560. EQ = pp.Suppress('=')
  3561. key_value = key + EQ + value
  3562. sample = u"""\
  3563. şehir=İzmir
  3564. ülke=Türkiye
  3565. nüfus=4279677"""
  3566. result = pp.Dict(pp.OneOrMore(pp.Group(key_value))).parseString(sample)
  3567. print_(result.asDict())
  3568. self.assertEqual(result.asDict(), {u'şehir': u'İzmir', u'ülke': u'Türkiye', u'nüfus': 4279677},
  3569. "Failed to parse Turkish key-value pairs")
  3570. class IndentedBlockExampleTest(ParseTestCase):
  3571. # Make sure example in indentedBlock docstring actually works!
  3572. def runTest(self):
  3573. from textwrap import dedent
  3574. from pyparsing import (Word, alphas, alphanums, indentedBlock, Optional, delimitedList, Group, Forward,
  3575. nums, OneOrMore)
  3576. data = dedent('''
  3577. def A(z):
  3578. A1
  3579. B = 100
  3580. G = A2
  3581. A2
  3582. A3
  3583. B
  3584. def BB(a,b,c):
  3585. BB1
  3586. def BBA():
  3587. bba1
  3588. bba2
  3589. bba3
  3590. C
  3591. D
  3592. def spam(x,y):
  3593. def eggs(z):
  3594. pass
  3595. ''')
  3596. indentStack = [1]
  3597. stmt = Forward()
  3598. identifier = Word(alphas, alphanums)
  3599. funcDecl = ("def" + identifier + Group("(" + Optional(delimitedList(identifier)) + ")") + ":")
  3600. func_body = indentedBlock(stmt, indentStack)
  3601. funcDef = Group(funcDecl + func_body)
  3602. rvalue = Forward()
  3603. funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")")
  3604. rvalue << (funcCall | identifier | Word(nums))
  3605. assignment = Group(identifier + "=" + rvalue)
  3606. stmt << (funcDef | assignment | identifier)
  3607. module_body = OneOrMore(stmt)
  3608. parseTree = module_body.parseString(data)
  3609. parseTree.pprint()
  3610. self.assertEqual(parseTree.asList(),
  3611. [['def',
  3612. 'A',
  3613. ['(', 'z', ')'],
  3614. ':',
  3615. [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]],
  3616. 'B',
  3617. ['def',
  3618. 'BB',
  3619. ['(', 'a', 'b', 'c', ')'],
  3620. ':',
  3621. [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]],
  3622. 'C',
  3623. 'D',
  3624. ['def',
  3625. 'spam',
  3626. ['(', 'x', 'y', ')'],
  3627. ':',
  3628. [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]],
  3629. "Failed indentedBlock example"
  3630. )
  3631. class IndentedBlockTest(ParseTestCase):
  3632. # parse pseudo-yaml indented text
  3633. def runTest(self):
  3634. import textwrap
  3635. EQ = pp.Suppress('=')
  3636. stack = [1]
  3637. key = pp.pyparsing_common.identifier
  3638. value = pp.Forward()
  3639. key_value = key + EQ + value
  3640. compound_value = pp.Dict(pp.ungroup(pp.indentedBlock(key_value, stack)))
  3641. value <<= pp.pyparsing_common.integer | pp.QuotedString("'") | compound_value
  3642. parser = pp.Dict(pp.OneOrMore(pp.Group(key_value)))
  3643. text = """
  3644. a = 100
  3645. b = 101
  3646. c =
  3647. c1 = 200
  3648. c2 =
  3649. c21 = 999
  3650. c3 = 'A horse, a horse, my kingdom for a horse'
  3651. d = 505
  3652. """
  3653. text = textwrap.dedent(text)
  3654. print_(text)
  3655. result = parser.parseString(text)
  3656. print_(result.dump())
  3657. self.assertEqual(result.a, 100, "invalid indented block result")
  3658. self.assertEqual(result.c.c1, 200, "invalid indented block result")
  3659. self.assertEqual(result.c.c2.c21, 999, "invalid indented block result")
  3660. class IndentedBlockTest2(ParseTestCase):
  3661. # exercise indentedBlock with example posted in issue #87
  3662. def runTest(self):
  3663. from textwrap import dedent
  3664. from pyparsing import Word, alphas, alphanums, Suppress, Forward, indentedBlock, Literal, OneOrMore
  3665. indent_stack = [1]
  3666. key = Word(alphas, alphanums) + Suppress(":")
  3667. stmt = Forward()
  3668. suite = indentedBlock(stmt, indent_stack)
  3669. body = key + suite
  3670. pattern = (Word(alphas) + Suppress("(") + Word(alphas) + Suppress(")"))
  3671. stmt << pattern
  3672. def key_parse_action(toks):
  3673. print_("Parsing '%s'..." % toks[0])
  3674. key.setParseAction(key_parse_action)
  3675. header = Suppress("[") + Literal("test") + Suppress("]")
  3676. content = (header + OneOrMore(indentedBlock(body, indent_stack, False)))
  3677. contents = Forward()
  3678. suites = indentedBlock(content, indent_stack)
  3679. extra = Literal("extra") + Suppress(":") + suites
  3680. contents << (content | extra)
  3681. parser = OneOrMore(contents)
  3682. sample = dedent("""
  3683. extra:
  3684. [test]
  3685. one0:
  3686. two (three)
  3687. four0:
  3688. five (seven)
  3689. extra:
  3690. [test]
  3691. one1:
  3692. two (three)
  3693. four1:
  3694. five (seven)
  3695. """)
  3696. success, _ = parser.runTests([sample])
  3697. self.assertTrue(success, "Failed indentedBlock test for issue #87")
  3698. class IndentedBlockScanTest(ParseTestCase):
  3699. def get_parser(self):
  3700. """
  3701. A valid statement is the word "block:", followed by an indent, followed by the letter A only, or another block
  3702. """
  3703. stack = [1]
  3704. block = pp.Forward()
  3705. body = pp.indentedBlock(pp.Literal('A') ^ block, indentStack=stack, indent=True)
  3706. block <<= pp.Literal('block:') + body
  3707. return block
  3708. def runTest(self):
  3709. from textwrap import dedent
  3710. # This input string is a perfect match for the parser, so a single match is found
  3711. p1 = self.get_parser()
  3712. r1 = list(p1.scanString(dedent("""\
  3713. block:
  3714. A
  3715. """)))
  3716. self.assertEqual(len(r1), 1)
  3717. # This input string is a perfect match for the parser, except for the letter B instead of A, so this will fail (and should)
  3718. p2 = self.get_parser()
  3719. r2 = list(p2.scanString(dedent("""\
  3720. block:
  3721. B
  3722. """)))
  3723. self.assertEqual(len(r2), 0)
  3724. # This input string contains both string A and string B, and it finds one match (as it should)
  3725. p3 = self.get_parser()
  3726. r3 = list(p3.scanString(dedent("""\
  3727. block:
  3728. A
  3729. block:
  3730. B
  3731. """)))
  3732. self.assertEqual(len(r3), 1)
  3733. # This input string contains both string A and string B, but in a different order.
  3734. p4 = self.get_parser()
  3735. r4 = list(p4.scanString(dedent("""\
  3736. block:
  3737. B
  3738. block:
  3739. A
  3740. """)))
  3741. self.assertEqual(len(r4), 1)
  3742. # This is the same as case 3, but with nesting
  3743. p5 = self.get_parser()
  3744. r5 = list(p5.scanString(dedent("""\
  3745. block:
  3746. block:
  3747. A
  3748. block:
  3749. block:
  3750. B
  3751. """)))
  3752. self.assertEqual(len(r5), 1)
  3753. # This is the same as case 4, but with nesting
  3754. p6 = self.get_parser()
  3755. r6 = list(p6.scanString(dedent("""\
  3756. block:
  3757. block:
  3758. B
  3759. block:
  3760. block:
  3761. A
  3762. """)))
  3763. self.assertEqual(len(r6), 1)
  3764. class ParseResultsWithNameMatchFirst(ParseTestCase):
  3765. def runTest(self):
  3766. import pyparsing as pp
  3767. expr_a = pp.Literal('not') + pp.Literal('the') + pp.Literal('bird')
  3768. expr_b = pp.Literal('the') + pp.Literal('bird')
  3769. expr = (expr_a | expr_b)('rexp')
  3770. expr.runTests("""\
  3771. not the bird
  3772. the bird
  3773. """)
  3774. self.assertEqual(list(expr.parseString('not the bird')['rexp']), 'not the bird'.split())
  3775. self.assertEqual(list(expr.parseString('the bird')['rexp']), 'the bird'.split())
  3776. # test compatibility mode, restoring pre-2.3.1 behavior
  3777. with AutoReset(pp.__compat__, "collect_all_And_tokens"):
  3778. pp.__compat__.collect_all_And_tokens = False
  3779. pp.__diag__.warn_multiple_tokens_in_named_alternation = True
  3780. expr_a = pp.Literal('not') + pp.Literal('the') + pp.Literal('bird')
  3781. expr_b = pp.Literal('the') + pp.Literal('bird')
  3782. if PY_3:
  3783. with self.assertWarns(UserWarning, msg="failed to warn of And within alternation"):
  3784. expr = (expr_a | expr_b)('rexp')
  3785. else:
  3786. self.expect_warning = True
  3787. expr = (expr_a | expr_b)('rexp')
  3788. expr.runTests("""
  3789. not the bird
  3790. the bird
  3791. """)
  3792. self.assertEqual(expr.parseString('not the bird')['rexp'], 'not')
  3793. self.assertEqual(expr.parseString('the bird')['rexp'], 'the')
  3794. class ParseResultsWithNameOr(ParseTestCase):
  3795. def runTest(self):
  3796. import pyparsing as pp
  3797. expr_a = pp.Literal('not') + pp.Literal('the') + pp.Literal('bird')
  3798. expr_b = pp.Literal('the') + pp.Literal('bird')
  3799. expr = (expr_a ^ expr_b)('rexp')
  3800. expr.runTests("""\
  3801. not the bird
  3802. the bird
  3803. """)
  3804. self.assertEqual(list(expr.parseString('not the bird')['rexp']), 'not the bird'.split())
  3805. self.assertEqual(list(expr.parseString('the bird')['rexp']), 'the bird'.split())
  3806. expr = (expr_a | expr_b)('rexp')
  3807. expr.runTests("""\
  3808. not the bird
  3809. the bird
  3810. """)
  3811. self.assertEqual(list(expr.parseString('not the bird')['rexp']), 'not the bird'.split())
  3812. self.assertEqual(list(expr.parseString('the bird')['rexp']), 'the bird'.split())
  3813. # test compatibility mode, restoring pre-2.3.1 behavior
  3814. with AutoReset(pp.__compat__, "collect_all_And_tokens"):
  3815. pp.__compat__.collect_all_And_tokens = False
  3816. pp.__diag__.warn_multiple_tokens_in_named_alternation = True
  3817. expr_a = pp.Literal('not') + pp.Literal('the') + pp.Literal('bird')
  3818. expr_b = pp.Literal('the') + pp.Literal('bird')
  3819. if PY_3:
  3820. with self.assertWarns(UserWarning, msg="failed to warn of And within alternation"):
  3821. expr = (expr_a ^ expr_b)('rexp')
  3822. else:
  3823. self.expect_warning = True
  3824. expr = (expr_a ^ expr_b)('rexp')
  3825. expr.runTests("""\
  3826. not the bird
  3827. the bird
  3828. """)
  3829. self.assertEqual(expr.parseString('not the bird')['rexp'], 'not')
  3830. self.assertEqual(expr.parseString('the bird')['rexp'], 'the')
  3831. class EmptyDictDoesNotRaiseException(ParseTestCase):
  3832. def runTest(self):
  3833. import pyparsing as pp
  3834. key = pp.Word(pp.alphas)
  3835. value = pp.Word(pp.nums)
  3836. EQ = pp.Suppress('=')
  3837. key_value_dict = pp.dictOf(key, EQ + value)
  3838. print_(key_value_dict.parseString("""\
  3839. a = 10
  3840. b = 20
  3841. """).dump())
  3842. try:
  3843. print_(key_value_dict.parseString("").dump())
  3844. except pp.ParseException as pe:
  3845. exc = pe
  3846. if not hasattr(exc, '__traceback__'):
  3847. # Python 2 compatibility
  3848. etype, value, traceback = sys.exc_info()
  3849. exc.__traceback__ = traceback
  3850. print_(pp.ParseException.explain(pe))
  3851. else:
  3852. self.assertTrue(False, "failed to raise exception when matching empty string")
  3853. class ExplainExceptionTest(ParseTestCase):
  3854. def runTest(self):
  3855. import pyparsing as pp
  3856. expr = pp.Word(pp.nums).setName("int") + pp.Word(pp.alphas).setName("word")
  3857. try:
  3858. expr.parseString("123 355")
  3859. except pp.ParseException as pe:
  3860. exc = pe
  3861. if not hasattr(exc, '__traceback__'):
  3862. # Python 2 compatibility
  3863. etype, value, traceback = sys.exc_info()
  3864. exc.__traceback__ = traceback
  3865. print_(pp.ParseException.explain(pe, depth=0))
  3866. expr = pp.Word(pp.nums).setName("int") - pp.Word(pp.alphas).setName("word")
  3867. try:
  3868. expr.parseString("123 355 (test using ErrorStop)")
  3869. except pp.ParseSyntaxException as pe:
  3870. exc = pe
  3871. if not hasattr(exc, '__traceback__'):
  3872. # Python 2 compatibility
  3873. etype, value, traceback = sys.exc_info()
  3874. exc.__traceback__ = traceback
  3875. print_(pp.ParseException.explain(pe))
  3876. integer = pp.Word(pp.nums).setName("int").addParseAction(lambda t: int(t[0]))
  3877. expr = integer + integer
  3878. def divide_args(t):
  3879. integer.parseString("A")
  3880. return t[0] / t[1]
  3881. expr.addParseAction(divide_args)
  3882. pp.ParserElement.enablePackrat()
  3883. print_()
  3884. # ~ print(expr.parseString("125 25"))
  3885. try:
  3886. expr.parseString("123 0")
  3887. except pp.ParseException as pe:
  3888. exc = pe
  3889. if not hasattr(exc, '__traceback__'):
  3890. # Python 2 compatibility
  3891. etype, value, traceback = sys.exc_info()
  3892. exc.__traceback__ = traceback
  3893. print_(pp.ParseException.explain(pe))
  3894. except Exception as exc:
  3895. if not hasattr(exc, '__traceback__'):
  3896. # Python 2 compatibility
  3897. etype, value, traceback = sys.exc_info()
  3898. exc.__traceback__ = traceback
  3899. print_(pp.ParseException.explain(exc))
  3900. raise
  3901. class CaselessKeywordVsKeywordCaselessTest(ParseTestCase):
  3902. def runTest(self):
  3903. import pyparsing as pp
  3904. frule = pp.Keyword('t', caseless=True) + pp.Keyword('yes', caseless=True)
  3905. crule = pp.CaselessKeyword('t') + pp.CaselessKeyword('yes')
  3906. flist = frule.searchString('not yes').asList()
  3907. print_(flist)
  3908. clist = crule.searchString('not yes').asList()
  3909. print_(clist)
  3910. self.assertEqual(flist, clist, "CaselessKeyword not working the same as Keyword(caseless=True)")
  3911. class OneOfKeywordsTest(ParseTestCase):
  3912. def runTest(self):
  3913. import pyparsing as pp
  3914. literal_expr = pp.oneOf("a b c")
  3915. success, _ = literal_expr[...].runTests("""
  3916. # literal oneOf tests
  3917. a b c
  3918. a a a
  3919. abc
  3920. """)
  3921. self.assertTrue(success, "failed literal oneOf matching")
  3922. keyword_expr = pp.oneOf("a b c", asKeyword=True)
  3923. success, _ = keyword_expr[...].runTests("""
  3924. # keyword oneOf tests
  3925. a b c
  3926. a a a
  3927. """)
  3928. self.assertTrue(success, "failed keyword oneOf matching")
  3929. success, _ = keyword_expr[...].runTests("""
  3930. # keyword oneOf failure tests
  3931. abc
  3932. """, failureTests=True)
  3933. self.assertTrue(success, "failed keyword oneOf failure tests")
  3934. class WarnUngroupedNamedTokensTest(ParseTestCase):
  3935. """
  3936. - warn_ungrouped_named_tokens_in_collection - flag to enable warnings when a results
  3937. name is defined on a containing expression with ungrouped subexpressions that also
  3938. have results names (default=True)
  3939. """
  3940. def runTest(self):
  3941. import pyparsing as pp
  3942. ppc = pp.pyparsing_common
  3943. pp.__diag__.warn_ungrouped_named_tokens_in_collection = True
  3944. COMMA = pp.Suppress(',').setName("comma")
  3945. coord = (ppc.integer('x') + COMMA + ppc.integer('y'))
  3946. # this should emit a warning
  3947. if PY_3:
  3948. with self.assertWarns(UserWarning, msg="failed to warn with named repetition of"
  3949. " ungrouped named expressions"):
  3950. path = coord[...].setResultsName('path')
  3951. pp.__diag__.warn_ungrouped_named_tokens_in_collection = False
  3952. class WarnNameSetOnEmptyForwardTest(ParseTestCase):
  3953. """
  3954. - warn_name_set_on_empty_Forward - flag to enable warnings whan a Forward is defined
  3955. with a results name, but has no contents defined (default=False)
  3956. """
  3957. def runTest(self):
  3958. import pyparsing as pp
  3959. pp.__diag__.warn_name_set_on_empty_Forward = True
  3960. base = pp.Forward()
  3961. if PY_3:
  3962. with self.assertWarns(UserWarning, msg="failed to warn when naming an empty Forward expression"):
  3963. base("x")
  3964. class WarnOnMultipleStringArgsToOneOfTest(ParseTestCase):
  3965. """
  3966. - warn_on_multiple_string_args_to_oneof - flag to enable warnings whan oneOf is
  3967. incorrectly called with multiple str arguments (default=True)
  3968. """
  3969. def runTest(self):
  3970. import pyparsing as pp
  3971. pp.__diag__.warn_on_multiple_string_args_to_oneof = True
  3972. if PY_3:
  3973. with self.assertWarns(UserWarning, msg="failed to warn when incorrectly calling oneOf(string, string)"):
  3974. a = pp.oneOf('A', 'B')
  3975. class EnableDebugOnNamedExpressionsTest(ParseTestCase):
  3976. """
  3977. - enable_debug_on_named_expressions - flag to auto-enable debug on all subsequent
  3978. calls to ParserElement.setName() (default=False)
  3979. """
  3980. def runTest(self):
  3981. import pyparsing as pp
  3982. import textwrap
  3983. test_stdout = StringIO()
  3984. with AutoReset(sys, 'stdout', 'stderr'):
  3985. sys.stdout = test_stdout
  3986. sys.stderr = test_stdout
  3987. pp.__diag__.enable_debug_on_named_expressions = True
  3988. integer = pp.Word(pp.nums).setName('integer')
  3989. integer[...].parseString("1 2 3")
  3990. expected_debug_output = textwrap.dedent("""\
  3991. Match integer at loc 0(1,1)
  3992. Matched integer -> ['1']
  3993. Match integer at loc 1(1,2)
  3994. Matched integer -> ['2']
  3995. Match integer at loc 3(1,4)
  3996. Matched integer -> ['3']
  3997. Match integer at loc 5(1,6)
  3998. Exception raised:Expected integer, found end of text (at char 5), (line:1, col:6)
  3999. """)
  4000. output = test_stdout.getvalue()
  4001. print_(output)
  4002. self.assertEqual(output,
  4003. expected_debug_output,
  4004. "failed to auto-enable debug on named expressions "
  4005. "using enable_debug_on_named_expressions")
  4006. class UndesirableButCommonPracticesTest(ParseTestCase):
  4007. def runTest(self):
  4008. import pyparsing as pp
  4009. ppc = pp.pyparsing_common
  4010. # While these are valid constructs, and they are not encouraged
  4011. # there is apparently a lot of code out there using these
  4012. # coding styles.
  4013. #
  4014. # Even though they are not encouraged, we shouldn't break them.
  4015. # Create an And using a list of expressions instead of using '+' operator
  4016. expr = pp.And([pp.Word('abc'), pp.Word('123')])
  4017. expr.runTests("""
  4018. aaa 333
  4019. b 1
  4020. ababab 32123
  4021. """)
  4022. # Passing a single expression to a ParseExpression, when it really wants a sequence
  4023. expr = pp.Or(pp.Or(ppc.integer))
  4024. expr.runTests("""
  4025. 123
  4026. 456
  4027. abc
  4028. """)
  4029. class ChainedTernaryOperator(ParseTestCase):
  4030. def runTest(self):
  4031. import pyparsing as pp
  4032. TERNARY_INFIX = pp.infixNotation(
  4033. pp.pyparsing_common.integer, [
  4034. (("?", ":"), 3, pp.opAssoc.LEFT),
  4035. ])
  4036. self.assertParseAndCheckList(TERNARY_INFIX,
  4037. "1?1:0?1:0",
  4038. [[1, '?', 1, ':', 0, '?', 1, ':', 0]])
  4039. TERNARY_INFIX = pp.infixNotation(
  4040. pp.pyparsing_common.integer, [
  4041. (("?", ":"), 3, pp.opAssoc.RIGHT),
  4042. ])
  4043. self.assertParseAndCheckList(TERNARY_INFIX,
  4044. "1?1:0?1:0",
  4045. [[1, '?', 1, ':', [0, '?', 1, ':', 0]]])
  4046. class MiscellaneousParserTests(ParseTestCase):
  4047. def runTest(self):
  4048. self.expect_warning = True
  4049. runtests = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  4050. if IRON_PYTHON_ENV:
  4051. runtests = "ABCDEGHIJKLMNOPQRSTUVWXYZ"
  4052. # test making oneOf with duplicate symbols
  4053. if "A" in runtests:
  4054. print_("verify oneOf handles duplicate symbols")
  4055. try:
  4056. test1 = pp.oneOf("a b c d a")
  4057. except RuntimeError:
  4058. self.assertTrue(False,"still have infinite loop in oneOf with duplicate symbols (string input)")
  4059. print_("verify oneOf handles generator input")
  4060. try:
  4061. test1 = pp.oneOf(c for c in "a b c d a" if not c.isspace())
  4062. except RuntimeError:
  4063. self.assertTrue(False,"still have infinite loop in oneOf with duplicate symbols (generator input)")
  4064. print_("verify oneOf handles list input")
  4065. try:
  4066. test1 = pp.oneOf("a b c d a".split())
  4067. except RuntimeError:
  4068. self.assertTrue(False,"still have infinite loop in oneOf with duplicate symbols (list input)")
  4069. print_("verify oneOf handles set input")
  4070. try:
  4071. test1 = pp.oneOf(set("a b c d a"))
  4072. except RuntimeError:
  4073. self.assertTrue(False,"still have infinite loop in oneOf with duplicate symbols (set input)")
  4074. # test MatchFirst bugfix
  4075. if "B" in runtests:
  4076. print_("verify MatchFirst iterates properly")
  4077. results = pp.quotedString.parseString("'this is a single quoted string'")
  4078. self.assertTrue(len(results) > 0, "MatchFirst error - not iterating over all choices")
  4079. # verify streamline of subexpressions
  4080. if "C" in runtests:
  4081. print_("verify proper streamline logic")
  4082. compound = pp.Literal("A") + "B" + "C" + "D"
  4083. self.assertEqual(len(compound.exprs), 2,"bad test setup")
  4084. print_(compound)
  4085. compound.streamline()
  4086. print_(compound)
  4087. self.assertEqual(len(compound.exprs), 4,"streamline not working")
  4088. # test for Optional with results name and no match
  4089. if "D" in runtests:
  4090. print_("verify Optional's do not cause match failure if have results name")
  4091. testGrammar = pp.Literal("A") + pp.Optional("B")("gotB") + pp.Literal("C")
  4092. try:
  4093. testGrammar.parseString("ABC")
  4094. testGrammar.parseString("AC")
  4095. except pp.ParseException as pe:
  4096. print_(pe.pstr,"->",pe)
  4097. self.assertTrue(False, "error in Optional matching of string %s" % pe.pstr)
  4098. # test return of furthest exception
  4099. if "E" in runtests:
  4100. testGrammar = ( pp.Literal("A") |
  4101. ( pp.Optional("B") + pp.Literal("C") ) |
  4102. pp.Literal("D") )
  4103. try:
  4104. testGrammar.parseString("BC")
  4105. testGrammar.parseString("BD")
  4106. except pp.ParseException as pe:
  4107. print_(pe.pstr,"->",pe)
  4108. self.assertEqual(pe.pstr, "BD", "wrong test string failed to parse")
  4109. self.assertEqual(pe.loc, 1, "error in Optional matching, pe.loc="+str(pe.loc))
  4110. # test validate
  4111. if "F" in runtests:
  4112. print_("verify behavior of validate()")
  4113. def testValidation( grmr, gnam, isValid ):
  4114. try:
  4115. grmr.streamline()
  4116. grmr.validate()
  4117. self.assertTrue(isValid,"validate() accepted invalid grammar " + gnam)
  4118. except pp.RecursiveGrammarException as e:
  4119. print_(grmr)
  4120. self.assertFalse(isValid, "validate() rejected valid grammar " + gnam)
  4121. fwd = pp.Forward()
  4122. g1 = pp.OneOrMore( ( pp.Literal("A") + "B" + "C" ) | fwd )
  4123. g2 = pp.ZeroOrMore("C" + g1)
  4124. fwd << pp.Group(g2)
  4125. testValidation( fwd, "fwd", isValid=True )
  4126. fwd2 = pp.Forward()
  4127. fwd2 << pp.Group("A" | fwd2)
  4128. testValidation( fwd2, "fwd2", isValid=False )
  4129. fwd3 = pp.Forward()
  4130. fwd3 << pp.Optional("A") + fwd3
  4131. testValidation( fwd3, "fwd3", isValid=False )
  4132. # test getName
  4133. if "G" in runtests:
  4134. print_("verify behavior of getName()")
  4135. aaa = pp.Group(pp.Word("a")("A"))
  4136. bbb = pp.Group(pp.Word("b")("B"))
  4137. ccc = pp.Group(":" + pp.Word("c")("C"))
  4138. g1 = "XXX" + pp.ZeroOrMore( aaa | bbb | ccc )
  4139. teststring = "XXX b bb a bbb bbbb aa bbbbb :c bbbbbb aaa"
  4140. names = []
  4141. print_(g1.parseString(teststring).dump())
  4142. for t in g1.parseString(teststring):
  4143. print_(t, repr(t))
  4144. try:
  4145. names.append( t[0].getName() )
  4146. except Exception:
  4147. try:
  4148. names.append( t.getName() )
  4149. except Exception:
  4150. names.append( None )
  4151. print_(teststring)
  4152. print_(names)
  4153. self.assertEqual(names, [None, 'B', 'B', 'A', 'B', 'B', 'A', 'B', None, 'B', 'A'],
  4154. "failure in getting names for tokens")
  4155. from pyparsing import Keyword, Word, alphas, OneOrMore
  4156. IF,AND,BUT = map(Keyword, "if and but".split())
  4157. ident = ~(IF | AND | BUT) + Word(alphas)("non-key")
  4158. scanner = OneOrMore(IF | AND | BUT | ident)
  4159. def getNameTester(s,l,t):
  4160. print_(t, t.getName())
  4161. ident.addParseAction(getNameTester)
  4162. scanner.parseString("lsjd sldkjf IF Saslkj AND lsdjf")
  4163. # test ParseResults.get() method
  4164. if "H" in runtests:
  4165. print_("verify behavior of ParseResults.get()")
  4166. # use sum() to merge separate groups into single ParseResults
  4167. res = sum(g1.parseString(teststring)[1:])
  4168. print_(res.dump())
  4169. print_(res.get("A","A not found"))
  4170. print_(res.get("D","!D"))
  4171. self.assertEqual(res.get("A","A not found"), "aaa", "get on existing key failed")
  4172. self.assertEqual(res.get("D","!D"), "!D", "get on missing key failed")
  4173. if "I" in runtests:
  4174. print_("verify handling of Optional's beyond the end of string")
  4175. testGrammar = "A" + pp.Optional("B") + pp.Optional("C") + pp.Optional("D")
  4176. testGrammar.parseString("A")
  4177. testGrammar.parseString("AB")
  4178. # test creating Literal with empty string
  4179. if "J" in runtests:
  4180. print_('verify non-fatal usage of Literal("")')
  4181. e = pp.Literal("")
  4182. try:
  4183. e.parseString("SLJFD")
  4184. except Exception as e:
  4185. self.assertTrue(False, "Failed to handle empty Literal")
  4186. # test line() behavior when starting at 0 and the opening line is an \n
  4187. if "K" in runtests:
  4188. print_('verify correct line() behavior when first line is empty string')
  4189. self.assertEqual(pp.line(0, "\nabc\ndef\n"), '', "Error in line() with empty first line in text")
  4190. txt = "\nabc\ndef\n"
  4191. results = [ pp.line(i,txt) for i in range(len(txt)) ]
  4192. self.assertEqual(results, ['', 'abc', 'abc', 'abc', 'abc', 'def', 'def', 'def', 'def'],
  4193. "Error in line() with empty first line in text")
  4194. txt = "abc\ndef\n"
  4195. results = [ pp.line(i,txt) for i in range(len(txt)) ]
  4196. self.assertEqual(results, ['abc', 'abc', 'abc', 'abc', 'def', 'def', 'def', 'def'],
  4197. "Error in line() with non-empty first line in text")
  4198. # test bugfix with repeated tokens when packrat parsing enabled
  4199. if "L" in runtests:
  4200. print_('verify behavior with repeated tokens when packrat parsing is enabled')
  4201. a = pp.Literal("a")
  4202. b = pp.Literal("b")
  4203. c = pp.Literal("c")
  4204. abb = a + b + b
  4205. abc = a + b + c
  4206. aba = a + b + a
  4207. grammar = abb | abc | aba
  4208. self.assertEqual(''.join(grammar.parseString( "aba" )), 'aba', "Packrat ABA failure!")
  4209. if "M" in runtests:
  4210. print_('verify behavior of setResultsName with OneOrMore and ZeroOrMore')
  4211. stmt = pp.Keyword('test')
  4212. print_(pp.ZeroOrMore(stmt)('tests').parseString('test test').tests)
  4213. print_(pp.OneOrMore(stmt)('tests').parseString('test test').tests)
  4214. print_(pp.Optional(pp.OneOrMore(stmt)('tests')).parseString('test test').tests)
  4215. print_(pp.Optional(pp.OneOrMore(stmt))('tests').parseString('test test').tests)
  4216. print_(pp.Optional(pp.delimitedList(stmt))('tests').parseString('test,test').tests)
  4217. self.assertEqual(len(pp.ZeroOrMore(stmt)('tests').parseString('test test').tests), 2, "ZeroOrMore failure with setResultsName")
  4218. self.assertEqual(len(pp.OneOrMore(stmt)('tests').parseString('test test').tests), 2, "OneOrMore failure with setResultsName")
  4219. self.assertEqual(len(pp.Optional(pp.OneOrMore(stmt)('tests')).parseString('test test').tests), 2, "OneOrMore failure with setResultsName")
  4220. self.assertEqual(len(pp.Optional(pp.delimitedList(stmt))('tests').parseString('test,test').tests), 2, "delimitedList failure with setResultsName")
  4221. self.assertEqual(len((stmt*2)('tests').parseString('test test').tests), 2, "multiplied(1) failure with setResultsName")
  4222. self.assertEqual(len((stmt*(None,2))('tests').parseString('test test').tests), 2, "multiplied(2) failure with setResultsName")
  4223. self.assertEqual(len((stmt*(1,))('tests').parseString('test test').tests), 2, "multipled(3) failure with setResultsName")
  4224. self.assertEqual(len((stmt*(2,))('tests').parseString('test test').tests), 2, "multipled(3) failure with setResultsName")
  4225. def makeTestSuite():
  4226. import inspect
  4227. suite = TestSuite()
  4228. suite.addTest(PyparsingTestInit())
  4229. test_case_classes = ParseTestCase.__subclasses__()
  4230. # put classes in order as they are listed in the source code
  4231. test_case_classes.sort(key=lambda cls: inspect.getsourcelines(cls)[1])
  4232. test_case_classes.remove(PyparsingTestInit)
  4233. # test_case_classes.remove(ParseASMLTest)
  4234. test_case_classes.remove(EnablePackratParsing)
  4235. if IRON_PYTHON_ENV:
  4236. test_case_classes.remove(OriginalTextForTest)
  4237. suite.addTests(T() for T in test_case_classes)
  4238. if TEST_USING_PACKRAT:
  4239. # retest using packrat parsing (disable those tests that aren't compatible)
  4240. suite.addTest( EnablePackratParsing() )
  4241. unpackrattables = [ PyparsingTestInit, EnablePackratParsing, RepeaterTest, ]
  4242. # add tests to test suite a second time, to run with packrat parsing
  4243. # (leaving out those that we know wont work with packrat)
  4244. packratTests = [t.__class__() for t in suite._tests
  4245. if t.__class__ not in unpackrattables]
  4246. suite.addTests( packratTests )
  4247. return suite
  4248. def makeTestSuiteTemp(classes):
  4249. suite = TestSuite()
  4250. suite.addTest(PyparsingTestInit())
  4251. suite.addTests(cls() for cls in classes)
  4252. return suite
  4253. # runnable from setup.py using "python setup.py test -s unitTests.suite"
  4254. suite = makeTestSuite()
  4255. if __name__ == '__main__':
  4256. # run specific tests by including them in this list, otherwise
  4257. # all tests will be run
  4258. testclasses = [
  4259. ]
  4260. if not testclasses:
  4261. testRunner = TextTestRunner()
  4262. result = testRunner.run(suite)
  4263. else:
  4264. # disable chaser '.' display
  4265. testRunner = TextTestRunner(verbosity=0)
  4266. BUFFER_OUTPUT = False
  4267. result = testRunner.run(makeTestSuiteTemp(testclasses))
  4268. sys.stdout.flush()
  4269. exit(0 if result.wasSuccessful() else 1)