PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /opt/gsutil/third_party/pyparsing/examples
Viewing File: /opt/gsutil/third_party/pyparsing/examples/verilog_parse.py
# # verilogParse.py # # an example of using the pyparsing module to be able to process Verilog files # uses BNF defined at http://www.verilog.com/VerilogBNF.html # # Copyright (c) 2004-2011 Paul T. McGuire. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # If you find this software to be useful, please make a donation to one # of the following charities: # - the Red Cross (https://www.redcross.org/) # - Hospice Austin (https://www.hospiceaustin.org/) # # DISCLAIMER: # THIS SOFTWARE IS PROVIDED BY PAUL T. McGUIRE ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL PAUL T. McGUIRE OR CO-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OFUSE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # For questions or inquiries regarding this license, or commercial use of # this software, contact the author via e-mail: ptmcg@users.sourceforge.net # # Todo: # - add pre-process pass to implement compilerDirectives (ifdef, include, etc.) # # Revision History: # # 1.0 - Initial release # 1.0.1 - Fixed grammar errors: # . real declaration was incorrect # . tolerant of '=>' for '*>' operator # . tolerant of '?' as hex character # . proper handling of mintypmax_expr within path delays # 1.0.2 - Performance tuning (requires pyparsing 1.3) # 1.0.3 - Performance updates, using Regex (requires pyparsing 1.4) # 1.0.4 - Performance updates, enable packrat parsing (requires pyparsing 1.4.2) # 1.0.5 - Converted keyword Literals to Keywords, added more use of Group to # group parsed results tokens # 1.0.6 - Added support for module header with no ports list (thanks, Thomas Dejanovic!) # 1.0.7 - Fixed erroneous '<<' Forward definition in timCheckCond, omitting ()'s # 1.0.8 - Re-released under MIT license # 1.0.9 - Enhanced udpInstance to handle identifiers with leading '\' and subscripting # 1.0.10 - Fixed change added in 1.0.9 to work for all identifiers, not just those used # for udpInstance. # 1.0.11 - Fixed bug in inst_args, content alternatives were reversed # 1.1.0 - Some performance fixes, convert most literal strs to Keywords # from pathlib import Path import pprint import time __version__ = "1.1.0" __all__ = ["__version__", "verilogbnf"] from pyparsing import ( Literal, Keyword, Word, Forward, DelimitedList, Group, Optional, Combine, alphas, nums, restOfLine, alphanums, dbl_quoted_string, empty, ParseException, one_of, StringEnd, FollowedBy, ParserElement, Regex, cppStyleComment, ) import pyparsing usePackrat = True packratOn = False if usePackrat: try: ParserElement.enable_packrat() except Exception: pass else: packratOn = True verilogbnf = None def make_verilog_bnf(): global verilogbnf if verilogbnf is None: # compiler directives compilerDirective = Combine( "`" + one_of( "define undef ifdef else endif default_nettype" " include resetall timescale unconnected_drive" " nounconnected_drive celldefine endcelldefine", as_keyword=True, ) + restOfLine ).set_name("compilerDirective") # primitives ( SEMI, COLON, LPAR, RPAR, LBRACE, RBRACE, LBRACK, RBRACK, DOT, COMMA, EQ, ) = Literal.using_each(";:(){}[].,=") identLead = alphas + "$_" identBody = alphanums + "$_" identifier1 = Regex( rf"\.?[{identLead}][{identBody}]*(\.[{identLead}][{identBody}]*)*" ).set_name("baseIdent") identifier2 = ( Regex(r"\\\S+").setParseAction(lambda t: t[0][1:]).set_name("escapedIdent") ) # .setDebug() identifier = identifier1 | identifier2 assert identifier2 == r"\abc" hexnums = nums + "abcdefABCDEF" + "_?" base = Regex("'[bBoOdDhH]").set_name("base") basedNumber = Combine( (Word(nums + "_") | "") + base + Word(hexnums + "xXzZ"), joinString=" ", adjacent=False, ).set_name("basedNumber") # number = ( basedNumber | Combine( Word( "+-"+spacedNums, spacedNums ) + # Optional( DOT + Optional( Word( spacedNums ) ) ) + # Optional( e + Word( "+-"+spacedNums, spacedNums ) ) ).set_name("numeric") ) number = ( basedNumber | Regex(r"[+-]?[0-9_]+(\.[0-9_]*)?([Ee][+-]?[0-9_]+)?") ).set_name("numeric") expr = Forward().set_name("expr") concat = Group(LBRACE + DelimitedList(expr) + RBRACE) multiConcat = Group("{" + expr + concat + "}").set_name("multiConcat") funcCall = Group( identifier + LPAR + (DelimitedList(expr) | "") + RPAR ).set_name("funcCall") subscrRef = Group(LBRACK + DelimitedList(expr, COLON) + RBRACK) subscrIdentifier = Group(identifier + (subscrRef | "")) # scalarConst = "0" | (( FollowedBy('1') + one_of("1'b0 1'b1 1'bx 1'bX 1'B0 1'B1 1'Bx 1'BX 1") )) scalarConst = Regex("0|1('[Bb][01xX])?") mintypmaxExpr = Group(expr + COLON + expr + COLON + expr).set_name("mintypmax") primary = ( number | (LPAR + mintypmaxExpr + RPAR) | (LPAR + Group(expr) + RPAR).set_name("nestedExpr") | multiConcat | concat | dbl_quoted_string | funcCall | subscrIdentifier ) unop = one_of("+ - ! ~ & ~& | ^| ^ ~^").set_name("unop") binop = one_of( "+ - * / % == != === !== && " "|| < <= > >= & | ^ ^~ >> << ** <<< >>>" ).set_name("binop") expr <<= ( (unop + expr) | (primary + "?" + expr + COLON + expr) # must be first! | (primary + ((binop + expr) | "")) ) lvalue = subscrIdentifier | concat # keywords reg = Keyword("reg") trireg = Keyword("trireg") signed = Keyword("signed") parameter = Keyword("parameter") input_, output, inout = Keyword.using_each("input output inout".split()) time = Keyword("time") integer = Keyword("integer") real = Keyword("real") event = Keyword("event") scalared = Keyword("scalared") vectored = Keyword("vectored") if_ = Keyword("if") else_ = Keyword("else") always = Keyword("always") initial = Keyword("initial") small, medium, large = Keyword.using_each("small medium large".split()) edge = Keyword("edge") posedge = Keyword("posedge") negedge = Keyword("negedge") specify, endspecify = Keyword.using_each("specify endspecify".split()) primitive, endprimitive = Keyword.using_each("primitive endprimitive".split()) fork = Keyword("fork") join = Keyword("join") begin = Keyword("begin") end = Keyword("end") default = Keyword("default") forever = Keyword("forever") repeat = Keyword("repeat") while_ = Keyword("while") for_ = Keyword("for") case = one_of("case casez casex", as_keyword=True) endcase = Keyword("endcase") wait = Keyword("wait") disable = Keyword("disable") deassign = Keyword("deassign") force = Keyword("force") release = Keyword("release") assign = Keyword("assign") table, endtable = Keyword.using_each("table endtable".split()) function, endfunction = Keyword.using_each("function endfunction".split()) task, endtask = Keyword.using_each("task endtask".split()) module, macromodule, endmodule = Keyword.using_each( "module macromodule endmodule".split() ) eventExpr = Forward() eventTerm = ( (posedge + expr) | (negedge + expr) | expr | (LPAR + eventExpr + RPAR) ) eventExpr <<= Group(DelimitedList(eventTerm, Keyword("or"))) eventControl = Group( "@" + ((LPAR + eventExpr + RPAR) | identifier | "*") ).set_name("eventCtrl") delayArg = ( number | Word(alphanums + "$_") | (LPAR + Group(DelimitedList(mintypmaxExpr | expr)) + RPAR) # identifier | ).set_name( "delayArg" ) # .setDebug() delay = Group("#" + delayArg).set_name("delay") # .setDebug() delayOrEventControl = delay | eventControl assgnmt = Group(lvalue + EQ + (delayOrEventControl | "") + expr).set_name( "assgnmt" ) nbAssgnmt = Group( (lvalue + "<=" + (delay | "") + expr) | (lvalue + "<=" + (eventControl | "") + expr) ).set_name("nbassgnmt") range_ = LBRACK + expr + COLON + expr + RBRACK paramAssgnmt = Group(identifier + EQ + expr).set_name("paramAssgnmt") parameterDecl = Group( parameter + (range_ | "") + DelimitedList(paramAssgnmt) + SEMI ).set_name("paramDecl") inputDecl = Group(input_ + (range_ | "") + DelimitedList(identifier) + SEMI) outputDecl = Group(output + (range_ | "") + DelimitedList(identifier) + SEMI) inoutDecl = Group(inout + (range_ | "") + DelimitedList(identifier) + SEMI) regIdentifier = Group(identifier + (LBRACK + expr + COLON + expr + RBRACK | "")) regDecl = Group( reg + (signed | "") + (range_ | "") + DelimitedList(regIdentifier) + SEMI ).set_name("regDecl") timeDecl = Group(time + DelimitedList(regIdentifier) + SEMI) integerDecl = Group(integer + DelimitedList(regIdentifier) + SEMI) strength0 = one_of("supply0 strong0 pull0 weak0 highz0", as_keyword=True) strength1 = one_of("supply1 strong1 pull1 weak1 highz1", as_keyword=True) driveStrength = Group( LPAR + ((strength0 + COMMA + strength1) | (strength1 + COMMA + strength0)) + RPAR ).set_name("driveStrength") nettype = one_of( "wire tri tri1 supply0 wand triand tri0 supply1 wor trior trireg", as_keyword=True, ) expandRange = (scalared | vectored | "") + range_ realDecl = Group(real + DelimitedList(identifier) + SEMI) eventDecl = Group(event + DelimitedList(identifier) + SEMI) blockDecl = ( parameterDecl | regDecl | integerDecl | realDecl | timeDecl | eventDecl ) stmt = Forward().set_name("stmt") # .setDebug() stmtOrNull = stmt | SEMI caseItem = (DelimitedList(expr) + COLON + stmtOrNull) | ( default + Optional(":") + stmtOrNull ) stmt <<= Group( (begin + Group(stmt[...:end]) + end).set_name("begin-end") | ( if_ + Group(LPAR + expr + RPAR) + stmtOrNull + (else_ + stmtOrNull | "") ).set_name("if") | (delayOrEventControl + stmtOrNull) | (case + LPAR + expr + RPAR + caseItem[1, ...] + endcase) | (forever + stmt) | (repeat + LPAR + expr + RPAR + stmt) | (while_ + LPAR + expr + RPAR + stmt) | ( for_ + LPAR + assgnmt + SEMI + Group(expr) + SEMI + assgnmt + RPAR + stmt ) | (fork + stmt[...] + join) | (fork + COLON + identifier + blockDecl[...] + stmt[...] + end) | (wait + LPAR + expr + RPAR + stmtOrNull) | ("->" + identifier + SEMI) | (disable + identifier + SEMI) | (assign + assgnmt + SEMI) | (deassign + lvalue + SEMI) | (force + assgnmt + SEMI) | (release + lvalue + SEMI) | (begin + COLON + identifier + blockDecl[...] + stmt[...] + end).set_name( "begin:label-end" ) | # these *have* to go at the end of the list!!! (assgnmt + SEMI) | (nbAssgnmt + SEMI) | ( Combine(Optional("$") + identifier) + (LPAR + DelimitedList(expr | empty) + RPAR | "") + SEMI ) ).set_name("stmtBody") """ x::=<blocking_assignment> ; x||= <non_blocking_assignment> ; x||= if ( <expression> ) <statement_or_null> x||= if ( <expression> ) <statement_or_null> else <statement_or_null> x||= case ( <expression> ) <case_item>+ endcase x||= casez ( <expression> ) <case_item>+ endcase x||= casex ( <expression> ) <case_item>+ endcase x||= forever <statement> x||= repeat ( <expression> ) <statement> x||= while ( <expression> ) <statement> x||= for ( <assignment> ; <expression> ; <assignment> ) <statement> x||= <delay_or_event_control> <statement_or_null> x||= wait ( <expression> ) <statement_or_null> x||= -> <name_of_event> ; x||= <seq_block> x||= <par_block> x||= <task_enable> x||= <system_task_enable> x||= disable <name_of_task> ; x||= disable <name_of_block> ; x||= assign <assignment> ; x||= deassign <lvalue> ; x||= force <assignment> ; x||= release <lvalue> ; """ alwaysStmt = Group(always + (eventControl | "") + stmt).set_name("alwaysStmt") initialStmt = Group(initial + stmt).set_name("initialStmt") chargeStrength = Group(LPAR + (small | medium | large) + RPAR).set_name( "chargeStrength" ) continuousAssign = Group( assign + (driveStrength | "") + (delay | "") + DelimitedList(assgnmt) + SEMI ).set_name("continuousAssign") tfDecl = ( parameterDecl | inputDecl | outputDecl | inoutDecl | regDecl | timeDecl | integerDecl | realDecl ) functionDecl = Group( function + (range_ | "integer" | "real" | "") + identifier + SEMI + Group(tfDecl[1, ...]) + Group(stmt[...]) + endfunction ) inputOutput = input_ | output netDecl1Arg = ( nettype + (expandRange | "") + (delay | "") + Group(DelimitedList(~inputOutput + identifier)) ) netDecl2Arg = ( trireg + (chargeStrength | "") + (expandRange | "") + (delay | "") + Group(DelimitedList(~inputOutput + identifier)) ) netDecl3Arg = ( nettype + (driveStrength | "") + (expandRange | "") + (delay | "") + Group(DelimitedList(assgnmt)) ) netDecl1 = Group(netDecl1Arg + SEMI).set_name("netDecl1") netDecl2 = Group(netDecl2Arg + SEMI).set_name("netDecl2") netDecl3 = Group(netDecl3Arg + SEMI).set_name("netDecl3") gateType = one_of( "and nand or nor xor xnor buf bufif0 bufif1 " "not notif0 notif1 pulldown pullup nmos rnmos " "pmos rpmos cmos rcmos tran rtran tranif0 " "rtranif0 tranif1 rtranif1", as_keyword=True, ) gateInstance = ( (Group(identifier + (range_ | "")) | "") + LPAR + Group(DelimitedList(expr)) + RPAR ) gateDecl = Group( gateType + (driveStrength | "") + (delay | "") + DelimitedList(gateInstance) + SEMI ) udpInstance = Group( Group(identifier + (range_ | subscrRef | "")) + LPAR + Group(DelimitedList(expr)) + RPAR ) udpInstantiation = Group( identifier - (driveStrength | "") + (delay | "") + DelimitedList(udpInstance) + SEMI ).set_name("udpInstantiation") parameterValueAssignment = Group( Literal("#") + LPAR + Group(DelimitedList(expr)) + RPAR ) namedPortConnection = Group(DOT + identifier + LPAR + expr + RPAR).set_name( "namedPortConnection" ) # .setDebug() # assert r".\abc (abc )" == namedPortConnection modulePortConnection = expr | empty inst_args = Group( LPAR + (DelimitedList(namedPortConnection) | DelimitedList(modulePortConnection)) + RPAR ).set_name("inst_args") moduleInstance = Group(Group(identifier + (range_ | "")) + inst_args).set_name( "moduleInstance" ) # .setDebug() moduleInstantiation = Group( identifier + (parameterValueAssignment | "") + DelimitedList(moduleInstance).set_name("moduleInstanceList") + SEMI ).set_name("moduleInstantiation") parameterOverride = Group("defparam" + DelimitedList(paramAssgnmt) + SEMI) task = Group(task + identifier + SEMI + tfDecl[...] + stmtOrNull + endtask) specparamDecl = Group("specparam" + DelimitedList(paramAssgnmt) + SEMI) pathDescr1 = Group(LPAR + subscrIdentifier + "=>" + subscrIdentifier + RPAR) pathDescr2 = Group( LPAR + Group(DelimitedList(subscrIdentifier)) + "*>" + Group(DelimitedList(subscrIdentifier)) + RPAR ) pathDescr3 = Group( LPAR + Group(DelimitedList(subscrIdentifier)) + "=>" + Group(DelimitedList(subscrIdentifier)) + RPAR ) pathDelayValue = Group( (LPAR + Group(DelimitedList(mintypmaxExpr | expr)) + RPAR) | mintypmaxExpr | expr ) pathDecl = Group( (pathDescr1 | pathDescr2 | pathDescr3) + EQ + pathDelayValue + SEMI ).set_name("pathDecl") portConditionExpr = Forward() portConditionTerm = (unop | "") + subscrIdentifier portConditionExpr <<= portConditionTerm + (binop + portConditionExpr | "") polarityOp = one_of("+ -") levelSensitivePathDecl1 = Group( if_ + Group(LPAR + portConditionExpr + RPAR) + subscrIdentifier + (polarityOp | "") + "=>" + subscrIdentifier + EQ + pathDelayValue + SEMI ) levelSensitivePathDecl2 = Group( if_ + Group(LPAR + portConditionExpr + RPAR) + LPAR + Group(DelimitedList(subscrIdentifier)) + (polarityOp | "") + "*>" + Group(DelimitedList(subscrIdentifier)) + RPAR + EQ + pathDelayValue + SEMI ) levelSensitivePathDecl = levelSensitivePathDecl1 | levelSensitivePathDecl2 edgeIdentifier = posedge | negedge edgeSensitivePathDecl1 = Group( (if_ + Group(LPAR + expr + RPAR) | "") + LPAR + (edgeIdentifier | "") + subscrIdentifier + "=>" + LPAR + subscrIdentifier + (polarityOp | "") + COLON + expr + RPAR + RPAR + EQ + pathDelayValue + SEMI ) edgeSensitivePathDecl2 = Group( (if_ + Group(LPAR + expr + RPAR) | "") + LPAR + (edgeIdentifier | "") + subscrIdentifier + "*>" + LPAR + DelimitedList(subscrIdentifier) + (polarityOp | "") + COLON + expr + RPAR + RPAR + EQ + pathDelayValue + SEMI ) edgeSensitivePathDecl = edgeSensitivePathDecl1 | edgeSensitivePathDecl2 edgeDescr = one_of("01 10 0x x1 1x x0").set_name("edgeDescr") timCheckEventControl = Group( posedge | negedge | (edge + LBRACK + DelimitedList(edgeDescr) + RBRACK) ) timCheckCond = Forward() timCondBinop = one_of("== === != !==") timCheckCondTerm = (expr + timCondBinop + scalarConst) | (Optional("~") + expr) timCheckCond <<= (LPAR + timCheckCond + RPAR) | timCheckCondTerm timCheckEvent = Group( (timCheckEventControl | "") + subscrIdentifier + ("&&&" + timCheckCond | "") ) timCheckLimit = expr controlledTimingCheckEvent = Group( timCheckEventControl + subscrIdentifier + ("&&&" + timCheckCond | "") ) notifyRegister = identifier systemTimingCheck1 = Group( "$setup" + LPAR + timCheckEvent + COMMA + timCheckEvent + COMMA + timCheckLimit + (COMMA + notifyRegister | "") + RPAR + SEMI ) systemTimingCheck2 = Group( "$hold" + LPAR + timCheckEvent + COMMA + timCheckEvent + COMMA + timCheckLimit + (COMMA + notifyRegister | "") + RPAR + SEMI ) systemTimingCheck3 = Group( "$period" + LPAR + controlledTimingCheckEvent + COMMA + timCheckLimit + (COMMA + notifyRegister | "") + RPAR + SEMI ) systemTimingCheck4 = Group( "$width" + LPAR + controlledTimingCheckEvent + COMMA + timCheckLimit + (COMMA + expr + COMMA + notifyRegister | "") + RPAR + SEMI ) systemTimingCheck5 = Group( "$skew" + LPAR + timCheckEvent + COMMA + timCheckEvent + COMMA + timCheckLimit + (COMMA + notifyRegister | "") + RPAR + SEMI ) systemTimingCheck6 = Group( "$recovery" + LPAR + controlledTimingCheckEvent + COMMA + timCheckEvent + COMMA + timCheckLimit + (COMMA + notifyRegister | "") + RPAR + SEMI ) systemTimingCheck7 = Group( "$setuphold" + LPAR + timCheckEvent + COMMA + timCheckEvent + COMMA + timCheckLimit + COMMA + timCheckLimit + (COMMA + notifyRegister | "") + RPAR + SEMI ) systemTimingCheck = ( FollowedBy("$") + ( systemTimingCheck1 | systemTimingCheck2 | systemTimingCheck3 | systemTimingCheck4 | systemTimingCheck5 | systemTimingCheck6 | systemTimingCheck7 ) ).set_name("systemTimingCheck") sdpd = ( if_ + Group(LPAR + expr + RPAR) + (pathDescr1 | pathDescr2) + EQ + pathDelayValue + SEMI ) specifyItem = ( specparamDecl | pathDecl | levelSensitivePathDecl | edgeSensitivePathDecl | systemTimingCheck | sdpd ) """ x::= <specparam_declaration> x||= <path_declaration> x||= <level_sensitive_path_declaration> x||= <edge_sensitive_path_declaration> x||= <system_timing_check> x||= <sdpd> """ specifyBlock = Group( specify + specifyItem[...:endspecify] + endspecify ).set_name("specifyBlock") moduleItem = ( parameterDecl | inputDecl | outputDecl | inoutDecl | regDecl | netDecl3 | netDecl1 | netDecl2 | timeDecl | integerDecl | realDecl | eventDecl | gateDecl | parameterOverride | continuousAssign | specifyBlock | initialStmt | alwaysStmt | task | functionDecl # these have to be at the end - they start with identifiers | moduleInstantiation | udpInstantiation ) """ All possible moduleItems, from Verilog grammar spec x::= <parameter_declaration> x||= <input_declaration> x||= <output_declaration> x||= <inout_declaration> ?||= <net_declaration> (spec does not seem consistent for this item) x||= <reg_declaration> x||= <time_declaration> x||= <integer_declaration> x||= <real_declaration> x||= <event_declaration> x||= <gate_declaration> x||= <UDP_instantiation> x||= <module_instantiation> x||= <parameter_override> x||= <continuous_assign> x||= <specify_block> x||= <initial_statement> x||= <always_statement> x||= <task> x||= <function> """ portRef = subscrIdentifier portExpr = portRef | Group(LBRACE + DelimitedList(portRef) + RBRACE) port = portExpr | Group(DOT + identifier + LPAR + portExpr + RPAR) moduleHdr = Group( (module | macromodule) + identifier + ( LPAR + Group( ( DelimitedList( Group( (input_ | output) + (netDecl1Arg | netDecl2Arg | netDecl3Arg) ) | port ) | "" ) ) + RPAR | "" ) + SEMI ).set_name("moduleHdr") module_expr = Group( moduleHdr + Group(moduleItem[...:endmodule]) + endmodule ).set_name( "module" ) # .setDebug() udpDecl = outputDecl | inputDecl | regDecl # udpInitVal = one_of("1'b0 1'b1 1'bx 1'bX 1'B0 1'B1 1'Bx 1'BX 1 0 x X") udpInitVal = (Regex("1'[bB][01xX]|[01xX]")).set_name("udpInitVal") udpInitialStmt = Group( "initial" + identifier + EQ + udpInitVal + SEMI ).set_name("udpInitialStmt") levelSymbol = one_of("0 1 x X ? b B") levelInputList = Group(levelSymbol[1, ...].set_name("levelInpList")) outputSymbol = one_of("0 1 x X") combEntry = Group(levelInputList + COLON + outputSymbol + SEMI) edgeSymbol = one_of("r R f F p P n N *") edge = Group(LPAR + levelSymbol + levelSymbol + RPAR) | Group(edgeSymbol) edgeInputList = Group(levelSymbol[...] + edge + levelSymbol[...]) inputList = levelInputList | edgeInputList seqEntry = Group( inputList + COLON + levelSymbol + COLON + (outputSymbol | "-") + SEMI ).set_name("seqEntry") udpTableDefn = Group( table + (combEntry | seqEntry)[1, ...] + endtable ).set_name("table") """ <UDP> ::= primitive <name_of_UDP> ( <name_of_variable> <,<name_of_variable>>* ) ; <UDP_declaration>+ <UDP_initial_statement>? <table_definition> endprimitive """ udp = Group( primitive + identifier + LPAR + Group(DelimitedList(identifier)) + RPAR + SEMI + udpDecl[1, ...] + (udpInitialStmt | "") + udpTableDefn + endprimitive ) verilogbnf = (module_expr | udp)[1, ...] + StringEnd() verilogbnf.ignore(cppStyleComment) verilogbnf.ignore(compilerDirective) return verilogbnf def test(strng): tokens = [] try: tokens = make_verilog_bnf().parse_string(strng) except ParseException as err: print(err.explain()) return tokens if __name__ == "__main__": def main(): import sys sys.setrecursionlimit(5000) print(f"Verilog parser test (V {__version__})") print(f" - using pyparsing version {pyparsing.__version__}") print(f" - using Python version {sys.version}") if packratOn: print(" - using packrat parsing") print() import gc failCount = 0 make_verilog_bnf() numlines = 0 fileDir = "verilog" fileDir = "scratch/verilog" # fileDir = "scratch/verilog/new3" fileDir = Path(fileDir) allFiles = [f for f in fileDir.glob("*.v")] pretty = pprint.PrettyPrinter(indent=2) totalTime = 0 for vfile in allFiles: gc.collect() gc.collect() filelines = vfile.read_text().splitlines() print(vfile.name, len(filelines), end=" ") numlines += len(filelines) teststr = "\n".join(filelines) time1 = time.perf_counter() tokens = test(teststr) time2 = time.perf_counter() elapsed = time2 - time1 totalTime += elapsed if len(tokens): print(f"OK {elapsed}") (fileDir / "parseOutput").mkdir(exist_ok=True) outfile = fileDir / "parseOutput" / (vfile.name + ".parsed.txt") outfile.write_text(f"{teststr}\n\n{pretty.pformat(tokens.as_list())}\n") else: print(f"failed {elapsed}") failCount += 1 for i, line in enumerate(filelines, 1): print(f"{i:4d}: {line.rstrip()}") print(f"Total parse time: {totalTime}") print(f"Total source lines: {numlines}") print(f"Average lines/sec: {numlines / (totalTime + 0.05):.1f}") if failCount: print(f"FAIL - {failCount} files failed to parse") else: print("SUCCESS - all files parsed") return 0 main()