12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358 |
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml"><head><script src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/main_003.html"></script>
-
-
- <script src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/analytics.js" async=""></script><script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/tracking.html" charset="utf-8"></script>
- <script type="text/javascript">
- var protocol = window.location.protocol;
- document.write('<script type="text/javascript" src="' + protocol + '//csdnimg.cn/pubfooter/js/repoAddr2.js?v=' + Math.random() + '"></' + 'script>');
- </script><script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/repoAddr2.html"></script>
- <script id="allmobilize" charset="utf-8" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/allmobilize.html"></script>
- <meta http-equiv="Cache-Control" content="no-siteapp"><link rel="alternate" media="handheld" href="#">
- <title>GNU Bison 中文手册 - Naga Bank
- - 博客频道 - CSDN.NET</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta name="description" content="author:skatetime:2011-04-06 对于电子商务网站,我们该如何对数据分析呢?当我们拿到数据的时候该做些什么?要回答这几个问题前,先回答如下问题:1. 数据是给谁看的? 2. 看数据的人,想从数据中得到什么?或者用数据证明什么? ">
- <script src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/jquery.js" type="text/javascript"></script>
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ad.js"></script>
- <!--new top-->
-
- <link rel="stylesheet" href="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/index.css">
- <!--new top-->
- <link rel="Stylesheet" type="text/css" href="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/style.css">
- <link id="RSSLink" title="RSS" type="application/rss+xml" rel="alternate" href="http://blog.csdn.net/sirouni2003/rss/list">
- <link rel="shortcut icon" href="http://c.csdnimg.cn/public/favicon.ico">
- <link type="text/css" rel="stylesheet" href="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/default.css">
-
- <style type="text/css">.MathJax_Hover_Frame {border-radius: .25em; -webkit-border-radius: .25em; -moz-border-radius: .25em; -khtml-border-radius: .25em; box-shadow: 0px 0px 15px #83A; -webkit-box-shadow: 0px 0px 15px #83A; -moz-box-shadow: 0px 0px 15px #83A; -khtml-box-shadow: 0px 0px 15px #83A; border: 1px solid #A6D ! important; display: inline-block; position: absolute}
- .MathJax_Hover_Arrow {position: absolute; width: 15px; height: 11px; cursor: pointer}
- </style><style type="text/css">#MathJax_About {position: fixed; left: 50%; width: auto; text-align: center; border: 3px outset; padding: 1em 2em; background-color: #DDDDDD; color: black; cursor: default; font-family: message-box; font-size: 120%; font-style: normal; text-indent: 0; text-transform: none; line-height: normal; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; z-index: 201; border-radius: 15px; -webkit-border-radius: 15px; -moz-border-radius: 15px; -khtml-border-radius: 15px; box-shadow: 0px 10px 20px #808080; -webkit-box-shadow: 0px 10px 20px #808080; -moz-box-shadow: 0px 10px 20px #808080; -khtml-box-shadow: 0px 10px 20px #808080; filter: progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')}
- .MathJax_Menu {position: absolute; background-color: white; color: black; width: auto; padding: 5px 0px; border: 1px solid #CCCCCC; margin: 0; cursor: default; font: menu; text-align: left; text-indent: 0; text-transform: none; line-height: normal; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; z-index: 201; border-radius: 5px; -webkit-border-radius: 5px; -moz-border-radius: 5px; -khtml-border-radius: 5px; box-shadow: 0px 10px 20px #808080; -webkit-box-shadow: 0px 10px 20px #808080; -moz-box-shadow: 0px 10px 20px #808080; -khtml-box-shadow: 0px 10px 20px #808080; filter: progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')}
- .MathJax_MenuItem {padding: 1px 2em; background: transparent}
- .MathJax_MenuArrow {position: absolute; right: .5em; color: #666666}
- .MathJax_MenuActive .MathJax_MenuArrow {color: white}
- .MathJax_MenuArrow.RTL {left: .5em; right: auto}
- .MathJax_MenuCheck {position: absolute; left: .7em}
- .MathJax_MenuCheck.RTL {right: .7em; left: auto}
- .MathJax_MenuRadioCheck {position: absolute; left: .7em}
- .MathJax_MenuRadioCheck.RTL {right: .7em; left: auto}
- .MathJax_MenuLabel {padding: 1px 2em 3px 1.33em; font-style: italic}
- .MathJax_MenuRule {border-top: 1px solid #DDDDDD; margin: 4px 3px}
- .MathJax_MenuDisabled {color: GrayText}
- .MathJax_MenuActive {background-color: #606872; color: white}
- .MathJax_Menu_Close {position: absolute; width: 31px; height: 31px; top: -15px; left: -15px}
- </style><style type="text/css">#MathJax_Zoom {position: absolute; background-color: #F0F0F0; overflow: auto; display: block; z-index: 301; padding: .5em; border: 1px solid black; margin: 0; font-weight: normal; font-style: normal; text-align: left; text-indent: 0; text-transform: none; line-height: normal; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; box-shadow: 5px 5px 15px #AAAAAA; -webkit-box-shadow: 5px 5px 15px #AAAAAA; -moz-box-shadow: 5px 5px 15px #AAAAAA; -khtml-box-shadow: 5px 5px 15px #AAAAAA; filter: progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')}
- #MathJax_ZoomOverlay {position: absolute; left: 0; top: 0; z-index: 300; display: inline-block; width: 100%; height: 100%; border: 0; padding: 0; margin: 0; background-color: white; opacity: 0; filter: alpha(opacity=0)}
- #MathJax_ZoomFrame {position: relative; display: inline-block; height: 0; width: 0}
- #MathJax_ZoomEventTrap {position: absolute; left: 0; top: 0; z-index: 302; display: inline-block; border: 0; padding: 0; margin: 0; background-color: white; opacity: 0; filter: alpha(opacity=0)}
- </style><style type="text/css">.MathJax_Preview {color: #888}
- #MathJax_Message {position: fixed; left: 1px; bottom: 2px; background-color: #E6E6E6; border: 1px solid #959595; margin: 0px; padding: 2px 8px; z-index: 102; color: black; font-size: 80%; width: auto; white-space: nowrap}
- #MathJax_MSIE_Frame {position: absolute; top: 0; left: 0; width: 0px; z-index: 101; border: 0px; margin: 0px; padding: 0px}
- .MathJax_Error {color: #CC0000; font-style: italic}
- </style><script src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/share.html"></script><script src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/main.html" charset="utf-8" type="text/javascript"></script></head>
- <body><div style="display: none;" id="MathJax_Message"></div>
-
-
- <!--new top-->
- <script id="toolbar-tpl-scriptId" fixed="true" prod="blog" skin="black" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/html.js" type="text/javascript"></script><div class="csdn-toolbar csdn-toolbar-skin-black "> <div class="container row center-block "> <div class="col-md-3 pull-left logo clearfix"><a href="http://www.csdn.net/?ref=toolbar" title="CSDN首页" target="_blank" class="icon"></a><a title="频道首页" href="http://blog.csdn.net/?ref=toolbar_logo" class="img blog-icon"></a></div> <div class="pull-right login-wrap "> <ul class="btns"> <li class="loginlink"><a href="https://passport.csdn.net/account/login?ref=toolbar" target="_top">登录 </a>|<a target="_top" href="http://passport.csdn.net/account/mobileregister?ref=toolbar&action=mobileRegister"> 注册</a></li> <li class="search"> <div class="icon on-search-icon"> <div class="wrap"> <div class="curr-icon-wrap"> <div class="curr-icon"></div> </div> <form action="http://so.csdn.net/search" method="get" target="_blank"> <input value="toolbar" name="ref" accesskey="2" type="hidden"> <div class="border"> <input placeholder="搜索" name="q" accesskey="2" type="text"><span class="icon-enter-sm"></span> </div> </form> </div> </div> </li> <li class="favor"> <div class="icon on-favor-icon"> <div class="wrap"> <div class="curr-icon-wrap"> <div class="curr-icon"></div> </div> <div style="display:none;" class="favor-success"><span class="msg">收藏成功</span> <div class="btns"><span class="btn btn-primary ok">确定</span></div> </div> <div style="display:none;" class="favor-failed"><span class="icon-danger-lg"></span><span class="msg">收藏失败,请重新收藏</span> <div class="btns"><span class="btn btn-primary ok">确定</span></div> </div> <form role="form" class="form-horizontal favor-form"> <div class="form-group"> <div class="clearfix"> <label for="input-title" class="col-sm-2 control-label">标题</label> <div class="col-sm-10"> <input value="GNU Bison 中文手册 - Naga Bank - 博客频道 - CSDN.NET" id="inputTitle" placeholder="" class="title form-control" type="text"> </div> </div> <div class="alert alert-danger"><strong></strong>标题不能为空</div> </div> <div class="form-group"> <label for="input-url" class="col-sm-2 control-label">网址</label> <div class="col-sm-10"> <input value="http://blog.csdn.net/sirouni2003/article/details/400672#SEC115" id="input-url" placeholder="" class="url form-control" type="text"> </div> </div> <div class="form-group"> <label for="input-tag" class="col-sm-2 tag control-label">标签</label> <div class="col-sm-10"> <input id="input-tag" class="form-control tag" type="text"> </div> </div> <div class="form-group"> <label for="input-description" class="description col-sm-2 control-label">摘要</label> <div class="col-sm-10"> <textarea id="input-description" class="form-control description"></textarea> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10 ft"> <div class="col-sm-4 pull-left"> <div class="checkbox"> <label> <input name="share" checked="checked" class="share" type="checkbox">公开 </label> </div> </div> <div class="col-sm-8 pull-right favor-btns"> <button type="button" class="cancel btn btn-default">取消</button> <button type="submit" class="submit btn btn-primary">收藏</button> </div> </div> </div> </form> </div> </div> </li> <li style="display: none;" class="notify"> <div style="display:none" class="number"></div> <div style="display:none" class="icon-hasnotes-sm"></div> <div id="header_notice_num"></div> <div class="icon on-notify-icon"> <div class="wrap"> <div class="curr-icon-wrap"> <div class="curr-icon"></div> </div> <div id="note1" class="csdn_note"> <div class="box"></div> </div> </div> </div> </li> <li class="ugc"> <div class="icon on-ugc-icon"> <div class="wrap clearfix"> <div class="curr-icon-wrap"> <div class="curr-icon"></div> </div> <dl> <dt><a href="http://geek.csdn.net/news/expert?ref=toolbar" target="_blank" class="p-news clearfix" style="display:none;"><em class="icon"></em><span>分享资讯</span></a></dt> <dt><a href="http://u.download.csdn.net/upload?ref=toolbar" target="_blank" class="p-doc clearfix"><em class="icon"></em><span>传PPT/文档</span></a></dt> <dt><a href="http://bbs.csdn.net/topics/new?ref=toolbar" target="_blank" class="p-ask clearfix"><em class="icon"></em><span>提问题</span></a></dt> <dt><a href="http://write.blog.csdn.net/postedit?ref=toolbar" target="_blank" class="p-blog clearfix"><em class="icon"></em><span>写博客</span></a></dt> <dt><a href="http://u.download.csdn.net/upload?ref=toolbar" target="_blank" class="p-src clearfix"><em class="icon"></em><span>传资源</span></a></dt> <dt><a href="https://code.csdn.net/projects/new?ref=toolbar" target="_blank" class="c-obj clearfix"><em class="icon"></em><span>创建项目</span></a></dt> <dt><a href="https://code.csdn.net/snippets/new?ref=toolbar" target="_blank" class="c-code clearfix"><em class="icon"></em><span>创建代码片</span></a></dt> </dl> </div> </div> </li> <li class="profile"> <div class="icon on-profile-icon"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/2_lhh411291769.gif" class="curr-icon-img"> <div class="wrap clearfix"> <div class="curr-icon-wrap"> <div class="curr-icon"></div> </div> <div class="bd"> <dl class="clearfix"> <dt class="pull-left img"><a target="_blank" href="http://my.csdn.net/?ref=toolbar" class="avatar"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/2_lhh411291769.gif"></a></dt> <dd class="info" style="border: none;"><a target="_blank" href="http://my.csdn.net/?ref=toolbar" class="nickname">lhh411291769</a><span class="dec"><a class="fill-dec" href="http://my.csdn.net/" target="_blank">编辑自我介绍,让更多人了解你<span class="write-icon"></span></a></span></dd> </dl> </div> <div class="ft clearfix"><a target="_blank" href="http://my.csdn.net/my/account/changepwd?ref=toolbar" class="pull-left"><span class="icon-cog"></span>帐号设置</a><a href="https://passport.csdn.net/account/logout?ref=toolbar" target="_top" class="pull-left" style="margin-left:132px; width:18px; height:27px; white-space:nowrap; overflow:hidden;"><span class="icon-signout"></span><span class="out">退出</span></a></div> </div> </div> </li> <li class="apps"> <div style="display: none;" id="chasnew123" class="hasnew"></div> <div id="cappsarea123" class="icon on-apps-icon"> <div class="wrap clearfix"> <div class="curr-icon-wrap"> <div class="curr-icon"></div> </div> <div class="detail"> <dl> <dt> <h5>社区</h5> </dt> <dd> <a href="http://blog.csdn.net/?ref=toolbar" target="_blank">博客</a></dd> <dd> <a href="http://bbs.csdn.net/?ref=toolbar" target="_blank">论坛</a></dd> <dd> <a href="http://download.csdn.net/?ref=toolbar" target="_blank">下载</a></dd> <dd><a href="http://ask.csdn.net/?ref=toolbar" target="_blank">技术问答</a></dd> <dd><a href="http://geek.csdn.net/?ref=toolbar" target="_blank">极客头条</a></dd> <dd> <a href="http://hero.csdn.net/?ref=toolbar" target="_blank">英雄会</a></dd> </dl> </div> <div class="detail"> <dl> <dt> <h5>服务</h5> </dt> <dd> <a href="http://job.csdn.net/?ref=toolbar" target="_blank">JOB<img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/new.html" style="display: none; margin-top: -26px; width: 23px;"></a></dd> <dd> <a href="http://edu.csdn.net/?ref=toolbar" target="_blank">学院<img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/new.html" style="display: none; margin-top: -26px; width: 23px;"></a></dd> <dd> <a href="https://code.csdn.net/?ref=toolbar" target="_blank">CODE</a></dd> <dd> <a href="http://huiyi.csdn.net/?ref=toolbar" target="_blank">活动</a></dd> <dd> <a href="http://www.csto.com/?ref=toolbar" target="_blank">CSTO</a></dd> <dd> <a href="http://mall.csdn.net/?ref=toolbar" target="_blank">C币兑换<img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/new.html" style="display: none; margin-top: -26px; width: 23px;"></a></dd> </dl> </div> <div class="detail last"> <dl> <dt> <h5>俱乐部</h5> </dt> <dd> <a href="http://cto.csdn.net/?ref=toolbar" target="_blank">CTO俱乐部</a></dd> <dd> <a href="http://student.csdn.net/?ref=toolbar" target="_blank">高校俱乐部</a></dd> </dl> </div> </div> </div> </li> </ul> </div> </div> </div>
- <!--new top-->
- <div id="container">
- <div id="header">
- <div class="header">
- <div id="blog_title">
- <h2>
- <a href="http://blog.csdn.net/sirouni2003">Naga Bank</a></h2>
- <h3>所有软件都应该是自由软件</h3>
- <div class="clear">
- </div>
- </div>
- <div class="clear">
- </div>
- </div>
- </div>
- <div id="navigator">
- <div class="navigator_bg">
- </div>
- <div class="navigator">
- <ul>
-
- <li id="btnContents"><a href="http://blog.csdn.net/sirouni2003?viewmode=contents"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_mulu'])">
- <img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ico_list.gif">目录视图</span></a></li>
- <li id="btnView"><a href="http://blog.csdn.net/sirouni2003?viewmode=list"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_zhaiyao'])">
- <img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ico_summary.gif">摘要视图</span></a></li>
- <li id="btnRss"><a href="http://blog.csdn.net/sirouni2003/rss/list"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_RSS'])">
- <img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ico_rss.gif">订阅</span></a></li>
- </ul>
- </div>
- </div>
- <script type="text/javascript">
- var username = "sirouni2003";
- var _blogger = username;
- var blog_address = "http://blog.csdn.net/sirouni2003";
- var static_host = "http://static.blog.csdn.net";
- var currentUserName = "lhh411291769";
- </script>
- <div id="body">
- <div id="main">
- <div class="main">
- <div class="ad_class">
- <div class="notice tracking-ad" data-mod="popu_3">
- <a href="http://blog.csdn.net/blogdevteam/article/details/48287419">
- <font color="blue">有奖征文:那些年我们一起写过的代码
- </font></a>
-
- <a href="http://blog.csdn.net/blogdevteam/article/details/48436599"><font color="red">博乐8月贡献榜</font></a>
-
-
- <a href="http://www.csdn.net/app/">
- <font color="blue">CSDN 移动客户端正式上线
- </font></a>
-
- <a href="http://bss.csdn.net/m/topic/learning_path_weixin">
- <font color="red">微信开发学习路线高级篇上线
- </font></a>
-
- </div> </div>
-
-
- <link href="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/comment1.css" type="text/css" rel="stylesheet">
- <link href="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/style1.css" type="text/css" rel="stylesheet">
- <script language="JavaScript" type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/jquery_002.js"></script>
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/main_002.html"></script>
- <link rel="stylesheet" href="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/markdown_views.css">
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/MathJax.js"></script>
- <script type="text/ecmascript">
- window.quickReplyflag = true;
-
- var isBole = false;
-
-
- </script>
- <div id="article_details" class="details">
- <div class="article_title">
- <span class="ico ico_type_Original"></span>
- <h1>
- <span class="link_title"><a href="http://blog.csdn.net/sirouni2003/article/details/400672">
- GNU Bison 中文手册
- </a></span>
- </h1>
- </div>
-
- <div class="article_manage">
- <span class="link_categories">
- 分类:
- <a href="http://blog.csdn.net/sirouni2003/article/category/129669" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_fenlei']);">Open Source</a>
- </span>
- <span class="link_postdate">2005-06-22 22:31</span>
- <span class="link_view" title="阅读次数">35152人阅读</span>
- <span class="link_comments" title="评论次数"><a href="#comments" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">评论</a>(14)</span>
- <span class="link_collect"><a href="javascript:void(0);" onclick="javascript:collectArticle('GNU Bison 中文手册','400672');return false;" title="收藏">收藏</a></span>
- <span class="link_report"><a href="#report" onclick="javascript:report(400672,2);return false;" title="举报">举报</a></span>
-
- </div>
- <div class="tag2box"><a href="http://www.csdn.net/tag/%e8%af%ad%e8%a8%80" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">语言</a><a href="http://www.csdn.net/tag/token" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">token</a><a href="http://www.csdn.net/tag/parsing" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">parsing</a><a href="http://www.csdn.net/tag/semantic" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">semantic</a><a href="http://www.csdn.net/tag/yacc" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">yacc</a><a href="http://www.csdn.net/tag/conflict" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">conflict</a></div>
-
-
-
-
- <div style="clear:both"></div><div style="border:solid 1px #ccc; background:#eee; float:left; min-width:200px;padding:4px 10px;"><p style="text-align:right;margin:0;"><span style="float:left;">目录<a href="#" title="系统根据文章中H1到H6标签自动生成文章目录">(?)</a></span><a href="#" onclick="javascript:return openct(this);" title="展开">[+]</a></p><ol style="display:none;margin-left:14px;padding-left:14px;line-height:160%;"><li><a href="#t0">GNU Bison 中文手册翻译完成</a></li><li><a href="#t1">Bison</a></li><li><a href="#t2"> Bison简介-Introduction </a></li><li><a href="#t3"> 使用Bison的条件-Conditions for Using Bison </a></li><li><a href="#t4"> GNU GENERAL PUBLIC LICENSE </a></li><ol><li><a href="#t5"> Preamble </a></li><li><a href="#t6"> Appendix How to Apply These Terms to Your New Programs </a></li></ol><li><a href="#t7"> 1 和Bison相关的一些基本概念-The Concepts of Bison </a></li><ol><li><a href="#t8"> 11 语言与上下文无关文法-Languages and Context-Free Grammars </a></li><li><a href="#t9"> 12 从正规文法转换到Bison的输入-From Formal Rules to Bison Input </a></li><li><a href="#t10"> 13 语义值-Semantic Values </a></li><li><a href="#t11"> 14 语义动作 </a></li><li><a href="#t12"> 15 编写GLR分析器-Writing GLR Parsers </a></li><ol><li><a href="#t13"> 151 使用GLR分析器分析非歧义文法 </a></li><li><a href="#t14"> 152 使用GLR解决歧义-Using GLR to Resolve Ambiguities </a></li><li><a href="#t15"> 153 编译GLR分析器时需要考虑的问题-Considerations when Compiling GLR Parsers </a></li></ol><li><a href="#t16"> 16 位置-Locations </a></li><li><a href="#t17"> 17 Bison的输出分析器文件-Bison Output the Parser File </a></li><li><a href="#t18"> 18 使用Bison的流程-Stages in Using Bison </a></li><li><a href="#t19"> 19 Bison语法文件的整体布局-The Overall Layout of a Bison Grammar </a></li></ol><li><a href="#t20"> 2 实例-Examples </a></li><ol><li><a href="#t21"> 21 逆波兰记号计算器-Reverse Polish Notation Calculator </a></li><ol><li><a href="#t22"> 211 rpclac的声明部分-Declarations for rpcalc </a></li><li><a href="#t23"> 212 rpcalc的语法规则-Grammar Rules for rpcalc </a></li><ol><li><a href="#t24"> 2121 解释input-Explanation of input </a></li><li><a href="#t25"> 2122 解释line-Explanation of line </a></li><li><a href="#t26"> 2123 解释expr-Explanation of expr </a></li></ol><li><a href="#t27"> 213 rpcalc的词法分析器-The rpcalc Lexical Analyzer </a></li><li><a href="#t28"> 214 控制函数-The Controlling Function </a></li><li><a href="#t29"> 215 错误报告的规则-The Error Reporting Routine </a></li><li><a href="#t30"> 216 运行Bison来产生分析器-Running Bison to Make the Parser </a></li><li><a href="#t31"> 217 编译分析器文件-Compiling the Parser File </a></li></ol><li><a href="#t32"> 22 中缀符号计算器calc-Infix Notation Calculator calc </a></li><li><a href="#t33"> 23 简单的错误恢复-Simple Error Recovery </a></li><li><a href="#t34"> 24 带有位置追踪的计算器ltcalc-Location Tracking Calculator ltcalc </a></li><ol><li><a href="#t35"> 241 ltcalc的Declarations-Declarations for ltcalc </a></li><li><a href="#t36"> 242 ltcalc的语法规则-Grammar Rules for ltcalc </a></li><li><a href="#t37"> 243 ltcalc的词法分析器-The ltcalc Lexical Analyzer </a></li></ol><li><a href="#t38"> 25 多功能计算器mfcalc-Multi-Function Calculator mfcalc </a></li><ol><li><a href="#t39"> 251 mfcalc的声明-Declarations for mfcalc </a></li><li><a href="#t40"> 252 mfcalc的语法规则-Grammar Rules for mfcalc </a></li><li><a href="#t41"> 253 mfcalc的符号表-The mfcalc Symbol Table </a></li></ol><li><a href="#t42"> 26 练习-Exercises </a></li></ol><li><a href="#t43"> 3 Biosn的语法文件-Bison Grammar Files </a></li><ol><li><a href="#t44"> 31 Bison语法的提纲-Outline of a Bison Grammar </a></li><ol><li><a href="#t45"> 311 Prologue部分-The prologue </a></li><li><a href="#t46"> 312 Bison Declarations部分-The Bison Declarations Section </a></li><li><a href="#t47"> 313 语法规则部分-The Grammar Rules Section </a></li><li><a href="#t48"> 314 Epilogue部分-The epilogue </a></li></ol><li><a href="#t49"> 32 符号终结符和非终结符-Symbols Terminal and Nonterminal </a></li><li><a href="#t50"> 33 描述语法规则的语法-Syntax of Grammar Rules </a></li><li><a href="#t51"> 34 递归规则-Recursive Rules </a></li><li><a href="#t52"> 35 定义语言的语义-Defining Language Semantics </a></li><ol><li><a href="#t53"> 351 语义值的数据类型-Data Types of Semantic Values </a></li><li><a href="#t54"> 352 多种值类型-More Than One Value Type </a></li><li><a href="#t55"> 353 动作-Actions </a></li><li><a href="#t56"> 354 动作中值的数据类型-Data Types of Values in Actions </a></li><li><a href="#t57"> 355 规则中的动作-Actions in Mid-Rule </a></li></ol><li><a href="#t58"> 36 追踪位置-Tracking Locations </a></li><ol><li><a href="#t59"> 361 位置的数据类型-Data Type of Locations </a></li><li><a href="#t60"> 362 动作和位置-Actions and Locations </a></li><li><a href="#t61"> 363 位置的默认动作-Default Action for Locations </a></li></ol><li><a href="#t62"> 37 Bison声明-Bison Declarations </a></li><ol><li><a href="#t63"> 371 符号类型名称-Token Type Names </a></li><li><a href="#t64"> 372 操作符优先级-Operator Precedence </a></li><li><a href="#t65"> 373 值类型集-The Collection of Value Types </a></li><li><a href="#t66"> 374 非终结符-Nonterminal Symbols </a></li><li><a href="#t67"> 375 在分析执行前执行一些动作-Performing Actions before Parsing </a></li><li><a href="#t68"> 376 释放被丢弃的符号-Freeing Discarded Symbols </a></li><li><a href="#t69"> 377 消除冲突警告-Suppressing Conflict Warnings </a></li><li><a href="#t70"> 378 开始符号-The Start-Symbol </a></li><li><a href="#t71"> 379 纯可重入分析器-A Pure Reentrant Parser </a></li><li><a href="#t72"> 3710 Bison声明总结-Bison Declaration Summary </a></li></ol><li><a href="#t73"> 38 在同一个程序中使用多个分析器-Multiple Parsers in the Same Program </a></li></ol><li><a href="#t74"> 4 分析器C语言接口-Parser C-Language Interface </a></li><ol><li><a href="#t75"> 41 分析器函数yyparse-The Parser Function yyparse </a></li><li><a href="#t76"> 42 词法分析器函数yylex-The Lexical Analyzer Function yylex </a></li><ol><li><a href="#t77"> 421 yylex的调用惯例-Calling Convention for yylex </a></li><li><a href="#t78"> 422 记号的语义值-Semantic Values of Tokens </a></li><li><a href="#t79"> 423 记号的文字位置-Textual Locations of Tokens </a></li><li><a href="#t80"> 424 纯分析器的调用惯例-Conventions for Pure Parsers </a></li></ol><li><a href="#t81"> 43 错误报告函数yyerror-The Error Reporting Function yyerror </a></li><li><a href="#t82"> 44 在动作中使用的特殊特征-Special Features for Use in Actions </a></li></ol><li><a href="#t83"> 5 Bison分析器算法-The Bison Parser Algorithm </a></li><ol><li><a href="#t84"> 51 超前扫描记号-Look-Ahead Tokens </a></li><li><a href="#t85"> 52 移进归约冲突-ShiftReduce Conflicts </a></li><li><a href="#t86"> 53 操作符优先级-Operator Precedence </a></li><ol><li><a href="#t87"> 531 什么时候需要优先级-When Precedence is Needed </a></li><li><a href="#t88"> 532 指定操作符的优先级-Specifying Operator Precedence </a></li><li><a href="#t89"> 533 优先级使用的例子-Precedence Examples </a></li><li><a href="#t90"> 534 优先级如何工作-How Precedence Works </a></li></ol><li><a href="#t91"> 54 上下文依赖优先级-Context-Dependent Precedence </a></li><li><a href="#t92"> 55 分析器状态-Parser States </a></li><li><a href="#t93"> 56 归约归约冲突-ReduceReduce Conflicts </a></li><li><a href="#t94"> 57 神秘的归约归约冲突-Mysterious ReduceReduce Conflicts </a></li><li><a href="#t95"> 58 通用LR GLR分析-Generalized LR GLR Parsing </a></li><li><a href="#t96"> 59 栈溢出以及如何避免它-Stack Overflow and How to Avoid It </a></li></ol><li><a href="#t97"> 6 错误恢复-Error Recovery </a></li><li><a href="#t98"> 7 处理上下文依赖-Handling Context Dependencies </a></li><ol><li><a href="#t99"> 71 符号类型中的语义信息-Semantic Info in Token Types </a></li><li><a href="#t100"> 72 词法关联-Lexical Tie-ins </a></li><li><a href="#t101"> 73 词法关联和错误恢复-Lexical Tie-ins and Error Recovery </a></li></ol><li><a href="#t102"> 8 调式你的分析器-Debugging Your Parser </a></li><ol><li><a href="#t103"> 81 理解你的分析器-Understanding Your Parser </a></li><li><a href="#t104"> 82 跟踪你的分析器-Tracing Your Parser </a></li></ol><li><a href="#t105"> 9 调用Bison-Invoking Bison </a></li><ol><li><a href="#t106"> 91 Bison选项-Bison Options </a></li><li><a href="#t107"> 92 选项交叉键-Option Cross Key </a></li><li><a href="#t108"> 93 Yacc库-Yacc Library </a></li></ol><li><a href="#t109"> 10 常见问题-Frequently Asked Questions </a></li><ol><li><a href="#t110"> 101 分析器栈溢出-Parser Stack Overflow </a></li><li><a href="#t111"> 102 我如何复位分析器-How Can I Reset the Parser </a></li><li><a href="#t112"> 103 被销毁的字符串-Strings are Destroyed </a></li><li><a href="#t113"> 104 C分析器-C Parsers </a></li><li><a href="#t114"> 105 实现跳转循环-Implementing GotosLoops </a></li></ol><li><a href="#t115"> A Bison符号-Bison Symbols </a></li><li><a href="#t116"> B 词汇表-Glossary </a></li><li><a href="#t117"> C 复制这个手册-Copying This Manual </a></li><ol><li><a href="#t118"> C1 GNU Free Documentation License </a></li><ol><li><a href="#t119"> C11 ADDENDUM How to use this License for your documents </a></li></ol></ol><li><a href="#t120"> 索引-Index </a></li><li><a href="#t121">目录</a></li><li><a href="#t122">关于这个文档</a></li></ol></div><div style="clear:both"></div><div id="article_content" class="article_content">
- <h3><a name="t0"></a>20050620 GNU Bison 中文手册翻译完成</h3><p>GNU Bison实际上是使用最广泛的Yacc-like分析器生成器,使用它可以生成解释器,编译器,协议实现等多种程序. 它不但与Yacc兼容还具有许多Yacc不具备的特性.</p><p>这个手册编写十分完整,带你领略Bison在使用中的各个细节(注:并不是实现细节).</p><p>如果发现错误,语句不通顺,意思不明,确请立即发邮件把您的建议或者您认为正确的翻译 <a href="mailto:sirouni@yahoo.com.cn">写信告诉我</a>,非常需要并感谢你的帮助! </p><p><a href="http://www.gnu.org/software/bison/manual/">英文原件页面</a></p><p>这个翻译版手册也是在<a href="http://www.gnu.org/copyleft/fdl.html">GNU Free Documentation License</a>下发布.</p><p>提供以下格式:(会陆续增加格式)</p><ul><li><a href="http://crspo.myrice.com/bison-c/bison-c.texinfo.tar.gz">原始texinfo格式(78,999字节,gzip压缩)</a> </li><li><a href="http://crspo.myrice.com/bison-c/bison-c.tar.gz">HTML格式(111,882字节,gzip压缩)</a> </li><li><a href="http://crspo.myrice.com/bison-c/bison-c.zip">HTML格式(109,570字节,zip压缩)</a> </li></ul><p>HTML格式使用一个由我patch的texi2html生成,如果需要的话可以跟我联系.</p><p>一些参考:</p><ul><li><a href="http://www.gnu.org/software/bison/bison.html">GNU Bison Project</a> </li><li><a href="http://dinosaur.compilertools.net/">The LEX & YACC Page</a> </li><li><a href="http://www.gnu.org/software/flex/">GNU Flex Project</a> </li><li><a href="http://mhss.nease.net/unix/yacc.html">Yacc: 另一个编译器的编译器</a>Stephen C. Johnson著,寒蝉退 士译</li></ul>
- <hr>
- <a name="Top"></a>
- <a name="SEC_Top"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="settitle"><a name="t1"></a>Bison</h1>
- <p>这个手册是针对<acronym>GNU</acronym> Bison (版本2.0,22 December 2004),
- <acronym>GNU</acronym>分析器生成器.
- </p>
- <p>Copyright © 1988, 1989, 1990, 1991, 1992, 1993, 1995, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
- </p>
- <p>Chinese(zh_CN) translation:Xiao Wang
- </p>
- <blockquote><p>Permission is granted to copy, distribute and/or modify this document
- under the terms of the <acronym>GNU</acronym> Free Documentation License,
- Version 1.1 or any later version published by the Free Software
- Foundation; with no Invariant Sections, with the Front-Cover texts
- being "A <acronym>GNU</acronym> Manual," and with the Back-Cover Texts as in
- (a) below. A copy of the license is included in the section entitled
- "<acronym>GNU</acronym> Free Documentation License."
- </p>
- <p>(a) The <acronym>FSF</acronym>'s Back-Cover Text is: "You have freedom to copy
- and modify this <acronym>GNU</acronym> Manual, like <acronym>GNU</acronym> software.
- Copies published by the Free Software Foundation raise funds for
- <acronym>GNU</acronym> development."
- </p></blockquote>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC1">Bison简介-Introduction</a></td><td> </td><td align="left" valign="top">
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC2">使用Bison的条件-Conditions for Using Bison</a></td><td> </td><td align="left" valign="top">
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC3">GNU GENERAL PUBLIC LICENSE</a></td><td> </td><td align="left" valign="top"> <acronym>GNU</acronym> General Public License
- 说明了你如何使用和共享Bison
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">教学章节:
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC6">1. 和Bison相关的一些基本概念-The Concepts of Bison</a></td><td> </td><td align="left" valign="top"> 理解Bison的基本概念.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC19">2. 实例-Examples</a></td><td> </td><td align="left" valign="top"> 三个详细解释的使用Binson的例子.
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">参考章节:
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC42">3. Biosn的语法文件-Bison Grammar Files</a></td><td> </td><td align="left" valign="top"> 编写Bison声明和规则.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC73">4. 分析器C语言接口-Parser C-Language Interface</a></td><td> </td><td align="left" valign="top"> 分析器函数<code>yyparse</code>的C语言接口.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC82">5. Bison分析器算法-The Bison Parser Algorithm</a></td><td> </td><td align="left" valign="top"> Bison分析器运行时如何工作.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC96">6. 错误恢复-Error Recovery</a></td><td> </td><td align="left" valign="top"> 编写错误恢复规则.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC97">7. 处理上下文依赖-Handling Context Dependencies</a></td><td> </td><td align="left" valign="top"> 如果你的语言的语法过于凌乱以至于Bison不能直接处理,你该怎么做.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC101">8. 调式你的分析器-Debugging Your Parser</a></td><td> </td><td align="left" valign="top"> 理解或调试Bison分析器.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC104">9. 调用Bison-Invoking Bison</a></td><td> </td><td align="left" valign="top"> 如何运行Bison(来生成分析源文件).
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC114">A. Bison符号-Bison Symbols</a></td><td> </td><td align="left" valign="top"> 解释所有Bison语言的关键字.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC115">B. 词汇表-Glossary</a></td><td> </td><td align="left" valign="top"> 解释基本概念.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC108">10. 常见问题-Frequently Asked Questions</a></td><td> </td><td align="left" valign="top"> 常见问题
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC116">C. 复制这个手册-Copying This Manual</a></td><td> </td><td align="left" valign="top"> 复制这个手册的许可
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC119">索引-Index</a></td><td> </td><td align="left" valign="top"> 文本交叉索引
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment"> --- 详细节点列表 ---
- Bison的基本概念-The Concepts of Bison
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td><td> </td><td align="left" valign="top"> 从数学的概念来介绍语言和上下文无关文法.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC8">1.2 从正规文法转换到Bison的输入-From Formal Rules to Bison Input</a></td><td> </td><td align="left" valign="top"> 怎样用Bison的语法表示各种文法.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC9">1.3 语义值-Semantic Values</a></td><td> </td><td align="left" valign="top"> 每个记号或者语法组可有一个语义值(例如:整数的数值,标识符的名称等等)
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC10">1.4 语义动作</a></td><td> </td><td align="left" valign="top"> 每个规则可有一个包含C代码的动作
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC11">1.5 编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers</a></td><td> </td><td align="left" valign="top"> 为普通的上下文无关文法编写分析器
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC15">1.6 位置-Locations</a></td><td> </td><td align="left" valign="top"> 追踪位置
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC16">1.7 Bison的输出:分析器文件-Bison Output: the Parser File</a></td><td> </td><td align="left" valign="top"> Bison的输入和输出是什么,怎样使用Bison的输出
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC17">1.8 使用Bison的流程-Stages in Using Bison</a></td><td> </td><td align="left" valign="top"> 编写和运行Bison语法分析程序的流程.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC18">1.9 Bison语法文件的整体布局-The Overall Layout of a Bison Grammar</a></td><td> </td><td align="left" valign="top"> Bison语法文件的整体布局
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC12">1.5.1 使用<acronym>GLR</acronym>分析器分析非歧义文法</a></td><td> </td><td align="left" valign="top"></td></tr>
- <tr><td align="left" valign="top"><a href="#SEC13">1.5.2 使用<acronym>GLR</acronym>解决歧义-Using <acronym>GLR</acronym> to Resolve Ambiguities</a></td><td> </td><td align="left" valign="top"> 使用<acronym>GLR</acronym>分析器解决歧义
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC14">1.5.3 编译<acronym>GLR</acronym>分析器时需要考虑的问题-Considerations when Compiling <acronym>GLR</acronym> Parsers</a></td><td> </td><td align="left" valign="top"> <acronym>GLR</acronym>分析器需要一个现代的C编译器
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">实例-Examples
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC20">2.1 逆波兰记号计算器-Reverse Polish Notation Calculator</a></td><td> </td><td align="left" valign="top"> 逆波兰记号计算器,我们的第一个例子,并不带有操作符优先级
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC31">2.2 中缀符号计算器:<code>calc</code>-Infix Notation Calculator: <code>calc</code></a></td><td> </td><td align="left" valign="top"> 中缀代数符号计算器,简单地介绍操作符优先级.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC32">2.3 简单的错误恢复-Simple Error Recovery</a></td><td> </td><td align="left" valign="top"> 在出现语法错误后继续分析
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC33">2.4 带有位置追踪的计算器:<code>ltcalc</code>-Location Tracking Calculator: <code>ltcalc</code></a></td><td> </td><td align="left" valign="top"> 展示@<var>n</var>和@$的用法
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC37">2.5 多功能计算器:<code>mfcalc</code>-Multi-Function Calculator: <code>mfcalc</code></a></td><td> </td><td align="left" valign="top"> 带有存储和触发功能的计算器.它使用了多种数据类型来表示语义值.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC41">2.6 练习-Exercises</a></td><td> </td><td align="left" valign="top"> 一些改进多功能计算器的方案
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">逆波兰记号计算器-Reverse Polish Notation Calculator
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC21">2.1.1 <code>rpclac</code>的声明部分-Declarations for <code>rpcalc</code></a></td><td> </td><td align="left" valign="top"> rpclac的Prologue(声明)部分.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC22">2.1.2 <code>rpcalc</code>的语法规则-Grammar Rules for <code>rpcalc</code></a></td><td> </td><td align="left" valign="top"> 带注释的rpcalc语法规则
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC26">2.1.3 <code>rpcalc</code>的词法分析器-The <code>rpcalc</code> Lexical Analyzer</a></td><td> </td><td align="left" valign="top"> 词法分析器
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC27">2.1.4 控制函数-The Controlling Function</a></td><td> </td><td align="left" valign="top"> 控制函数
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC28">2.1.5 错误报告的规则-The Error Reporting Routine</a></td><td> </td><td align="left" valign="top"> 错误报告的规则
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC29">2.1.6 运行Bison来产生分析器-Running Bison to Make the Parser</a></td><td> </td><td align="left" valign="top"> 使用Bison生成分析器
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC30">2.1.7 编译分析器文件-Compiling the Parser File</a></td><td> </td><td align="left" valign="top"> 使用C编译器编译得到最终结果
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment"><code>rpcalc</code>的语法规则-Grammar Rules for <code>rpcalc</code>
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC23">2.1.2.1 解释<code>input</code>-Explanation of <code>input</code></a></td><td> </td><td align="left" valign="top">
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC24">2.1.2.2 解释<code>line</code>-Explanation of <code>line</code></a></td><td> </td><td align="left" valign="top">
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC25">2.1.2.3 解释<code>expr</code>-Explanation of <code>expr</code></a></td><td> </td><td align="left" valign="top">
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">位置追踪计算器:<code>ltcalc</code>-Location Tracking Calculator: <code>ltcalc</code>
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC34">2.4.1 <code>ltcalc</code>的<var>Declarations</var>-Declarations for <code>ltcalc</code></a></td><td> </td><td align="left" valign="top"> ltcalc的Bison和C语言的声明
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC35">2.4.2 <code>ltcalc</code>的语法规则-Grammar Rules for <code>ltcalc</code></a></td><td> </td><td align="left" valign="top"> 详细解释ltcalc的语法规则
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC36">2.4.3 <code>ltcalc</code>的词法分析器-The <code>ltcalc</code> Lexical Analyzer.</a></td><td> </td><td align="left" valign="top"> 词法分析器
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">多功能计算器:<code>mfcalc</code>-Multi-Function Calculator: <code>mfcalc</code>
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC38">2.5.1 <code>mfcalc</code>的声明-Declarations for <code>mfcalc</code></a></td><td> </td><td align="left" valign="top"> 多功能计算器的Bison声明
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC39">2.5.2 <code>mfcalc</code>的语法规则-Grammar Rules for <code>mfcalc</code></a></td><td> </td><td align="left" valign="top"> 计算器的语法声明
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC40">2.5.3 <code>mfcalc</code>的符号表-The <code>mfcalc</code> Symbol Table</a></td><td> </td><td align="left" valign="top"> 符号表管理规则
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">Bison语法文件-Bison Grammar Files
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC43">3.1 Bison语法的提纲-Outline of a Bison Grammar</a></td><td> </td><td align="left" valign="top"> 语法文件的整体布局
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td><td> </td><td align="left" valign="top"> 终结符与非终结符
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC49">3.3 描述语法规则的语法-Syntax of Grammar Rules</a></td><td> </td><td align="left" valign="top"> 如何编写语法规则
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC50">3.4 递归规则-Recursive Rules</a></td><td> </td><td align="left" valign="top"> 编写递归规则
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC51">3.5 定义语言的语义-Defining Language Semantics</a></td><td> </td><td align="left" valign="top"> 语义值和动作
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC57">3.6 追踪位置-Tracking Locations</a></td><td> </td><td align="left" valign="top"> 位置和动作
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC61">3.7 Bison声明-Bison Declarations</a></td><td> </td><td align="left" valign="top"> 所有种类的Bison声明在这里讨论
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC72">3.8 在同一个程序中使用多个分析器-Multiple Parsers in the Same Program</a></td><td> </td><td align="left" valign="top"> 将多个Bison分析器放在一个程序中
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">Bison语法提纲-Outline of a Bison Grammar
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC44">3.1.1 <var>Prologue</var>部分-The prologue</a></td><td> </td><td align="left" valign="top"> Prologue部分的语法和使用
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC45">3.1.2 <var>Bison Declarations</var>部分-The Bison Declarations Section</a></td><td> </td><td align="left" valign="top"> Bison declarations部分的语法和使用
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC46">3.1.3 语法规则部分-The Grammar Rules Section</a></td><td> </td><td align="left" valign="top"> Grammar Rules部分的语法和使用
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC47">3.1.4 <var>Epilogue</var>部分-The epilogue</a></td><td> </td><td align="left" valign="top"> Epilogue部分的语法和使用
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">定义语言的语义-Defining Language Semantics
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC52">3.5.1 语义值的数据类型-Data Types of Semantic Values</a></td><td> </td><td align="left" valign="top"> 为所有的语义值指定一个类型.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC53">3.5.2 多种值类型-More Than One Value Type</a></td><td> </td><td align="left" valign="top"> 指定多种可选的数据类型.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC54">3.5.3 动作-Actions</a></td><td> </td><td align="left" valign="top"> 动作是一个语法规则的语义定义.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC55">3.5.4 动作中值的数据类型-Data Types of Values in Actions</a></td><td> </td><td align="left" valign="top"> 为动作指定一个要操作的数据类型.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC56">3.5.5 规则中的动作-Actions in Mid-Rule</a></td><td> </td><td align="left" valign="top"> 多数动作在规则之后,
- 这一节讲述什么时候以及为什么要使用规则中间动作的特例.
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">追踪位置-Tracking Locations
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC58">3.6.1 位置的数据类型-Data Type of Locations</a></td><td> </td><td align="left" valign="top"> 描述位置的数据类型.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC59">3.6.2 动作和位置-Actions and Locations</a></td><td> </td><td align="left" valign="top"> 在动作中使用位置.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC60">3.6.3 位置的默认动作-Default Action for Locations</a></td><td> </td><td align="left" valign="top"> 定义了一个计算位置的通用方法.
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">Bison声明-Bison Declarations
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC62">3.7.1 符号类型名称-Token Type Names</a></td><td> </td><td align="left" valign="top"> 声明终结符
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC63">3.7.2 操作符优先级-Operator Precedence</a></td><td> </td><td align="left" valign="top"> 声明终结符的优先级和结合性
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC64">3.7.3 值类型集-The Collection of Value Types</a></td><td> </td><td align="left" valign="top"> 声明一组语义值类型
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC65">3.7.4 非终结符-Nonterminal Symbols</a></td><td> </td><td align="left" valign="top"> 声明非终结语义值的类型
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC66">3.7.5 在分析执行前执行一些动作-Performing Actions before Parsing</a></td><td> </td><td align="left" valign="top"> 在分析开始前执行的代码
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC67">3.7.6 释放被丢弃的符号-Freeing Discarded Symbols</a></td><td> </td><td align="left" valign="top"> 声明如何释放符号
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC68">3.7.7 消除冲突警告-Suppressing Conflict Warnings</a></td><td> </td><td align="left" valign="top"> 消除分析冲突时的警告
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC69">3.7.8 开始符号-The Start-Symbol</a></td><td> </td><td align="left" valign="top"> 指明开始符号
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC70">3.7.9 纯(可重入)分析器-A Pure (Reentrant) Parser</a></td><td> </td><td align="left" valign="top"> 请求一个可重入的分析器
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC71">3.7.10 Bison声明总结-Bison Declaration Summary</a></td><td> </td><td align="left" valign="top"> 一个所有Bison声明的总结
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">分析器C语言接口-Parser C-Language Interface
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC74">;4.1 分析器函数<code>yyparse</code>-The Parser Function <code>yyparse</code></a></td><td> </td><td align="left" valign="top"> 如何调用<code>yyparse</code>以及它的返回值.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC75">4.2 词法分析器函数<code>yylex</code>-The Lexical Analyzer Function <code>yylex</code></a></td><td> </td><td align="left" valign="top"> 你必提供一个读入记号的函数<code>yylex</code>.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC80">4.3 错误报告函数<code>yyerror</code>-The Error Reporting Function <code>yyerror</code></a></td><td> </td><td align="left" valign="top"> 你必须提供一个函数<code>yyerror</code>.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC81">4.4 在动作中使用的特殊特征-Special Features for Use in Actions</a></td><td> </td><td align="left" valign="top"> 在动作中使用的特殊特征.
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">词法分析器函数<code>yylex</code>-The Lexical Analyzer Function <code>yylex</code>
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC76">4.2.1 <code>yylex</code>的调用惯例-Calling Convention for <code>yylex</code></a></td><td> </td><td align="left" valign="top"> <code>yyparse</code>如何调用<code>yylex</code>.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC77">4.2.2 记号的语义值-Semantic Values of Tokens</a></td><td> </td><td align="left" valign="top"> <code>yylex</code>是如何返回它已经读入的记号的语义值.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC78">4.2.3 记号的文字位置-Textual Locations of Tokens</a></td><td> </td><td align="left" valign="top"> 如果动作需要,<code>yylex</code>是如何返回记号的文字位置(行号,等等).
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC79">4.2.4 纯分析器的调用惯例-Conventions for Pure Parsers</a></td><td> </td><td align="left" valign="top"> 调用惯例如何区分一个纯分析器
- (参阅<a href="#SEC70">一个纯(可重入)分析器-A Pure (Reentrant) Parser</a>一章).
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">Bison分析器算法-The Bison Parser Algorithm
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC83">5.1 超前扫描记号-Look-Ahead Tokens</a></td><td> </td><td align="left" valign="top"> 当分析器决定做什么的时候它查看的一个记号.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC84">5.2 移进/归约冲突-Shift/Reduce Conflicts</a></td><td> </td><td align="left" valign="top"> 冲突:移进和归约均有效.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC85">5.3 操作符优先级-Operator Precedence</a></td><td> </td><td align="left" valign="top"> 由于解决冲突的操作符优先级.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC90">5.4 上下文依赖优先级-Context-Dependent Precedence</a></td><td> </td><td align="left" valign="top"> 当一个操作符的优先级依赖上下文.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC91">5.5 分析器状态-Parser States</a></td><td> </td><td align="left" valign="top"> 分析器是一个带有栈的有限状态机.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC92">5.6 归约/归约冲突-Reduce/Reduce Conflicts</a></td><td> </td><td align="left" valign="top"> 在同意情况下可以应用两个规则.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC93">5.7 神秘的归约/归约冲突-Mysterious Reduce/Reduce Conflicts</a></td><td> </td><td align="left" valign="top"> 看起来不平等的归约/归约冲突.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC94">5.8 通用<acronym>LR</acronym> (<acronym>GLR</acronym>)分析-Generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) Parsing</a></td><td> </td><td align="left" valign="top"> 分析arbitrary上下文无关文法.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC95">5.9 栈溢出以及如何避免它-Stack Overflow, and How to Avoid It</a></td><td> </td><td align="left" valign="top"> 当栈溢出时发生的事情以及如何避免它.
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">操作符优先级-Operator Precedence
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC86">5.3.1 什么时候需要优先级-When Precedence is Needed</a></td><td> </td><td align="left" valign="top"> 一个展示为什么需要优先级的例子
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC87">5.3.2 指定操作符的优先级-Specifying Operator Precedence</a></td><td> </td><td align="left" valign="top"> 在Bison的语法中如何指定优先级
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC88">5.3.3 优先级使用的例子-Precedence Examples</a></td><td> </td><td align="left" valign="top"> 这些特性在前面的例子中是怎样使用的
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC89">5.3.4 优先级如何工作-How Precedence Works</a></td><td> </td><td align="left" valign="top"> 它们如何工作
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">处理上下文依赖-Handling Context Dependencies
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC98">7.1 符号类型中的语义信息-Semantic Info in Token Types</a></td><td> </td><td align="left" valign="top"> 对记号的分析可能依赖于语义上下文.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC99">7.2 词法关联-Lexical Tie-ins</a></td><td> </td><td align="left" valign="top"> 对记号的分析可能依赖上下文.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC100">7.3 词法关联和错误恢复-Lexical Tie-ins and Error Recovery</a></td><td> </td><td align="left" valign="top"> 词法关联含有如何编写错误恢复规则的暗示.
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">调试你的分析器-Debugging Your Parser
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td><td> </td><td align="left" valign="top"> 理解你的分析器的结构
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC103">8.2 跟踪你的分析器-Tracing Your Parser</a></td><td> </td><td align="left" valign="top"> 跟踪你的分析器的执行
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">调用Bison-Invoking Bison
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC105">9.1 Bison选项-Bison Options</a></td><td> </td><td align="left" valign="top"> 按简写选项的字母顺序详细描述所有选项
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC106">9.2 选项交叉键-Option Cross Key</a></td><td> </td><td align="left" valign="top"> 按字母顺序列出长选项
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC107">9.3 Yacc库-Yacc Library</a></td><td> </td><td align="left" valign="top"> 与Yacc兼容的<code>yylex</code>和<code>main</code>
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">常见问题-Frequently Asked Questions
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC109">10.1 分析器栈溢出-Parser Stack Overflow</a></td><td> </td><td align="left" valign="top"> 突破栈限制
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC110">10.2 我如何复位分析器-How Can I Reset the Parser</a></td><td> </td><td align="left" valign="top"> <code>yyparse</code>保持一些状态
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC111">10.3 被销毁的字符串-Strings are Destroyed</a></td><td> </td><td align="left" valign="top"> <code>yylval</code>丢掉了字符串的追踪
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC112">10.4 C++分析器-C++ Parsers</a></td><td> </td><td align="left" valign="top"> 使用C++编译器编译分析器
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC113">10.5 实现跳转/循环-Implementing Gotos/Loops</a></td><td> </td><td align="left" valign="top"> 在计算器中控制流
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment">复制这个文档-Copying This Manual
- </pre></th></tr><tr><td align="left" valign="top"><a href="#SEC117">C.1 GNU Free Documentation License</a></td><td> </td><td align="left" valign="top"> 复制这个手册的许可.
- </td></tr>
- <tr><th colspan="3" align="left" valign="top"><pre name="code" class="menu-comment"></pre></th></tr></tbody></table>
- <hr size="1">
- <a name="Introduction"></a>
- <a name="SEC1"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC_Top"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC2"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[ << ]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC2"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="unnumbered"><a name="t2"></a> Bison简介-Introduction </h1>
- <p><em>Bison</em>是一种通用目的的分析器生成器.
- 它将<acronym>LALR</acronym>(1)上下文无关文法的描述转化成分析该文法的C程序.
- 一旦你精通<acronym>Bison</acronym>,
- 你可以用它生成从简单的桌面计算器到复杂的程序设计语言等等许多语言的分析器.
- </p>
- <p>Bison向上兼容Yacc:所有书写正确的Yacc语法都应该可以不加更改地与Bison一起工作.
- 熟悉Yacc的人能毫不费力地使用Bison.
- 你应该熟练地掌握C程序设计语言,这样你才能使用Bison和理解这个手册.
- </p>
- <p>我们会在这个教程的最初几章解释BIson的基本概念,并且展示三个详细解释的例子,
- 这些例子将在教程的最后被构建.
- 如果你对Bison或者Yacc一无所知,
- 你应该首先阅读这些章节.
- 接下来的参阅章节详细地阐述了Bison的各个方面.
- </p>
- <p>Bison主要由Rovert Corbett编写.Richard Stallman使它与Yacc兼容.
- Carnegie Mellon大学的Wilfred Hansen为Bison添加了
- 多字符字符串文字(multi-character string literals)和其它一些特性.
- </p>
- <p>这个版本的手则主要与Bison2.0相一致.
- </p><hr size="6">
- <a name="Conditions"></a>
- <a name="SEC2"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC1"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC3"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC1"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC3"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="unnumbered"><a name="t3"></a> 使用Bison的条件-Conditions for Using Bison </h1>
- <p>为了允许非自由程序(nonfree programs)使用Bison生成的LALR分析器C代码,
- 我们在Bison版本1.24的时已经修改了<code>yyparse</code>的发布条款(distribution terms for yyparse).
- 在这之前,这些分析器只能用于自由软件(free software)的程序.
- </p>
- <p>其它<acronym>GNU</acronym>编程工具,例如<acronym>GNU</acronym> C编译器从未有过类似的要求.
- 它们总能用于非自由软件的发布.
- Bison与它们不同的原因并不是出于特殊策略的决定,
- 而是由于应用通用许可证(General Public License)到所有的Bison源代码造成的结果.
- </p>
- <p>Bison工具的输出-也就是Bison分析器文件(the Bison parser file)包括大小不固定的Bison代码片段.
- 这些代码片段来源于yyparse函数.(你的语法的动作被Bison插入到这个函数的某个位置,
- 但是函数的其余部分并未更改).当我们应用GPL条款到yyparse的代码的时候,
- 它产生的效果就是Bison的输出只能到自由软件.
- </p>
- <p>我们并未更改条款使出于对那些希望是软件私有化的人的同情.
- <strong>所有的软件都应该是自由软件.</strong>但是我们的结论是:
- 使Bison只能用于自由软件,这对鼓励人们使其它软件变为自由软件作用甚微.
- 所以我们决定将使用Bison的条件与使用其它<acronym>GNU</acronym>工具的条件相一致.
- (注:即和<acronym>GCC</acronym>一样可以用于非自由软件).
- </p>
- <p>这个特例仅仅在Bison生成<acronym>LALR</acronym>(1)分析器的C代码时适用.
- 否则,<acronym>GPL</acronym>条款仍然正常的执行.
- 你可以通过查看代码,看其是否由这样的说明"As a special execption, when
- this file is copied by Bison into a Bison output file, you may use that
- output file without restriction."来分辩这个特例是否适用于你的<samp>`.c'</samp>输出文件.
- </p>
- <hr size="6">
- <a name="Copying"></a>
- <a name="SEC3"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC2"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC4"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC2"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC6"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="unnumbered"><a name="t4"></a> GNU GENERAL PUBLIC LICENSE </h1>
- <p align="center"> Version 2, June 1991
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="display">Copyright © 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="SEC4"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC3"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC5"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC3"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC3"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC6"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="unnumberedsec"><a name="t5"></a> Preamble </h2>
- <p> The licenses for most software are designed to take away your
- freedom to share and change it. By contrast, the GNU General Public
- License is intended to guarantee your freedom to share and change free
- software--to make sure the software is free for all its users. This
- General Public License applies to most of the Free Software
- Foundation's software and to any other program whose authors commit to
- using it. (Some other Free Software Foundation software is covered by
- the GNU Library General Public License instead.) You can apply it to
- your programs, too.
- </p>
- <p> When we speak of free software, we are referring to freedom, not
- price. Our General Public Licenses are designed to make sure that you
- have the freedom to distribute copies of free software (and charge for
- this service if you wish), that you receive source code or can get it
- if you want it, that you can change the software or use pieces of it
- in new free programs; and that you know you can do these things.
- </p>
- <p> To protect your rights, we need to make restrictions that forbid
- anyone to deny you these rights or to ask you to surrender the rights.
- These restrictions translate to certain responsibilities for you if you
- distribute copies of the software, or if you modify it.
- </p>
- <p> For example, if you distribute copies of such a program, whether
- gratis or for a fee, you must give the recipients all the rights that
- you have. You must make sure that they, too, receive or can get the
- source code. And you must show them these terms so they know their
- rights.
- </p>
- <p> We protect your rights with two steps: (1) copyright the software, and
- (2) offer you this license which gives you legal permission to copy,
- distribute and/or modify the software.
- </p>
- <p> Also, for each author's protection and ours, we want to make certain
- that everyone understands that there is no warranty for this free
- software. If the software is modified by someone else and passed on, we
- want its recipients to know that what they have is not the original, so
- that any problems introduced by others will not reflect on the original
- authors' reputations.
- </p>
- <p> Finally, any free program is threatened constantly by software
- patents. We wish to avoid the danger that redistributors of a free
- program will individually obtain patent licenses, in effect making the
- program proprietary. To prevent this, we have made it clear that any
- patent must be licensed for everyone's free use or not licensed at all.
- </p>
- <p> The precise terms and conditions for copying, distribution and
- modification follow.
- </p>
- <ol>
- <li>
- This License applies to any program or other work which contains
- a notice placed by the copyright holder saying it may be distributed
- under the terms of this General Public License. The "Program", below,
- refers to any such program or work, and a "work based on the Program"
- means either the Program or any derivative work under copyright law:
- that is to say, a work containing the Program or a portion of it,
- either verbatim or with modifications and/or translated into another
- language. (Hereinafter, translation is included without limitation in
- the term "modification".) Each licensee is addressed as "you".
- <p>Activities other than copying, distribution and modification are not
- covered by this License; they are outside its scope. The act of
- running the Program is not restricted, and the output from the Program
- is covered only if its contents constitute a work based on the
- Program (independent of having been made by running the Program).
- Whether that is true depends on what the Program does.
- </p>
- </li><li>
- You may copy and distribute verbatim copies of the Program's
- source code as you receive it, in any medium, provided that you
- conspicuously and appropriately publish on each copy an appropriate
- copyright notice and disclaimer of warranty; keep intact all the
- notices that refer to this License and to the absence of any warranty;
- and give any other recipients of the Program a copy of this License
- along with the Program.
- <p>You may charge a fee for the physical act of transferring a copy, and
- you may at your option offer warranty protection in exchange for a fee.
- </p>
- </li><li>
- You may modify your copy or copies of the Program or any portion
- of it, thus forming a work based on the Program, and copy and
- distribute such modifications or work under the terms of Section 1
- above, provided that you also meet all of these conditions:
- <ol>
- <li>
- You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
- </li><li>
- You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
- </li><li>
- If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
- </li></ol>
- <p>These requirements apply to the modified work as a whole. If
- identifiable sections of that work are not derived from the Program,
- and can be reasonably considered independent and separate works in
- themselves, then this License, and its terms, do not apply to those
- sections when you distribute them as separate works. But when you
- distribute the same sections as part of a whole which is a work based
- on the Program, the distribution of the whole must be on the terms of
- this License, whose permissions for other licensees extend to the
- entire whole, and thus to each and every part regardless of who wrote it.
- </p>
- <p>Thus, it is not the intent of this section to claim rights or contest
- your rights to work written entirely by you; rather, the intent is to
- exercise the right to control the distribution of derivative or
- collective works based on the Program.
- </p>
- <p>In addition, mere aggregation of another work not based on the Program
- with the Program (or with a work based on the Program) on a volume of
- a storage or distribution medium does not bring the other work under
- the scope of this License.
- </p>
- </li><li>
- You may copy and distribute the Program (or a work based on it,
- under Section 2) in object code or executable form under the terms of
- Sections 1 and 2 above provided that you also do one of the following:
- <ol>
- <li>
- Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
- </li><li>
- Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
- </li><li>
- Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
- </li></ol>
- <p>The source code for a work means the preferred form of the work for
- making modifications to it. For an executable work, complete source
- code means all the source code for all modules it contains, plus any
- associated interface definition files, plus the scripts used to
- control compilation and installation of the executable. However, as a
- special exception, the source code distributed need not include
- anything that is normally distributed (in either source or binary
- form) with the major components (compiler, kernel, and so on) of the
- operating system on which the executable runs, unless that component
- itself accompanies the executable.
- </p>
- <p>If distribution of executable or object code is made by offering
- access to copy from a designated place, then offering equivalent
- access to copy the source code from the same place counts as
- distribution of the source code, even though third parties are not
- compelled to copy the source along with the object code.
- </p>
- </li><li>
- You may not copy, modify, sublicense, or distribute the Program
- except as expressly provided under this License. Any attempt
- otherwise to copy, modify, sublicense or distribute the Program is
- void, and will automatically terminate your rights under this License.
- However, parties who have received copies, or rights, from you under
- this License will not have their licenses terminated so long as such
- parties remain in full compliance.
- </li><li>
- You are not required to accept this License, since you have not
- signed it. However, nothing else grants you permission to modify or
- distribute the Program or its derivative works. These actions are
- prohibited by law if you do not accept this License. Therefore, by
- modifying or distributing the Program (or any work based on the
- Program), you indicate your acceptance of this License to do so, and
- all its terms and conditions for copying, distributing or modifying
- the Program or works based on it.
- </li><li>
- Each time you redistribute the Program (or any work based on the
- Program), the recipient automatically receives a license from the
- original licensor to copy, distribute or modify the Program subject to
- these terms and conditions. You may not impose any further
- restrictions on the recipients' exercise of the rights granted herein.
- You are not responsible for enforcing compliance by third parties to
- this License.
- </li><li>
- If, as a consequence of a court judgment or allegation of patent
- infringement or for any other reason (not limited to patent issues),
- conditions are imposed on you (whether by court order, agreement or
- otherwise) that contradict the conditions of this License, they do not
- excuse you from the conditions of this License. If you cannot
- distribute so as to satisfy simultaneously your obligations under this
- License and any other pertinent obligations, then as a consequence you
- may not distribute the Program at all. For example, if a patent
- license would not permit royalty-free redistribution of the Program by
- all those who receive copies directly or indirectly through you, then
- the only way you could satisfy both it and this License would be to
- refrain entirely from distribution of the Program.
- <p>If any portion of this section is held invalid or unenforceable under
- any particular circumstance, the balance of the section is intended to
- apply and the section as a whole is intended to apply in other
- circumstances.
- </p>
- <p>It is not the purpose of this section to induce you to infringe any
- patents or other property right claims or to contest validity of any
- such claims; this section has the sole purpose of protecting the
- integrity of the free software distribution system, which is
- implemented by public license practices. Many people have made
- generous contributions to the wide range of software distributed
- through that system in reliance on consistent application of that
- system; it is up to the author/donor to decide if he or she is willing
- to distribute software through any other system and a licensee cannot
- impose that choice.
- </p>
- <p>This section is intended to make thoroughly clear what is believed to
- be a consequence of the rest of this License.
- </p>
- </li><li>
- If the distribution and/or use of the Program is restricted in
- certain countries either by patents or by copyrighted interfaces, the
- original copyright holder who places the Program under this License
- may add an explicit geographical distribution limitation excluding
- those countries, so that distribution is permitted only in or among
- countries not thus excluded. In such case, this License incorporates
- the limitation as if written in the body of this License.
- </li><li>
- The Free Software Foundation may publish revised and/or new versions
- of the General Public License from time to time. Such new versions will
- be similar in spirit to the present version, but may differ in detail to
- address new problems or concerns.
- <p>Each version is given a distinguishing version number. If the Program
- specifies a version number of this License which applies to it and "any
- later version", you have the option of following the terms and conditions
- either of that version or of any later version published by the Free
- Software Foundation. If the Program does not specify a version number of
- this License, you may choose any version ever published by the Free Software
- Foundation.
- </p>
- </li><li>
- If you wish to incorporate parts of the Program into other free
- programs whose distribution conditions are different, write to the author
- to ask for permission. For software which is copyrighted by the Free
- Software Foundation, write to the Free Software Foundation; we sometimes
- make exceptions for this. Our decision will be guided by the two goals
- of preserving the free status of all derivatives of our free software and
- of promoting the sharing and reuse of software generally.
- </li><li>
- BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
- FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
- OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
- PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
- OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
- TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
- PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
- REPAIR OR CORRECTION.
- </li><li>
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
- WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
- REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
- INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
- OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
- TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
- YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
- PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGES.
- </li></ol>
- <hr size="6">
- <a name="SEC5"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC4"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC6"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC3"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC3"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC6"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="unnumberedsec"><a name="t6"></a> Appendix: How to Apply These Terms to Your New Programs </h2>
- <p> If you develop a new program, and you want it to be of the greatest
- possible use to the public, the best way to achieve this is to make it
- free software which everyone can redistribute and change under these terms.
- </p>
- <p> To do so, attach the following notices to the program. It is safest
- to attach them to the start of each source file to most effectively
- convey the exclusion of warranty; and each file should have at least
- the "copyright" line and a pointer to where the full notice is found.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample"><var>one line to give the program's name and a brief idea of what it does.</var>
- Copyright (C) <var>yyyy</var> <var>name of author</var>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- </pre></td></tr></tbody></table>
- <p>Also add information on how to contact you by electronic and paper mail.
- </p>
- <p>If the program is interactive, make it output a short notice like this
- when it starts in an interactive mode:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">Gnomovision version 69, Copyright (C) 19<var>yy</var> <var>name of author</var>
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
- </pre></td></tr></tbody></table>
- <p>The hypothetical commands <samp>`show w'</samp> and <samp>`show c'</samp> should show
- the appropriate parts of the General Public License. Of course, the
- commands you use may be called something other than <samp>`show w'</samp> and
- <samp>`show c'</samp>; they could even be mouse-clicks or menu items--whatever
- suits your program.
- </p>
- <p>You should also get your employer (if you work as a programmer) or your
- school, if any, to sign a "copyright disclaimer" for the program, if
- necessary. Here is a sample; alter the names:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
- <var>signature of Ty Coon</var>, 1 April 1989
- Ty Coon, President of Vice
- </pre></td></tr></tbody></table>
- <p>This General Public License does not permit incorporating your program into
- proprietary programs. If your program is a subroutine library, you may
- consider it more useful to permit linking proprietary applications with the
- library. If this is what you want to do, use the GNU Library General
- Public License instead of this License.
- </p>
- <hr size="6">
- <a name="Concepts"></a>
- <a name="SEC6"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC5"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC7"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC3"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="chapter"><a name="t7"></a> 1. 和Bison相关的一些基本概念-The Concepts of Bison </h1>
- <p>这一章介绍了许多基本概念,但没有提及一些感觉不到的细节.
- 如果你并不了解如何使用Bison/Yacc,我们建议你仔细阅读这一章.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td><td> </td><td align="left" valign="top"> 从数学的概念来介绍语言和上下文无关文法.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC8">1.2 从正规文法转换到Bison的输入-From Formal Rules to Bison Input</a></td><td> </td><td align="left" valign="top"> 怎样用Bison的语法表示各种文法.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC9">1.3 语义值-Semantic Values</a></td><td> </td><td align="left" valign="top"> 每个记号或者语法组可有一个语义值(例如:整数的数值,标识符的名称等等)
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC10">1.4 语义动作</a></td><td> </td><td align="left" valign="top"> 每个规则可有一个包含C代码的动作
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC11">1.5 编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers</a></td><td> </td><td align="left" valign="top"> 为普通的上下文无关文法编写分析器
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC15">1.6 位置-Locations</a></td><td> </td><td align="left" valign="top"> 追踪位置
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC16">1.7 Bison的输出:分析器文件-Bison Output: the Parser File</a></td><td> </td><td align="left" valign="top"> Bison的输入和输出是什么,怎样使用Bison的输出
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC17">1.8 使用Bison的流程-Stages in Using Bison</a></td><td> </td><td align="left" valign="top"> 编写和运行Bison语法分析程序的流程.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC18">1.9 Bison语法文件的整体布局-The Overall Layout of a Bison Grammar</a></td><td> </td><td align="left" valign="top"> Bison语法文件的整体布局
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Language-and-Grammar"></a>
- <a name="SEC7"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC6"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC8"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC6"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t8"></a> 1.1 语言与上下文无关文法-Languages and Context-Free Grammars </h2>
- <p>为了使Bison能分析语言,这种语言必须由<em>上下文无关文法(context-free grammar)</em>描述.
- 也就是说,你必须指出一个或者多个<em>语法组(syntactic groupings)</em>以及从语法组的部分构它的建整体的规则.
- 例如,在C语言中,有一种我们称之为`表达式(expression)'的语法组.
- 一个生成表达式的规则可能是"一个表达式由一个减号和另一个表达式构成".
- 另外一个规则可能是"一个表达式可以是一个整数".
- 就象你看到的一样,规则经常是递归定义的,但是必须有一个结束递归的规则.
- </p>
- <a name="IDX1"></a>
- <a name="IDX2"></a>
- <p>用于表示这些规则的最普遍的系统是<em>Backus-Naur 范式(Backus-Naur Form)</em>或者"<acronym>BNF</acronym>".
- 发明这种语言的目的是用来阐述Algol 60.
- 任何用<acronym>BNF</acronym>表示的文法都是一种上下文无关文法.
- Bison要求它的的输入必须用<acronym>BNF</acronym>表示.
- </p>
- <a name="IDX3"></a>
- <a name="IDX4"></a>
- <p>上下文无关文法有许多重要的子集.尽管Bison可以处理几乎所有的上下文无关文法,
- 但Bison针对<acronym>LALR</acronym>(1) 文法(<acronym>LALR</acronym>(1) grammars)做了优化.
- 简而言之,在这些文法中(注:指LALR(1)),我们可以告之如何分析仅代有一个超前扫描记号的输入字符串的任意部分.
- 严格的说,这是一个<acronym>LR</acronym>(1)文法的描述.
- <acronym>LALR</acronym>(1)包括了与多难以分析的额外限制.
- 幸运的是,在实际中,我们很难找到一个是<acronym>LR</acronym>(1)文法而不是<acronym>LALR</acronym>(1)文法的例子.
- 参阅<a href="#SEC93">神秘的归约/归约冲突-Mysterious Reduce/Reduce Conflicts</a>,以获取更多信息.
- </p>
- <a name="IDX5"></a>
- <a name="IDX6"></a>
- <a name="IDX7"></a>
- <a name="IDX8"></a>
- <p><acronym>LALR</acronym>(1)文法分析器具有<em>确定性(deterministic)</em>,
- 这就意味着应用于输入的下一个文法规则取决于之前的输入和确定的部分剩余输入(我们称之为一个<em>超前扫描记号(look-ahead)</em>.
- 一个上下文无关文法可能是有<em>歧义的(ambiguous)</em>,即可能可以应用多种规则来获取某些输入.
- 即使非歧义性文法也可能使<em>不确定(non-deterministic)</em>的,
- 即没有总能足以决定下一个应用的文法规则的确定的超前扫描记号。
- 使用孰知的<acronym>GLR</acronym>技术,Bison的<acronym>GLR</acronym>就可以分析这些更为普通的上下文无关文法.
- 当任意给定字符串的可能的分析是确定的情况下,Bison可以处理任意上下文无关文法.
- </p>
- <a name="IDX9"></a>
- <a name="IDX10"></a>
- <a name="IDX11"></a>
- <a name="IDX12"></a>
- <p>在正式的语言语法规则中,每一种语法单元或组合被称之为<em>符号(symbol)</em>.
- 那些可以通过语法规则被分解成更小的结构的符号叫做<em>非终结符(nonterminal symbols)</em>.
- 那些不能被再分的符号叫做<em>终结符(terminal symbols)</em>或者<em>记号类型(token types)</em>.
- 我们把同终结符相对应的输入片段叫做<em>记号(token)</em>,
- 把同单个非终结符相对应的输入片段叫做<em>组(grouping)</em>.
- </p>
- <p>我们可以使用C语言做为例子来解释什么是符号,以及终结符和非终结符的含义.
- C语言的记号包括标识符,常量(数字或者字符串)以及各种关键字,数学操作符和标点符号.
- 所以C语言语法的终结符包括`identifier',`number',`string',加上每个关键字的符号,操作符或者标点符号.
- 例如:`if',`return',`const',`static',`int',`char',`plus-sign',`open-brace',`close-brace',`comma'以及更多.
- (这些记号可以再分为字符,但是这些是词法学而不是语法学的事情)
- </p>
- <p>这是一个如何将C函数分解成记号的例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int /* 关键字 `int' */
- square (int x) /* identifier, open-paren, 关键字 `int', identifier, close-paren */
- { /* open-brace */
- return x * x; /* 关键字 `return', identifier, asterisk, identifier, semicolon */
- } /* close-brace */
- </pre></td></tr></tbody></table>
- <p>C语言的语法组包括表达式,语句,声明和函数定义.
- 这些由C语言语法中的非终结符`expression',`statement',`declaration'和`funcation definition'表示.
- 完整的语法还使用了许多额外的语言结构,每种结构都有自己的非终结符来表示上述四种的含义.
- 上面的例子是一个函数的定义,它包括了一个声明和一个语句.
- 每一个<samp>`x'</samp>一个表达式,而且<samp>`x * X'</samp>也是一个表达式.
- </p>
- <p>每一个非终结符必须有一个描述如何由更简单结构组成这个非终结符的语法规则.
- 例如,一种C的语句是<code>return</code>语句的非正式表达将由如下的语法规则描述:
- </p>
- <blockquote><p>一种语句可以由一个`return'关键字,一个`expression'何以个`semicolon'组成.
- </p></blockquote>
- <p>还有许多其它对应`statement'的规则,每一种规则对应一种C语句.
- </p>
- <a name="IDX13"></a>
- <p>我们必须注意到一种特殊的非终结符,这种非终结符定义了语言的一个完整表述.
- 我们称之为<em>开始符号(start symbol)</em>.
- 在编译器中,这意味着一个完整的输入程序.
- 在C语言中,非终结符`sequence of definitions and declarations'扮演了这个角色.
- </p>
- <p>例如,<samp>`1+2'</samp>是以个有效的C表达式--一个有效的C程序的部分--但它不能做为一个C程序的<em>全部(entire)</em>.
- 在C语言的上下文无关文法中,这遵循了`expression'不是开始符号的事实.
- </p>
- <p>Bison分析器读取一个记号序列做为它的输入并使用语法规则将记号组合.
- 如果输入是有效的,最终的结果是将整个的输入序列分析整理到开始符号.
- 如果我们使用C语言的语法,整个的输入必须是一个`sequence of definitions and declarations',
- 否则分析器会报告一个语法错误.
- </p>
- <hr size="6">
- <a name="Grammar-in-Bison"></a>
- <a name="SEC8"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC7"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC9"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC6"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t9"></a> 1.2 从正规文法转换到Bison的输入-From Formal Rules to Bison Input </h2>
- <p>正规文法是一种数学结构.为了定义Bison要分析的语言,
- 你必须用Bison语法编写一个表达该语言的文件,即一个<em>Bison 语法(Bison grammar)</em>文件.
- 参阅 <a href="#SEC42">Bison的语法文件-Bison Grammar Files</a>.
- </p>
- <p>就象C语言中的标识符一样,在Bison的输入中,一个正规文法的非终结符由一个标识符表示.
- 根据惯例,非终结符应该用小写子母表示,例如<code>expr</code>,<code>stmt</code>或者<code>declaration</code>.
- </p>
- <p>在Bison中,终结符也被称为<em>符号类型(token type)</em>.
- 符号类型也可以由类似C语言标识符来表示.
- 根据惯例,这些标识符因改用大写子母表示以区分它和非终结符.
- 例如,<code>INTEGER</code>,<code>INDENTIFIER</code>,<code>IF</code>或者<code>RETURN</code>.
- 一个表示某语言的特定关键字的终结符应该由紧随该关键字之后的它的大写表示来命名.
- 终结符<code>error</code>保留用作错误恢复之用.
- 参阅 <a href="#SEC48">符号-Symbols</a>.
- </p>
- <p>一个终结符也可以由一个像C中的字符常量一样的一个字符来表示.
- 当一个记号就是一个字符(括号,加号等等)的时候,你可以这样做:
- 使用同一个字符做为那个记号的终结符.
- </p>
- <p>第三种表示终结符的方法是使用包含一些字符的C字符串常量.
- 获取更多这方面的信息可以参阅 <a href="#SEC48">符号-Symbols</a>.
- </p>
- <p>语法规则在Bison语法中也有相应的表示.例如,下面有一个C语言<code>return</code>语句的规则.
- 在引号中的分号,是一个字符记号,它是用来表示C语言部分语法的.
- 没有在引号中的分号和冒号是Bison用来表示每一条规则的标点符号.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">stmt: RETURN expr ';'
- ;
- </pre></td></tr></tbody></table>
- <p>获取这方面更多信息,参阅 <a href="#SEC49">语法规则的语法-Syntax of Grammar Rules</a>.
- </p>
- <hr size="6">
- <a name="Semantic-Values"></a>
- <a name="SEC9"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC8"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC10"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC6"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t10"></a> 1.3 语义值-Semantic Values </h2>
- <p>正规文法仅仅靠类别来选择记号:例如,如果一个规则提到了终结符`integer constant',
- 这就意味着<em>任何</em>整数常量在那个位置上都是语法有效的.
- 常量的精确值与如何分析输入不相关:如果<samp>`x+4'</samp>符合语法,那么<samp>`x+1'</samp>或者<samp>`x+3989'</samp>也符合语法.
- </p>
- <p>但是,当分析输入时,它的精确值是非常重要的,通过精确值可以了解输入的含义.
- 如果一个编译器不能区别程序中的4,1和3989等常量,毫无疑问,这个编译器是没有用的!
- 因此,每一个Bison语法的记号既含有一个符号类别也有一个<em>语义值(semantic value)</em>.
- 获取这方面的更多信息,参阅 <a href="#SEC51">定义语言的语义-Defining Language Semantics</a>.
- </p>
- <p>符号类型是在语法中定义的终结符,例如<code>INTEGER</code>,<code>IDENTIFIRE</code>或者<code>','</code>.
- 它告诉你决定记号可能有效出现的位置以及如何将它组合成其它记号的信息.
- 语法规则只知道符号的类型,其它的什么都不知道.
- </p>
- <p>语义值包括了记号的所有剩余信息.例如整数的数值,标识符的名称.
- (一个如<code>','</code>的记号只是一个标点,并不需要语义值.)
- </p>
- <p>例如,一个分类为<code>INTEGER</code>的记号包含语义值4.
- 另一个也被分类为<code>INTEGER</code>的记号的语义值却是3989.
- 当一个语法规则表明<code>INTEGER</code>是允许的,任意的这些记号都是可接受的,因为它们都是<code>INTEGER</code>.
- 当一个分析器接受了记号,它会跟踪这个记号的语义值.
- </p>
- <p>每一个语法组和它的非终结符也可已有语义值.
- 一个很典型的例子,在计算器中,一个表达式含有一个数值做为它的语义值,
- 在程序语言编译器中.一个典型的表达式含有一个用于描述它含义的树型结构做为语义值.
- </p>
- <hr size="6">
- <a name="Semantic-Actions"></a>
- <a name="SEC10"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC9"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC11"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC6"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t11"></a> 1.4 语义动作 </h2>
- <p>为了更加实用,一个程序不仅仅要分析输入而且必须做的更多.
- 它应该可以在输入的基础上产生一些输出.
- 在Bison语法中,一个语法规则可以有一个包括多个C语句的<em>动作(action)</em>.
- 分析器每次识别一个规则的匹配,相应的动作就会被执行.
- 获取这方面的更多信息,参阅 <a href="#SEC54">动作-Actions</a>.
- </p>
- <p>大多数时候,动作的目的是从部分结构的语义值计算整个结构的语义值.
- 例如,加入我们有一个规则表明一个表达式可以由两个表达式相加而成.
- 当分析器识别了一个加法和,每一个子表达式都有一个描述其如何构建的语义值.
- 这个规的动做就是为了新识别的大表达式建立一个类似的语义值.
- </p>
- <p>例如,这里的一个规则表明一个表达式可由两个表达式相加而成.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">expr: expr '+' expr { $$ = $1 + $3; }
- ;
- </pre></td></tr></tbody></table>
- <p>这个动作表明了如何从子表达式的语义值产生加法和表达式的语义值.
- </p>
- <hr size="6">
- <a name="GLR-Parsers"></a>
- <a name="SEC11"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC10"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC12"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC6"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t12"></a> 1.5 编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers </h2>
- <p>在一些文法中,Bison标准的<acronym>LALR</acronym>(1)分析算法,
- 不能针对给定的输入应用一个确定的语法规则.
- 这就是说,Bison可能不能决定(在当前输入的基础上)应该使用两个可能的归约中的那一个,
- 或者不能决定到底应该应用一个归约还是先读取一些输入稍后再进行归约.
- 以上两种冲突分别被称为<em>归约/归约(reduce/reduce)</em>冲突(参阅<a href="#SEC92">归约/归约-Reduce/Reduce</a>一章)和
- <em>移进/归约(shift/reduce)</em>冲突(参阅<a href="#SEC84">移进/归约-Shift/Reduce</a>一章).
- </p>
- <p>有些时候,
- 为了使用一个很难被修改成<acronym>LALR</acronym>(1)文法的文法做为Bison的输入,
- Bison需要使用通用的分析算法.
- 如果你在你的文件中加入了这样的声明<code>%glr-parser</code>(参阅<a href="#SEC43">语法大纲-Grammar Outline</a>一章),
- Bison会产通用的<acronym>LR</acronym>(<acronym>GLR</acronym>)分析器.
- 这些分析器(例如,在应用了先前所述的声明之后)
- 在处理那些不包含未解决的冲突的文法时,
- 采用与<acronym>LALR</acronym>(1)分析器一样的处理方式.
- 但是当面临未解决的移进/归约冲突和归约/归约冲突的时候,
- <acronym>GLR</acronym>分析器权宜地同时处理这两个可能,
- 即有效地克隆分析器自己以便于追踪这这两种可能性.
- 每一个克隆出来的分析器还可以再次被克隆,
- 这就保证在任意给定的时间,可以处理任意个可能的分析.
- 分析器逐步地进行分析,即所有的分析器它们进入到下一个输入之前,
- 都会消耗(归约)给定的输入符号.
- 每一个被克隆的分析器最终只有两个可能的归宿:
- 或者这个分析器因进入了一个分析错误而最终被销毁,
- 会这它和其它的分析器合并,因为它们把输入归约到了一个相同的符号集.
- </p>
- <p>在有多个分析器并存的时刻,Bison只记录它们的语义动作而不是执行它们.
- 当一个分析器消失的时候,相应的语义动作记录也消失并且永远不会被执行.
- 当一个规约使得两个分析器等价而合并的时候,
- Bison会记录下它们两个的语义动作集.
- 每当最后两个分析器合并成为一个单独的分析器的时候,
- Bison执行所有未完成的动作.这些动作既可能依靠语法规则的优先级被执行也可能均被Bison执行.
- 在执行完动作之后,Bison调用指定的用户定义求值函数来产生一个独立的合并值.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC12">1.5.1 使用<acronym>GLR</acronym>分析器分析非歧义文法</a></td><td> </td><td align="left" valign="top"></td></tr>
- <tr><td align="left" valign="top"><a href="#SEC13">1.5.2 使用<acronym>GLR</acronym>解决歧义-Using <acronym>GLR</acronym> to Resolve Ambiguities</a></td><td> </td><td align="left" valign="top"> 使用<acronym>GLR</acronym>分析器解决歧义
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC14">1.5.3 编译<acronym>GLR</acronym>分析器时需要考虑的问题-Considerations when Compiling <acronym>GLR</acronym> Parsers</a></td><td> </td><td align="left" valign="top"> <acronym>GLR</acronym>分析器需要一个现代的C编译器
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Simple-GLR-Parsers"></a>
- <a name="SEC12"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC11"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC13"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC11"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t13"></a> 1.5.1 使用<acronym>GLR</acronym>分析器分析非歧义文法 </h3>
- <p>在最简单的情况下,你可以使用<acronym>GLR</acronym>算法分析那些非歧义但不是<acronym>LALR</acronym>(1)文法的文法.
- 典型地,这些文法需要不止一个的超前扫描记号,
- 或者(在极少数情况下)由于<acronym>LALR</acronym>(1)算法丢弃太多的信息
- 而不属于<acronym>LALR</acronym>(1)的文法(它们却属于<acronym>LR</acronym>(1),参阅<a href="#SEC93">冲突-Mystery Conflicts</a>).
- </p>
- <p>考虑一个产生于Pascal语言枚举和子界类型声明中的问题,.
- 这里有一些例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">type subrange = lo .. hi;
- type enum = (a, b, c);
- </pre></td></tr></tbody></table>
- <p>最初的语言标准只允许数字和常量标识符做为子界的范围(<samp>`lo'</samp>和<samp>`hi'</samp>).
- 但是扩展的Pascal(<acronym>ISO</acronym>/<acronym>IEC</acronym>10206)以及许多以它的Pascal的实现还允许独立的表达式.
- 这导致了如下一个包含过量括号的情形.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">type subrange = (a) .. b;
- </pre></td></tr></tbody></table>
- <p>考虑如下这个仅含一个值的枚举类型的声明.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">type enum = (a);
- </pre></td></tr></tbody></table>
- <p>(在这里的这些例子是人为制造的,但它们是语法有效的.
- 在实际的程序中可能会出现更复杂的例子)
- </p>
- <p>这两个例子看起来相同(注:指语法上)直到<samp>`..'</samp>记号的出现.
- 对于只含有一个超前扫描记号的普通<acronym>LALR</acronym>(1)分析,
- 当<samp>`a'</samp>被分析的时,分析器候并不能两个形式中(注:指枚举或者子界)那一个是正确的.
- 因为在后一个例子中,<samp>`a'</samp>必须成为一个新的标识符来表示枚举;
- 而在前一个例子中必须使用<samp>`a'</samp>和它的含义来估计它可能是一个常量或者函数调用,
- 所以我们当然希望分析器可以对此作出正确的决定.
- </p>
- <p>你可将<samp>`(a)'</samp>分析成"在括号中为说明的标识符"以便稍后进行分析.
- 但当括号嵌套在表达式的递归规则中的时候,
- 这种方式需要对语义动作和大部分语法做出相应的调整.
- </p>
- <p>你可能会想到使用词法分析器通过返回已定义和未定地标识符来区别这两种形式.
- 但是如果这些声明在局部出现,
- 而<samp>`a'</samp>在外部定义的时候,这两种形式都是可能的-
- 既可能是局部重定义的<samp>`a'</samp>.也可能是使用外部定义的<samp>`a'</samp>的值.
- 所以这种方法不可行.
- </p>
- <p>解决这个问题由一个简单的办法,那就是使用<acronym>GLR</acronym>算法.
- 当<acronym>GLR</acronym>分析器到达关键区域的时候,
- 它会同时沿着两个分支进行分析.
- 其中的一个分支迟早要进入分析错误.
- 如果有一个<samp>`..'</samp>记号在下一个<samp>`;'</samp>之前的化;
- 由于枚举类型的规则不能接受<samp>`..'</samp>,所以它应用失败;
- 否则,子界类型规则应用失败,因为它要求一个<samp>`..'</samp>记号.
- 所以,一个分支无声地失败而另一个分支正常地进行,
- 并且执行所有的在拆分期间被推迟执行的中间动作.
- </p>
- <p>如果输入不符和语法,则这两个分支的分析都会失败
- 并且如常地报告一个语法错误.
- </p>
- <p>分析器的功能似乎是在"猜测"正确的语法分支,换句话说,
- 它使用了比<acronym>LALR</acronym>(1)算法允许使用的更多的超前扫描记号.
- <acronym>LALR</acronym>(2)有能力分析这个句子,
- 但是有些不符和<acronym>LALR</acronym>(<em>k</em>)的例子,
- 即使任意多的<em>k</em>可以这样地处理.
- </p>
- <p>一般而言,一个<acronym>GLR</acronym>分析器在最坏情况下会花费二次方或者三次方的时间复杂度,
- 当前的Bison甚至会为了某些文法而花费指数的时间.
- 在实际应用中,这些几乎不会发生,
- 并且对于许多文法来说,证明它不能发生也是可能的.
- 当前讨论的例子在两个规则中只有一个冲突,
- 并且含有冲突的类型声明不能嵌套使用.
- 所以在任意时刻的分支数量被限制在常量2以下,
- 这时候分析时间仍然是线性的.
- </p>
- <p>这是一个同上面描述相对应的例子.
- 它由Pascal类型声明大大简化而来.
- 如果输入不符和语法,两个分支都会失败并且如常地报告一个语法错误.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%token TYPE DOTDOT ID
- %left '+' '-'
- %left '*' '/'
- %%
- type_decl : TYPE ID '=' type ';'
- ;
- type : '(' id_list ')'
- | expr DOTDOT expr
- ;
- id_list : ID
- | id_list ',' ID
- ;
- expr : '(' expr ')'
- | expr '+' expr
- | expr '-' expr
- | expr '*' expr
- | expr '/' expr
- | ID
- ;
- </pre></td></tr></tbody></table>
- <p>当使用平常的<acronym>LALR</acronym>(1)文法的时候,Bison会报告一个归约/归约冲突.
- 在冲突的时候,分析器在会众多选择中选取一个-随意地选择那个先声明的.
- 所以下面的正确输入不能被识别.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">type t = (a) .. b;
- </pre></td></tr></tbody></table>
- <p>在Bison输入文件中,
- 加入这两个声明(在第一个<samp>`%%'</samp>之前)分析器可以将分析器编成一个<acronym>GLR</acronym>分析器,
- 并且Bison不会报告一个归约/归约冲突.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%glr-parser
- %expect-rr 1
- </pre></td></tr></tbody></table>
- <p>并不需要对语法本身进行修改.
- 分析器现通过上面的限制语法后,可以认识所有有效的声明.
- 用户实际上并不能查觉分析器的拆分.
- </p>
- <p>这就是我们使用<acronym>GLR</acronym>而几乎没有坏处的例子.
- 即使像这样简单的例子,至少两个潜在的问题值得我们注意.
- 第一,我们总应该分析Bison的冲突报告来确定<acronym>GLR</acronym>拆分总发生在我们想要的时候.
- 一个<acronym>GLR</acronym>分析器的拆分会不经意地产生比<acronym>LALR</acronym>分析器在冲突中静态的错误选择
- 更加不明显的问题.
- 第二,要仔细考虑与词法分析器的互动(参阅<a href="#SEC98">语义记号-Sematic Tokens</a>一章).
- 由于在拆分期间的分析器消耗记号时并不产生任何动作,
- 词法分析器并不能通过分析动作获得信息.
- 一些与词法分析器的互动在使用<acronym>GLR</acronym>来消除从词法分析器到语法分析器的复杂读时可以忽略.
- 你必须监察其余情况下时的正确性.
- </p>
- <p>在我们的例子中,因为并没有新的符号在类型声明中间被定义.
- 词法分析器基于记号当前在符号表的含意被返回是安全的.
- 即使在分析枚举常量时定义它们是可能的,
- 由于它们不能在相同的枚举类型声明中使用,
- 所以这实际上并没有什么不同.
- </p>
- <hr size="6">
- <a name="Merging-GLR-Parses"></a>
- <a name="SEC13"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC12"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC14"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC11"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t14"></a> 1.5.2 使用<acronym>GLR</acronym>解决歧义-Using <acronym>GLR</acronym> to Resolve Ambiguities </h3>
- <p>让我们考虑由C++语法大大简化而来的例子.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%{
- #include <stdio.h>
- #define YYSTYPE char const *
- int yylex (void);
- void yyerror (char const *);
- %}
- %token TYPENAME ID
- %right '='
- %left '+'
- %glr-parser
- %%
- prog :
- | prog stmt { printf ("/n"); }
- ;
- stmt : expr ';' %dprec 1
- | decl %dprec 2
- ;
- expr : ID { printf ("%s ", $$); }
- | TYPENAME '(' expr ')'
- { printf ("%s <cast> ", $1); }
- | expr '+' expr { printf ("+ "); }
- | expr '=' expr { printf ("= "); }
- ;
- decl : TYPENAME declarator ';'
- { printf ("%s <declare> ", $1); }
- | TYPENAME declarator '=' expr ';'
- { printf ("%s <init-declare> ", $1); }
- ;
- declarator : ID { printf ("/"%s/" ", $1); }
- | '(' declarator ')'
- ;
- </pre></td></tr></tbody></table>
- <p>这个例子模拟了有问题的C++语法--某些声明和语句中的歧义.例如,
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">T (x) = y+z;
- </pre></td></tr></tbody></table>
- <p>既可以被分析为一个<code>expr</code>也可被分析为一个<code>stmt</code>
- (假定<samp>`T'</samp>被识别为一个<code>TYPENAME</code>并且<samp>`x'</samp>被识别为<code>ID</code>).
- Biosn检测到了这个在规则<code>expr : ID</code>和规则<code>delarator : ID</code>之间的归约/归约冲突.
- 分析器遇到<code>x</code>的时候还不能解决冲突.
- 由于这是一个<acronym>GLR</acronym>分析器,所以它会把问题拆分成两个分析器,
- 每一个用于解决归约/归约冲突中的一个.
- 与上一节的例子不同(参阅<a href="#SEC12">简单的GLR分析器</a>一章),两个分析器中的任一个都不"死亡,"
- 因为这个语法本身就是歧义的.
- 其中的一个分析最终归约到<code>stmt : expr ';'</code>而另一个归约到<code>stmt : decl</code>,
- 在这之后,两个分析器进入同一个状态: 它们都已经看到<samp>`prog stmt'</samp>并且有相同的未处理剩余输入.
- 我们说这些分析器已经<em>合并(merged)</em>.
- </p>
- <p>在这个时候,<acronym>GLR</acronym>分析器需要一个关于如何在两个竞争的分析中做出选择的说明.
- 在上面的例子中,两个<code>%dprec</code>声明说明了Bison给予<code>decl</code>的解释以优先级.
- 这就表明<code>x</code>是一个声明符(declarator).
- 因此分析器会打印出:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">"x" y z + T <init-declare>
- </pre></td></tr></tbody></table>
- <p><code>%deprc</code>声明仅在多于一个分析幸存的情况下起作用.
- 考虑这个分析器的一个不同的输入字符串:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">T (x) + y;
- </pre></td></tr></tbody></table>
- <p>像在上一节展示的一样(参阅<a href="#SEC12">简单的GLR分析器-Simple GLR Parsers</a>一章),
- 这是另外一个使用<acronym>GLR</acronym>分析非歧义结构的例子.
- 在这里并没有歧义(这个并不能被分析成一个声明).
- 但是在Bison分析器遇到<code>x</code>的时候,
- 它没有足够的信息解决归约/归约冲突(还是不能决定<code>x</code>是一个<code>expr</code>还是一个<code>declarator</code>).
- 在这种情况下,没有优先级可供使用.
- 分析器再次被拆分成两个,一个假定<code>x</code>是一个<code>expr</code>
- 而另一个假定<code>x</code>是一个<code>declarator</code>.
- 两个分析器中的第二个在遇到<code>+</code>的时候被销毁,并且分析器打印出
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">x T <cast> y +
- </pre></td></tr></tbody></table>
- <p>假设你想查看所有的可能性而不是解决歧义.
- 你必须合并两个可能的分析器的语义动作而不是选择其中的一个.
- 为了达到这个目的,你需要像如下那样地改变<code>stmt</code>的声明:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">stmt : expr ';' %merge <stmtMerge>
- | decl %merge <stmtMerge>
- ;
- </pre></td></tr></tbody></table>
- <p>并且定义<code>stmtMerge</code>函数如下:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">static YYSTYPE
- stmtMerge (YYSTYPE x0, YYSTYPE x1)
- {
- printf ("<OR> ");
- return "";
- }
- </pre></td></tr></tbody></table>
- <p>并且在文件的开头要伴随一个前置声明在C声明中:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%{
- #define YYSTYPE char const *
- static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);
- %}
- </pre></td></tr></tbody></table>
- <p>使用这些声明以后,产生的的分析器将第一个例子既分析成一个<code>expr</code>又分析成一个<code>decl</code>,
- 并且打印
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">"x" y z + T <init-declare> x T <cast> y z + = <OR>
- </pre></td></tr></tbody></table>
- <p>Bison要求所有参加任何特定合并的产品(productions)拥有相同的<samp>`%merge'</samp>语句.
- 否则,歧义不能被解决而且分析器会在任何导致违反规定的合并时候报告一个错误.
- </p>
- <hr size="6">
- <a name="Compiler-Requirements"></a>
- <a name="SEC14"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC13"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC15"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC11"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t15"></a> 1.5.3 编译<acronym>GLR</acronym>分析器时需要考虑的问题-Considerations when Compiling <acronym>GLR</acronym> Parsers </h3>
- <p><acronym>GLR</acronym>分析器需要支持C89或更新标准的编译器.
- 额外地,Bison使用关键字<code>inline</code>,这个关键字不是C89标准但却是C99标准,
- 并且是许多C99之前编译器支持的扩展.
- 使用它是为了分析器的用户可以处理移植性问题.
- 例如,如果使用Autoconf和Autoconf宏<code>AC_C_INLINE</code>,一个单单的
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%{
- #include <config.h>
- %}
- </pre></td></tr></tbody></table>
- <p>就足够用了,否则我们建议使用
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%{
- #if __STDC_VERSION__ < 199901 && ! defined __GNUC__ && ! defined inline
- #define inline
- #endif
- %}
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Locations-Overview"></a>
- <a name="SEC15"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC14"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC16"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC6"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t16"></a> 1.6 位置-Locations </h2>
- <p>许多应用程序,如解释器和编译器,需要产生一些有用信息或者出错的信息.
- 为了达到这个目的,我们必须追踪每个语法结构的<em>原文位置(textual location)</em>或<em>位置(location)</em>.
- Bison提供了追踪这些位置的机制.
- </p>
- <p>每一个记号有一个语义值.类似地,每个记号也有一个位置,
- 对于所有记号和组来说,它们的位置的类型是相同的.
- 此外,输出的分析器也带有默认的存储位置的数据结构
- (获取更多信息,参阅<a href="#SEC57">位置-Locations</a>一章).
- </p>
- <p>像语义值一样,位置可以在动作中使用特定的一套结构来访问.
- 在上面个的例子中,这个组的的位置是<code>@$</code>,而子表达式的位置是<code>@1</code>和<code>@3</code>.
- </p>
- <p>当一个规则被匹配,一个默认的动作用于计算左侧的语义值(参阅<a href="#SEC54">动作-Actions</a>一章).
- 类似地,另外一个默认的动作用于计算位置.
- 然而,这个默认动作对于对于大多数情况已经足够永,
- 即经常没有必要为每个规则描述<code>@$</code>应该是如何形成的.
- 当为一个给定的组建立一个新的位置的时候,
- 输出的分析器的默认行为是取第一个符号的开头和最后一个符号的末尾.
- </p>
- <hr size="6">
- <a name="Bison-Parser"></a>
- <a name="SEC16"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC15"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC17"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC6"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t17"></a> 1.7 Bison的输出:分析器文件-Bison Output: the Parser File </h2>
- <p>当你运行Bison的时候,你需要给Bison一个语法文件做为其输入.
- Bison的输出是一个分析这个语法文件描述的语言的C源代码文件.
- 这个文件叫做<em>Bison分析器(Bison parse)</em>.
- 我们要记住Bison工具和Bison分析器是两个明显不同的程序:
- Bison工具是一个以Bison分析器为输出的程序.
- 这个Bison分析器应是你程序的一部分.
- </p>
- <p>Bison分析器的工作是依照语法规则组合记号--例如,将标识符和操作符构建成表达式.
- 在组合的过程中它还要执行相应的语法规定的动作.
- </p>
- <p>记号是来源于称为<em>词法分析器(lexical analyzer)</em>的程序.
- 你必须以某种形式提供词法分析器(如用C编写).
- Bison分析器每当需要一个新的记号的时候就会调用词法分析器.
- Bison分析器并不之道记号"中"有什么东西(即使它们的语义值可能反映这个).
- 典型的词法分析器靠分析字符来产生记号,但是Bison并不依靠这个.
- 获取更多细节,参阅 <a href="#SEC75">词法分析函数<code>yylex</code>-The Lexical Analyzer Function <code>yylex</code></a>.
- </p>
- <p>Bison分析器文件是定义了名为<code>yyparse</code>并且实现了那个语法的函数的C代码.
- 这个函数并不能成为一个完成的C程序:你必须提供额外的一些函数.
- 其中之一是词法分析器.另外的一个是一个分析器报告错误时调用的错误报告函数.
- 另外,一个完整的C程序必须以名为<code>main</code>的函数开头;
- 你必须提供这个函数.并且安排它调用<code>yyparse</code>.
- 否则分析器永远都不会运行.
- 参阅 <a href="#SEC73">分析器C语言接口-Parser C-Language Interface</a>.
- </p>
- <p>除了你编写的动作中的记号类型名称和符号以外
- ,所有Bison分析器文件自己定义的符号都以<samp>`yy'</samp>或者<samp>`YY'</samp>开头.
- 这些符号包括了接口函数例如词法分析函数<code>yylex</code>,错误报告函数<code>yyerror</code>
- 和分析器函数<code>yyparse</code>.
- 这些符号也包括了许多内部目的的标识符.
- 所以你要在Bison语法文件中避免使用除了本手册定义的以外的以<samp>`yy'</samp>或者<samp>`YY'</samp>开头的C标识符.
- </p>
- <p>在一些情况下,Bison分析器文件包含系统头文件.
- 在这中情况下,你的代码注意被这些文件保留的标识符.
- 在意些非<acronym>GNU</acronym>系统,<code><alloca.h></code>,<code><stddef.h></code>以及<code><stdlib.h></code>
- 被包含在内用于声明内存分配器及相关类型.
- 如果你定义<code>YYDEBUG</code>为非零值,其它的系统头文件也可能被包括进内.
- (参阅<a href="#SEC103">跟踪你的分析器-Tracing Your Parser</a>一章)
- </p>
- <hr size="6">
- <a name="Stages"></a>
- <a name="SEC17"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC16"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC18"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC6"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t18"></a> 1.8 使用Bison的流程-Stages in Using Bison </h2>
- <p>实际使用Bison设计语言的流程,从语法描述到编写一个编译器或者解释器,有三个步骤:
- </p>
- <ol>
- <li>
- 以Bison可识别的格式正式地描述语法.(参阅<a href="#SEC42">Bison语法文件</a>一章)
- 对每一个语法规则,描述当这个规则被识别时相应的执行动作.
- 动作由C语句序列描述.
- </li><li>
- 编写一个词法分析器处理输入并将记号传递给语法分析器.
- 词法分析器既可是手工编写的C代码(参阅<a href="#SEC75">词法分析函数<code>yylex</code></a>一章),
- 也可以由lex产生,但是lex的使用并未在这个手册中讨论.
- </li><li>
- 编写一个调用Bison产生的分析器的控制函数.
- </li><li>
- 编写错误报告函数.
- </li></ol>
- <p>将这些源代码转换成可执行程序,你需要按以下步骤进行.
- </p>
- <ol>
- <li>
- 按语法运行Bison产生分析器.
- </li><li>
- 同其它源代码一样编译Bison输出的代码.
- </li><li>
- 链接目标文件以产生最终的产品.
- </li></ol>
- <hr size="6">
- <a name="Grammar-Layout"></a>
- <a name="SEC18"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC17"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC19"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC6"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC19"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t19"></a> 1.9 Bison语法文件的整体布局-The Overall Layout of a Bison Grammar </h2>
- <p>Bison工具的输入文件是以个<em>Bison语法文件(Bison grammar file)</em>.
- 通常的Bison语法文件格式如下:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%{
- <var>Prologue</var>
- %}
- <var>Bison declarations</var>
- %%
- <var>Grammar rules</var>
- %%
- <var>Epilogue</var>
- </pre></td></tr></tbody></table>
- <p><samp>`%%'</samp>,<samp>`%{'</samp> 和<samp>`%}'</samp>是Bison在每个Bison语法文件中用于分隔部分的标点符号.
- </p>
- <p><var>prologue</var>可用来定义在动作中使用类型和变量.
- 你可以使用预处理器命令在那里来定义宏,
- 或者使用<code>#include</code>包含干这些事情的头文件.
- 你需要声在那里与许多要在语法规则的动总中使用的全局标识符一起
- 声明词法分析器<code>yylex</code>和错误打印程序<code>yyerror</code>.
- </p>
- <p><var>Bison declarations</var>声明了终结符和非终结符以及操作符的优先级和各种符号语义值的各种类型.
- </p>
- <p><var>Grammar rules</var>定义了如何从每一个非终结符的部分构建其整体的语法规则.
- </p>
- <p><var>Epilogue</var>可以包括任何你想使用的代码.
- 在<var>Prologue</var>中声明的函数经常定义在这里.
- 在简单的程序里,剩余的所有程序可以放在这里.
- </p>
- <hr size="6">
- <a name="Examples"></a>
- <a name="SEC19"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC18"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC20"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC6"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="chapter"><a name="t20"></a> 2. 实例-Examples </h1>
- <p>现在开始我们展示并解释三个使用Bison编写的示范程序:
- 一个逆波兰记号计算器,一个代数符号(中缀)计算器和一个多功能计算器.
- 这些程序在BSD Unix 4.3上测试无误;它们每一个虽然功能有限,
- 但确都是实用的互动桌面计算器.
- </p>
- <p>这些例子虽然简单,但是用Bison语法编写真正的程序设计语言的道理与这相同.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC20">2.1 逆波兰记号计算器-Reverse Polish Notation Calculator</a></td><td> </td><td align="left" valign="top"> 逆波兰记号计算器,我们的第一个例子,并不带有操作符优先级
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC31">2.2 中缀符号计算器:<code>calc</code>-Infix Notation Calculator: <code>calc</code></a></td><td> </td><td align="left" valign="top"> 中缀代数符号计算器,简单地介绍操作符优先级.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC32">2.3 简单的错误恢复-Simple Error Recovery</a></td><td> </td><td align="left" valign="top"> 在出现语法错误后继续分析
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC33">2.4 带有位置追踪的计算器:<code>ltcalc</code>-Location Tracking Calculator: <code>ltcalc</code></a></td><td> </td><td align="left" valign="top"> 展示@<var>n</var>和@$的用法
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC37">2.5 多功能计算器:<code>mfcalc</code>-Multi-Function Calculator: <code>mfcalc</code></a></td><td> </td><td align="left" valign="top"> 带有存储和触发功能的计算器.它使用了多种数据类型来表示语义值.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC41">2.6 练习-Exercises</a></td><td> </td><td align="left" valign="top"> 一些改进多功能计算器的方案
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="RPN-Calc"></a>
- <a name="SEC20"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC19"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC21"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC19"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t21"></a> 2.1 逆波兰记号计算器-Reverse Polish Notation Calculator </h2>
- <p>我们的第一个例子是双精度<em>逆波兰记号(reverse polish notation)</em>计算器(一个使用后缀操作符的计算器).
- 这个例子是一个很好的起点,因为没有操作符优先级的问题.
- 第二个例子会说明如何处理运算符优先级.
- </p>
- <p>这个计算器的源代码文件叫<tt>`rpcalc.y'</tt>.
- <samp>`.y'</samp>是Bison惯用的输入文件的扩展名.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC21">2.1.1 <code>rpclac</code>的声明部分-Declarations for <code>rpcalc</code></a></td><td> </td><td align="left" valign="top"> rpclac的Prologue(声明)部分.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC22">2.1.2 <code>rpcalc</code>的语法规则-Grammar Rules for <code>rpcalc</code></a></td><td> </td><td align="left" valign="top"> 带注释的rpcalc语法规则
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC26">2.1.3 <code>rpcalc</code>的词法分析器-The <code>rpcalc</code> Lexical Analyzer</a></td><td> </td><td align="left" valign="top"> 词法分析器
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC27">2.1.4 控制函数-The Controlling Function</a></td><td> </td><td align="left" valign="top"> 控制函数
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC28">2.1.5 错误报告的规则-The Error Reporting Routine</a></td><td> </td><td align="left" valign="top"> 错误报告的规则
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC29">2.1.6 运行Bison来产生分析器-Running Bison to Make the Parser</a></td><td> </td><td align="left" valign="top"> 使用Bison生成分析器
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC30">2.1.7 编译分析器文件-Compiling the Parser File</a></td><td> </td><td align="left" valign="top"> 使用C编译器编译得到最终结果
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Rpcalc-Decls"></a>
- <a name="SEC21"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC20"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC22"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC20"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t22"></a> 2.1.1 <code>rpclac</code>的声明部分-Declarations for <code>rpcalc</code> </h3>
- <p>这就是逆波兰记号计算器的C和Bison声明部分.
- 像C语言一样,注释部分在<samp>`/*…*/'</samp>中.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">/* Reverse polish notation calculator. */
- /* 逆波兰记号计算器 */
- %{
- #define YYSTYPE double
- #include <math.h>
- int yylex (void);
- void yyerror (char const *);
- %}
- %token NUM
- %% /* Grammar rules and actions follow. */
- </pre></td></tr></tbody></table>
- <p>声明部分(参阅<a href="#SEC44"><var>Prologue</var>部分-The prologue</a>一章)包括了两个预处理指令和两个前置声明.
- </p>
- <p><code>#define</code>指令定义了<code>YYSTYPE</code>宏,
- 它指明了记号和组(参阅<a href="#SEC52">语义值的数据类型-Data Types of Semantic Values</a>一章)语义值的C数据类型.
- Bison分析器会使用任何<code>YYSTYPE</code>定义的数据类型;
- 如果你没有定义它,<code>int</code>则是默认的类型.
- 因为我们指明了<code>double</code>,所以每个记号和表达式已经关联了一个浮点数值.
- </p>
- <p><code>#include</code>用来声明幂函数<code>pow</code>.
- </p>
- <p>由于C语言要求函数必须在使用之前声明,
- 所以前置声明<code>yylex</code>和<code>yyerror</code>是必须的.
- 这些函数将在<var>epilogue</var>部分定义,但是分析器会调用它们,
- 所以它们必须在<var>prologue</var>部分声明.
- </p>
- <p>第二部分-<var>Bison declarations</var>,提供了有关记号类型的信息(参阅<a href="#SEC45"><var>Bison Declarations</var>部分-The Bison Declarations Section</a>一章).
- 每一个不只一个字符组成的终结符必须在这里声明.(通常没有必要声明单一字符.)
- 在这个例子中,所有的算术操作符都是单一字符的,
- 所以我们在这里仅需要声明的终结符是<code>NUM</code>--数字常量的记号类型.
- </p>
- <hr size="6">
- <a name="Rpcalc-Rules"></a>
- <a name="SEC22"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC21"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC23"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC20"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t23"></a> 2.1.2 <code>rpcalc</code>的语法规则-Grammar Rules for <code>rpcalc</code> </h3>
- <p>这就是逆波兰记号计算器的语法规则:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">input: /* empty */
- | input line
- ;
- line: '/n'
- | exp '/n' { printf ("/t%.10g/n", $1); }
- ;
- exp: NUM { $$ = $1; }
- | exp exp '+' { $$ = $1 + $2; }
- | exp exp '-' { $$ = $1 - $2; }
- | exp exp '*' { $$ = $1 * $2; }
- | exp exp '/' { $$ = $1 / $2; }
- /* Exponentiation */
- | exp exp '^' { $$ = pow ($1, $2); }
- /* Unary minus */
- | exp 'n' { $$ = -$1; }
- ;
- %%
- </pre></td></tr></tbody></table>
- <p>在这里定义的rpcalc"语言"的组是:表达式(名称是<code>exp</code>),
- 输入行(<code>line</code>),整个的输入脚本(<code>input)</code>.
- 这些非终结符每个都有多个可选择的规则.
- 这些规则由<samp>`|'</samp>连接而成.
- 我们可以把<samp>`|'</samp>读做"或者".
- 接下来的部分解释了规则的含义.
- </p>
- <p>语法的语义由当组组被识别时执行的动作决定.
- 动作由在大括号中C代码组成.
- 参阅<a href="#SEC54">动作-Actions</a>一章.
- </p>
- <p>你必须用C语言来指定这些动作,
- 但是Bison也提供了在规则之间传递语义值的方法.
- 在每个动作中,伪变量<code>$$</code>代表着将要构建的组的语义值.
- 赋值给<code>$$</code>是大多数动作的工作.
- 规则的组成部分的语义值由<code>$1</code>,<code>$2</code>等等指定.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC23">2.1.2.1 解释<code>input</code>-Explanation of <code>input</code></a></td><td> </td><td align="left" valign="top">
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC24">2.1.2.2 解释<code>line</code>-Explanation of <code>line</code></a></td><td> </td><td align="left" valign="top">
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC25">2.1.2.3 解释<code>expr</code>-Explanation of <code>expr</code></a></td><td> </td><td align="left" valign="top">
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Rpcalc-Input"></a>
- <a name="SEC23"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC22"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC24"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC22"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h4 class="subsubsection"><a name="t24"></a> 2.1.2.1 解释<code>input</code>-Explanation of <code>input</code> </h4>
- <p>考虑<code>input</code>的定义:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">input: /* empty */
- | input line
- ;
- </pre></td></tr></tbody></table>
- <p>这个定义可以被解释为:"一个完整的输入己可能是一个空字符串,
- 也可能是一个完整输入后紧跟一个输入行".
- 我们应该注意到"完整输入"定义在它自己的条款中.
- 由于<code>input</code>总是出现在符号序列的最左端,
- 我们称这种定义为<em>左递归(left recursive)</em>.
- (参阅 <a href="#SEC50">递归规则-Recursive Rule</a>.)
- </p>
- <p>第一个可选择的规则为空是由于在冒号和第一个<samp>`|'</samp>之间没有任何符号;
- 这意味着<code>input</code>可以匹配一个空字符串的输入(没有符号).
- 我们这样编写规则是因为在你启动计算器后,在右端输入<kbd>Ctrl-d</kbd>是合法的.
- 把空规则放在最开始并伴随注释<samp>`/* empty */'</samp>是使用惯例.
- </p>
- <p>第二个可选的规则(<code>input line</code>)处理了所有非平凡的输入.
- 它的含义是"在读取任意个数的line后,如果可能的化读取更多的line."
- 作递归使得这个规则进入循环.
- 由于第一个可选的规则与空输入匹配,循环可能被执行零次或多次.
- </p>
- <p>分析器函数<code>yyparse</code>继续处理输入直到发现一个语法错误或者
- 词法分析器表明没有更多的输入记号为止;
- 我们会安排后者在输入结束的时候发生.
- </p>
- <hr size="6">
- <a name="Rpcalc-Line"></a>
- <a name="SEC24"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC23"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC25"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC22"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h4 class="subsubsection"><a name="t25"></a> 2.1.2.2 解释<code>line</code>-Explanation of <code>line</code> </h4>
- <p>现在我们考虑<code>line</code>的定义:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">line: '/n'
- | exp '/n' { printf ("/t%.10g/n", $1); }
- ;
- </pre></td></tr></tbody></table>
- <p>第一个选择是一个换行符号;
- 这意味着rpcalc接受一个空白行(并且忽略它,因为没有相关的动作).
- 第二个选择是一个表达式后紧跟着一个换行符.
- 这个选择使得rpcalc变得实用.
- <code>$1</code>的值是<code>exp</code>组的语义值,
- 这是因为<code>exp</code>是诸多选择中的第一个符号.
- 这个值就是用户需要的计算结果.
- 相关的动作打印了这个这个值.
- </p>
- <p>这个动作非同寻常,因为它并没有向<code>$$</code>赋值.
- 这样做的结果就是与<code>line</code>相关联的语义值并未被初始化(它的值是不可预期的).
- 如果那个值被使用的话,这会成为一个bug,但是我们并未使用它.
- rpcalc一旦已经打印了用户输入行的值,就不再需要那个值了.
- </p>
- <hr size="6">
- <a name="Rpcalc-Expr"></a>
- <a name="SEC25"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC24"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC26"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC22"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h4 class="subsubsection"><a name="t26"></a> 2.1.2.3 解释<code>expr</code>-Explanation of <code>expr</code> </h4>
- <p><code>exp</code>组有很多规则,每一个都是一种表达式.
- 第一个规则处理最简单的表达式:仅仅是数字的表达式.
- 第二个处理看起来像两个表达式后紧跟一个假发符号的加法表达式.
- 第三个处理减法等等.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp: NUM
- | exp exp '+' { $$ = $1 + $2; }
- | exp exp '-' { $$ = $1 - $2; }
- …
- ;
- </pre></td></tr></tbody></table>
- <p>我们已经使用<samp>`|'</samp>将<code>exp</code>的规则连接起来.
- 但是我们也可以将它们分开来写:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp: NUM ;
- exp: exp exp '+' { $$ = $1 + $2; } ;
- exp: exp exp '-' { $$ = $1 - $2; } ;
- …
- </pre></td></tr></tbody></table>
- <p>大部分规则都有从其部分值来计算表达式值的动作.
- 例如,在加法的规则中,<code>$1</code>指的是第一个部件<code>exp</code>,
- 而<code>$2</code>指的是第二个部件.
- 第三个部件<code>'+'并没有相关联的语义值.
- 但是如果它有语义值的话,你可以用<code>$3</code>来代表.
- 当<code>yyparse</code>使用这个规则识别了一个加法和表达式,
- 两个自表达式值的相加而得到了整个表达是的值.
- 参阅 <a href="#SEC54">动作-Actions</a>.
- </p>
- <p>你不必为每一个规则都指定动作.
- 当一个规则没有动作时,Bison会默认地将<code>$1</code>的值复制给<code>$$</code>.
- 这就是在第一规则被(使用<code>NUM</code>的规则)识别时发生的事情.
- </p>
- <p>在这里展示的是推荐的惯用格式,
- 但是Bison并没有要求一定要这么做.
- 你可以增加或者更改任意你想要的数量的空白.
- 例如,这个:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp : NUM | exp exp '+' {$$ = $1 + $2; } | … ;
- </pre></td></tr></tbody></table>
- <p>与这个的意义相同
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp: NUM
- | exp exp '+' { $$ = $1 + $2; }
- | …
- ;
- </pre></td></tr></tbody></table>
- <p>然而,后一种写法明显更可读.
- </p>
- <hr size="6">
- <a name="Rpcalc-Lexer"></a>
- <a name="SEC26"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC25"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC27"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC20"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t27"></a> 2.1.3 <code>rpcalc</code>的词法分析器-The <code>rpcalc</code> Lexical Analyzer </h3>
- <p>词法分析器的工作是低级别的分析:
- 将字符或者字符序列转化成记号.
- Bison分析器靠调用词法分析器来获取它的记号.
- 参阅 <a href="#SEC75">词法分析函数<code>yylex</code>-The Lexical Analyzer Function <code>yylex</code></a>.
- </p>
- <p>即使最简单的词法分析器也是<acronym>RPN</acronym>计算器所必须的.
- 这个词法分析器跳过了空白和制表符,
- 然后将数字读取为<code>double</code>并且以<code>NUM</code>记号返回它们.
- 任何不是数字的字符都是一个分隔记号.
- 注意到一个单个字符的记号是这个字符本身.
- </p>
- <p>词法分析器的返回值是一个代表记号类型的数字码.
- 相同的文字(在Biosn规则中使用,代表这个记号类型)
- 也是一个代表这个类型数字码的C表达式.
- 它以两种方式工作.
- 如果记号类型是一个字符,那么它的数字码就是那个字符;
- 你可以在词法分析器中使用相同字符表达那个数字码.
- 如果记号类型是一个标识符,
- 那个标识符是一个由Bison定义为一个恰当的数字的宏,
- 因此在这个例子中,<code>NUM</code>是一个给<code>yylex</code>使用的宏.
- </p>
- <p>记号的语义值(如果有的话)被存储在全局变量<code>yylval</code>中.
- Bison分析器会在需要语义值适当的时候找到它.
- (<code>yylval</code>的C数据类是<code>YYSTYPE</code>,它在语法的开始被定义;
- 参阅<a href="#SEC21"><code>rpcalc</code>的声明部分-Declarations for <code>rpcals</code></a>一章.
- </p>
- <p>符号类型码0在输入结束的时候被返回.
- (Bison将任何不正确的值识别为输入结束)
- </p>
- <p>这就是词法分析器的代码:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">/* The lexical analyzer returns a double floating point
- number on the stack and the token NUM, or the numeric code
- of the character read if not a number. It skips all blanks
- and tabs, and returns 0 for end-of-input. */
- /* 词法分析起在栈上返回一个双精度浮点数(注:指yylval)并且返回记号NUM,
- 或者返回不是数字的字符的数字码.它跳过所有的空白和制表符,
- 并且返回0作为输入的结束. */
- #include <ctype.h>
- int
- yylex (void)
- {
- int c;
- /* Skip white space. */
- /* 处理空白. */
- while ((c = getchar ()) == ' ' || c == '/t')
- ;
- /* Process numbers. */
- /* 处理数字 */
- if (c == '.' || isdigit (c))
- {
- ungetc (c, stdin);
- scanf ("%lf", &yylval);
- return NUM;
- }
- /* Return end-of-input. */
- /* 返回输入结束 */
- if (c == EOF)
- return 0;
- /* Return a single char. */
- /* 返回一个单一字符 */
- return c;
- }
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Rpcalc-Main"></a>
- <a name="SEC27"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC26"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC28"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC20"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t28"></a> 2.1.4 控制函数-The Controlling Function </h3>
- <p>为了保证这个例子的精巧,控制函数也保持了最小化。
- 它仅仅要求调用<code>yyparse</code>来开始分析的处理.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int
- main (void)
- {
- return yyparse ();
- }
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Rpcalc-Error"></a>
- <a name="SEC28"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC27"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC29"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC20"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t29"></a> 2.1.5 错误报告的规则-The Error Reporting Routine </h3>
- <p>当<code>yyparse</code>侦测到语法错误的时候,
- 它会调用错误报告函数<code>yyerror</code>来打印一个错误信息(经常但不总是<code>"syntax error"</code>).
- <code>yyparse</code>需要程序员来提供<code>yyerror</code>(参阅<a href="#SEC73">分析器C语言接口-Parser C-Language Interface</a>一章),
- 所我我们使用这样的定义:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">#include <stdio.h>
- /* Called by yyparse on error. */
- void
- yyerror (char const *s)
- {
- fprintf (stderr, "%s/n", s);
- }
- </pre></td></tr></tbody></table>
- <p>在<code>yyerror</code>返回之后,
- 如果语法包括了适当的错误规则(参阅<a href="#SEC96">错误恢复-Error Recovery</a>一章)
- Bison分析器可以从错误中恢复并且继续分析.
- 否则,<code>yyparse</code>返回非零值.
- 我们在这个例子中并没有编写任何错误规则,
- 所以任何无效的输入会导致计算器程序退出.
- 这种做法显然对于这正的计算器是不够用的,
- 但是足够用于这个例子.
- </p>
- <hr size="6">
- <a name="Rpcalc-Gen"></a>
- <a name="SEC29"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC28"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC30"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC20"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t30"></a> 2.1.6 运行Bison来产生分析器-Running Bison to Make the Parser </h3>
- <p>(参阅<a href="#SEC18">Bison语法文件的布局-The Overall Layout of a Bison Grammar</a>一章).
- 在运行Bison制造分析器之前,我们要决定如何把源代码安排在一个或多个源文件中.
- 对于这样一个简单的例子来说,
- 最简单的方法就是把所有的东西放到一个文件中.
- <code>yylex</code>,<code>yyerror</code>和<code>main</code>放在末尾的<var>epilogue</var>部分中.
- </p>
- <p>对于一个大工程来说,你可能会有很多的源代码文件,
- 这时候你需要使用<code>make</code>安排它们的重编译.
- </p>
- <p>因为所有的代码都在一个文件中,
- 你使用下面的命令将它转化成一个分析器文件:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">bison <var>file_name</var>.y
- </pre></td></tr></tbody></table>
- <p>在这个例子中,这个文件是<tt>`rpcalc.y'</tt>(代表 "Reverse Polish <small>CALC</small>ulator").
- Bison产生一个名为<tt>`<var>file_name</var>.tab.c'</tt>的文件.
- 并且将原文件的<samp>`.y'</samp>的扩展名移去.
- 在输入中的额外函数(<code>yylex</code>,<code>yyerror</code>和<code>main</code>)被逐字地复制到输出文件.
- </p>
- <hr size="6">
- <a name="Rpcalc-Compile"></a>
- <a name="SEC30"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC29"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC31"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC20"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t31"></a> 2.1.7 编译分析器文件-Compiling the Parser File </h3>
- <p>这就是如何编译并运行分析器文件:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example"># 列出当前目录的文件.
- $ <kbd>ls</kbd>
- rpcalc.tab.c rpcalc.y
- # 编译Bison分析器.
- # <samp>`-lm'</samp> 告诉编译器搜索与<code>pow</code>匹配的库.
- $ <kbd>cc -lm -o rpcalc rpcalc.tab.c</kbd>
- # 再次列文件.
- $ <kbd>ls</kbd>
- rpcalc rpcalc.tab.c rpcalc.y
- </pre></td></tr></tbody></table>
- <p>文件<tt>`rpcalc'</tt>现在已经包含了可执行代码.
- 这就是使用<code>rpcalc</code>的会话的例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">$ <kbd>rpcalc</kbd>
- <kbd>4 9 +</kbd>
- 13
- <kbd>3 7 + 3 4 5 *+-</kbd>
- -13
- <kbd>3 7 + 3 4 5 * + - n</kbd> 注意负号操作符, <samp>`n'</samp>
- 13
- <kbd>5 6 / 4 n +</kbd>
- -3.166666667
- <kbd>3 4 ^</kbd> 幂运算
- 81
- <kbd>^D</kbd> 文件结束标识符
- $
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Infix-Calc"></a>
- <a name="SEC31"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC30"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC32"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC19"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t32"></a> 2.2 中缀符号计算器:<code>calc</code>-Infix Notation Calculator: <code>calc</code> </h2>
- <p>现在我们可以通过修改rpcalc使其处理中缀操作符.
- 中缀操作符涉及到了操作符优先级的概念以及任意深度的括号嵌套.
- 这里是<tt>`calc.y'</tt>,一个中缀桌面计算器的代码.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">/* Infix notation calculator. */
- /* 中缀符号计算器 */
- %{
- #define YYSTYPE double
- #include <math.h>
- #include <stdio.h>
- int yylex (void);
- void yyerror (char const *);
- %}
- /* Bison declarations. */
- %token NUM
- %left '-' '+'
- %left '*' '/'
- %left NEG /* negation--unary minus */ /* 负号 */
- %right '^' /* exponentiation */ /* 幂运算 */
- %% /* The grammar follows. */ /* 下面是语法 */
- input: /* empty */
- | input line
- ;
- line: '/n'
- | exp '/n' { printf ("/t%.10g/n", $1); }
- ;
- exp: NUM { $$ = $1; }
- | exp '+' exp { $$ = $1 + $3; }
- | exp '-' exp { $$ = $1 - $3; }
- | exp '*' exp { $$ = $1 * $3; }
- | exp '/' exp { $$ = $1 / $3; }
- | '-' exp %prec NEG { $$ = -$2; }
- | exp '^' exp { $$ = pow ($1, $3); }
- | '(' exp ')' { $$ = $2; }
- ;
- %%
- </pre></td></tr></tbody></table>
- <p><code>yylex</code>,<code>yyerror</code>和<code>main</code>可以与上一个例子一样.
- </p>
- <p>这段代码展示了两个重要的新特征.
- </p>
- <p>在第二部分中(<var>Bison declarations</var>),
- <code>%left</code>声明了记号类型并且指明它们是左结合操作符.
- <code>%left</code>和<code>%right</code>(右结合)的声明代替了<code>%token</code>.
- <code>%token</code>是用来声明没有结合性的记号类型的.
- (这些记号(注:是指<samp>`'+''</samp>,<samp>`'-''</samp>,<samp>`'*''</samp>,<samp>`'/''</samp>,<samp>`'NEG''</samp>)
- 是原本并不用声明的单字符记号.我们声明它们的目的是指出它们的结合性.)
- </p>
- <p>操作符优先级是由声明所在行的顺序决定的.
- 行号越大的操作符(在一页或者屏幕底端)具有越高的优先级.
- 因此,幂运算具有最高优先级,负号(<code>NEG</code>)其次,
- 接这是<samp>`*'</samp>和<samp>`/'</samp>等等.
- 参阅 <a href="#SEC85">操作符优先级-Operator Precedence</a>.
- </p>
- <p>另外一个重要的特征是在语法部分的负号操作符中使用了<code>%prec</code>.
- 语法中的<code>%prec</code>只是简单的告诉Bison规则<samp>`| '-' exp'</samp>与<code>NEG</code>有相同的优先级--在前述的优先级规则中.
- 参阅 <a href="#SEC90">依赖上下文的优先级-Context-Dependent Precedence</a>.
- </p>
- <p>这就是一个运行<tt>`calc.y'</tt>的例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">$ <kbd>calc</kbd>
- <kbd>4 + 4.5 - (34/(8*3+-3))</kbd>
- 6.880952381
- <kbd>-56 + 2</kbd>
- -54
- <kbd>3 ^ 2</kbd>
- 9
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Simple-Error-Recovery"></a>
- <a name="SEC32"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC31"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC33"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC19"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t33"></a> 2.3 简单的错误恢复-Simple Error Recovery </h2>
- <p>直到这一章之前,这个手册并未提及<em>错误恢复(error recovery)</em>的内容--
- 即在分析器侦测到错误之后如何继续分析.
- 所有我们需要做的事情就是编写<code>yyerror</code>函数.
- 我们可以回忆一下以前的例子,
- <code>yyparse</code>在调用<code>yyerror</code>后返回.
- 这就意味着任一个错误的输入会导致计算机程序的退出.
- 现在我们就展示如何改正这个不足.
- </p>
- <p>Bison语言自己包括了可以插入到语法规则中去的保留字<code>error</code>.
- 在这个例子中,它被添加到<code>line</code>的一个可选的规则中.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">line: '/n'
- | exp '/n' { printf ("/t%.10g/n", $1); }
- | error '/n' { yyerrok; }
- ;
- </pre></td></tr></tbody></table>
- <p>这个添加的规则允许在语法错误发生的时候有简单的错误恢复动作.
- 如果一个读入一个无法求值的表达式,
- 这个错误会被识别成<code>line</code>的第三个规则并且分析会继续执行.
- (<code>yyerror</code>函数仍会被调用来打印它的信息).
- 执行这个动作的语句<code>yyerrok</code>是一个被Bison自动定义的宏.
- 它的含义是错误恢复已经完成(参阅<a href="#SEC96">错误恢复-Error Recovery</a>一章).
- 我们应当注意到<code>yyerror</code>和<code>yyerrok</code>的区别,
- 它们的印刷都没有错误.
- </p>
- <p>这种形式的错误恢复用于处理语法错误.
- 还有很多其它形式的错误;
- 例如,除数为0,这会产生一个通常致命的异常信号(an exception signal).
- 一个真正的计算器必须处理这种信号并且使用<code>longjmp</code>返回到<code>main</code>并且继续分析输入行;
- 它(注:真正的计算器)也可以丢弃剩余的输入行.
- 我们并不深入地讨论这个问题,
- 因为这与Bison程序无关.
- </p>
- <hr size="6">
- <a name="Location-Tracking-Calc"></a>
- <a name="SEC33"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC32"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC34"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC19"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t34"></a> 2.4 带有位置追踪的计算器:<code>ltcalc</code>-Location Tracking Calculator: <code>ltcalc</code> </h2>
- <p>这个例子将中缀符号计算器扩展以使其带有位置追踪功能.
- 这个特征将被应用于改进错误消息的显示.
- 为了把保持简洁性,
- 这个例子是一个简单的整数计算器.
- 为了使用位置,大多数工作将在词法分析器中完成.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC34">2.4.1 <code>ltcalc</code>的<var>Declarations</var>-Declarations for <code>ltcalc</code></a></td><td> </td><td align="left" valign="top"> ltcalc的Bison和C语言的声明
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC35">2.4.2 <code>ltcalc</code>的语法规则-Grammar Rules for <code>ltcalc</code></a></td><td> </td><td align="left" valign="top"> 详细解释ltcalc的语法规则
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC36">2.4.3 <code>ltcalc</code>的词法分析器-The <code>ltcalc</code> Lexical Analyzer.</a></td><td> </td><td align="left" valign="top"> 词法分析器
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Ltcalc-Decls"></a>
- <a name="SEC34"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC33"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC35"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC33"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t35"></a> 2.4.1 <code>ltcalc</code>的<var>Declarations</var>-Declarations for <code>ltcalc</code> </h3>
- <p>位置追踪计算器的C和Bison声明部分与中缀符号计算器的声明部分相同.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">/* Location tracking calculator. */
- /* 位置追踪计算器 */
- %{
- #define YYSTYPE int
- #include <math.h>
- int yylex (void);
- void yyerror (char const *);
- %}
- /* Bison declarations. */
- /* Bison 声明 */
- %token NUM
- %left '-' '+'
- %left '*' '/'
- %left NEG
- %right '^'
- %% /* The grammar follows. */ /* 下面是语法 */
- </pre></td></tr></tbody></table>
- <p>注意到并没有位置的特别声明.
- 并不需要定义一个存储位置的数据类型:
- 我们使用Bison提供的默认的类型(参阅<a href="#SEC58">位置的数据类型-Data Types of Locations</a>一章).
- 这种数据类型是带有四个整数域的结构体:
- <code>first_line</code>,<code>first_column</code>,<code>last_line</code>和<code>last_column</code>.
- </p>
- <hr size="6">
- <a name="Ltcalc-Rules"></a>
- <a name="SEC35"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC34"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC36"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC33"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t36"></a> 2.4.2 <code>ltcalc</code>的语法规则-Grammar Rules for <code>ltcalc</code> </h3>
- <p>是否处理位置对于你的语言的语法明没有影响.
- 因此,这个语言的语法规则与前一个例子的非常接近;
- 我们仅仅修改它们以获取新的信息.
- </p>
- <p>在这里,我们使用位置来报告除数为0并且对错误的表达式或子表达式进行定位.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">input : /* empty */
- | input line
- ;
- line : '/n'
- | exp '/n' { printf ("%d/n", $1); }
- ;
- exp : NUM { $$ = $1; }
- | exp '+' exp { $$ = $1 + $3; }
- | exp '-' exp { $$ = $1 - $3; }
- | exp '*' exp { $$ = $1 * $3; }
- | exp '/' exp
- {
- if ($3)
- $$ = $1 / $3;
- else
- {
- $$ = 1;
- fprintf (stderr, "%d.%d-%d.%d: division by zero",
- @3.first_line, @3.first_column,
- @3.last_line, @3.last_column);
- }
- }
- | '-' exp %preg NEG { $$ = -$2; }
- | exp '^' exp { $$ = pow ($1, $3); }
- | '(' exp ')' { $$ = $2; }
- </pre></td></tr></tbody></table>
- <p>这段代码展示了如何对规则部件使用伪变量<code>@<var>n</var></code>
- 以及对组使用伪变量<code>@$</code>在语义动作中确定位置.
- </p>
- <p>我们不需要向<code>@$</code>赋值:输出分析器会自动这样作.
- 默认地,在执行每个动作的C代码之前,
- 对于一个具有<var>n</var>个部件的规则,
- <code>@$</code>被设定为从<code>@1</code>的开始到<code>@<var>n</var></code>的结束.
- 我们可以重新定义这个动作(参阅<a href="#SEC60">位置的默认动作-Default Action for Locations</a>一章),
- 对于一些特殊的规则,<code>@$</code>可以手动计算.
- </p>
- <hr size="6">
- <a name="Ltcalc-Lexer"></a>
- <a name="SEC36"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC35"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC37"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC33"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t37"></a> 2.4.3 <code>ltcalc</code>的词法分析器-The <code>ltcalc</code> Lexical Analyzer. </h3>
- <p>直到现在,我们仍然在依靠Bison的默认来激活位置追踪.
- 下一步就我们重写词法分析器,
- 并且使它与语法分析器的记号位置相适合,
- 就像它已经为语义值做的那样.
- </p>
- <p>在最后,为了避免计算的位置出错,我们必须对每个输入字符进行计数.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int
- yylex (void)
- {
- int c;
- /* Skip white space. */
- /* 跳过空白 */
- while ((c = getchar ()) == ' ' || c == '/t')
- ++yylloc.last_column;
- /* Step. */
- yylloc.first_line = yylloc.last_line;
- yylloc.first_column = yylloc.last_column;
- /* Process numbers. */
- /* 处理数字 */
- if (isdigit (c))
- {
- yylval = c - '0';
- ++yylloc.last_column;
- while (isdigit (c = getchar ()))
- {
- ++yylloc.last_column;
- yylval = yylval * 10 + c - '0';
- }
- ungetc (c, stdin);
- return NUM;
- }
- /* Return end-of-input. */
- /* 返回输入结束 */
- if (c == EOF)
- return 0;
- /* Return a single char, and update location. */
- /* 返回一个单字符,并且更新位置 */
- if (c == '/n')
- {
- ++yylloc.last_line;
- yylloc.last_column = 0;
- }
- else
- ++yylloc.last_column;
- return c;
- }
- </pre></td></tr></tbody></table>
- <p>词法分析器基本上做出了与前一个例子相同的处理:
- 它跳过了空格和制表符,并且读入了许多单字符记号.
- 而外地,它更新了含有记号位置的全局变量(类型是<code>YYLTYPE</code>)<code>yyloc</code>.
- </p>
- <p>现在,每当这个函数返回一个记号,与语义值一样,
- 分析器就有了这个记号的编号和它的文字位置.
- 最后需要改变的就是初始化<code>yyloc</code>.
- 例如在控制函数中:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int
- main (void)
- {
- yylloc.first_line = yylloc.last_line = 1;
- yylloc.first_column = yylloc.last_column = 0;
- return yyparse ();
- }
- </pre></td></tr></tbody></table>
- <p>要记住:计算位置并不是语法的事情.
- 每个字符必须关联一个位置更新,
- 不论它是在一个有效的输入中还是在注释中或者字符串中等等.
- </p>
- <hr size="6">
- <a name="Multi_002dfunction-Calc"></a>
- <a name="SEC37"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC36"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC38"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC19"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t38"></a> 2.5 多功能计算器:<code>mfcalc</code>-Multi-Function Calculator: <code>mfcalc</code> </h2>
- <p>到现在为止,我们已经讨论了Bison的基础部分.
- 是时间去转移到一些高级的问题中去.
- 上述的计算器仅仅提供了五个功能,
- <samp>`+'</samp>,<samp>`-'</samp>,<samp>`*'</samp>,<samp>`/'</samp>和<samp>`^'</samp>.
- 让我们的计算器提供其它数学函数如<code>sin</code>,<code>cos</code>等等是一个不错的想法.
- </p>
- <p>一旦新的操作符只是单字符,将它们添加到中缀计算器是很简单的事情.
- 词法分析器<code>yylex</code>将所有非数字字符返回成记号,
- 所以新的语法规则对于新的操作符来说足够用.
- 但是我们需要一些更灵活的东西:采用这种格式的内建函数:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example"><var>function_name</var> (<var>argument</var>)
- </pre></td></tr></tbody></table>
- <p>同时,我们靠建立命名变量来为计算器添加记忆功能.
- 我们可以在它们中存储数值,并在稍后使用它们.
- 这就是多功能计算器的一个会话的例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">$ <kbd>mfcalc</kbd>
- <kbd>pi = 3.141592653589</kbd>
- 3.1415926536
- <kbd>sin(pi)</kbd>
- 0.0000000000
- <kbd>alpha = beta1 = 2.3</kbd>
- 2.3000000000
- <kbd>alpha</kbd>
- 2.3000000000
- <kbd>ln(alpha)</kbd>
- 0.8329091229
- <kbd>exp(ln(beta1))</kbd>
- 2.3000000000
- $
- </pre></td></tr></tbody></table>
- <p>注意到多重赋值和嵌套函数是允许使用的.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC38">2.5.1 <code>mfcalc</code>的声明-Declarations for <code>mfcalc</code></a></td><td> </td><td align="left" valign="top"> 多功能计算器的Bison声明
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC39">2.5.2 <code>mfcalc</code>的语法规则-Grammar Rules for <code>mfcalc</code></a></td><td> </td><td align="left" valign="top"> 计算器的语法声明
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC40">2.5.3 <code>mfcalc</code>的符号表-The <code>mfcalc</code> Symbol Table</a></td><td> </td><td align="left" valign="top"> 符号表管理规则
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Mfcalc-Decl"></a>
- <a name="SEC38"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC37"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC39"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC37"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t39"></a> 2.5.1 <code>mfcalc</code>的声明-Declarations for <code>mfcalc</code> </h3>
- <p>这就是多功能计算器的C和Bison声明部分:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">%{
- #include <math.h> /* For math functions, cos(), sin(), etc. */ /* 为了使用数学函数, cos(), sin(), 等等 */
- #include "calc.h" /* Contains definition of `symrec'. */ /* 包含了 `symrec'的定义 */
- int yylex (void);
- void yyerror (char const *);
- %}
- %union {
- double val; /* For returning numbers. */ /* 返回的数值 */
- symrec *tptr; /* For returning symbol-table pointers. */ /* 返回的符号表指针 */
- }
- %token <val> NUM /* Simple double precision number. */ /* 简单的双精度数值 */
- %token <tptr> VAR FNCT /* Variable and Function. */ /* 变量和函数 */
- %type <val> exp
- %right '='
- %left '-' '+'
- %left '*' '/'
- %left NEG /* negation--unary minus */ /* 负号 */
- %right '^' /* exponentiation */ /* 幂 */
- %% /* The grammar follows. */
- </pre></td></tr></tbody></table>
- <p>上述的语法仅仅引进了两个Bison语言的信特征.
- 这些特征允许语义值拥有多种数据类型.
- (参阅<a href="#SEC53">多种值类型-More Than One Value Type</a>一章).
- </p>
- <p><code>%union</code>声明了所有可能类型清单;
- 这是用来取代<code>YYSTYPE</code>的.
- 现在允许的类型是双精度(为了<code>exp</code>和<code>NUM</code>)和指向符号表目录项的指针.
- 参阅 <a href="#SEC64">值类型集-The Collection of Value Types</a>.
- </p>
- <p>由于语义值值现在可以有多种类型,
- 对每一个使用语义值的语法符号关联一个语义值类型是很必要的.
- 这些符号是<code>NUM</code>,<code>VAR</code>,<code>FNCT</code>,和<code>exp</code>.
- 它们的在声明的时候已经指明了语义值类型(在中括号之间).
- </p>
- <p><code>%type</code>用来声明非终结符,就像<code>%token</code>用来声明符号类型(注:终结符)的一样.
- 我们之前并没有<code>%type</code>是因为非终结符经常在定义它们的规则中隐含地声明.
- 但是<code>exp</code>必须被明确地声明以便我们使用它的语义值类型.
- 参阅 <a href="#SEC65">非终结符-Nonterminal Symbols</a>.
- </p>
- <hr size="6">
- <a name="Mfcalc-Rules"></a>
- <a name="SEC39"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC38"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC40"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC37"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t40"></a> 2.5.2 <code>mfcalc</code>的语法规则-Grammar Rules for <code>mfcalc</code> </h3>
- <p>这就是多功能计算器的语法规则.
- 它们之中的大多数都是从<code>calc</code>复制过来的;
- 三个提到<code>VAR</code>或者<code>FNCT</code>的规则是新增的.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">input: /* empty */
- | input line
- ;
- line:
- '/n'
- | exp '/n' { printf ("/t%.10g/n", $1); }
- | error '/n' { yyerrok; }
- ;
- exp: NUM { $$ = $1; }
- | VAR { $$ = $1->value.var; }
- | VAR '=' exp { $$ = $3; $1->value.var = $3; }
- | FNCT '(' exp ')' { $$ = (*($1->value.fnctptr))($3); }
- | exp '+' exp { $$ = $1 + $3; }
- | exp '-' exp { $$ = $1 - $3; }
- | exp '*' exp { $$ = $1 * $3; }
- | exp '/' exp { $$ = $1 / $3; }
- | '-' exp %prec NEG { $$ = -$2; }
- | exp '^' exp { $$ = pow ($1, $3); }
- | '(' exp ')' { $$ = $2; }
- ;
- /* End of grammar. */
- %%
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Mfcalc-Symtab"></a>
- <a name="SEC40"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC39"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC41"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC37"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t41"></a> 2.5.3 <code>mfcalc</code>的符号表-The <code>mfcalc</code> Symbol Table </h3>
- <p>多功能计算器需要一个符号表来追踪变量和符号的名称和意义.
- 这并不影响语法规则(除了动作以外)或者Biosn声明.
- 但是它要求一些额外的C函数支持.
- </p>
- <p>符号表本身由记录的链表组成.
- 它的定义在头文件<tt>`calc.h'</tt>中,如下.
- 它提供了将函数或者变量插入符号表的功能.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">/* Function type. */
- /* 函数类型 */
- typedef double (*func_t) (double);
- /* Data type for links in the chain of symbols. */
- /* 链表节点的数据类型 */
- struct symrec
- {
- char *name; /* name of symbol */ /* 符号的名称 */
- int type; /* type of symbol: either VAR or FNCT */ /* 符号的类型: VAR 或 FNCT */
- union
- {
- double var; /* value of a VAR */ /* VAR 的值 */
- func_t fnctptr; /* value of a FNCT */ /* FNCT 的值 */
- } value;
- struct symrec *next; /* link field */ /* 指针域 */
- };
- typedef struct symrec symrec;
- /* The symbol table: a chain of `struct symrec'. */
- /* 符号表: `struct symrec'的链表 */
- extern symrec *sym_table;
- symrec *putsym (char const *, func_t);
- symrec *getsym (char const *);
- </pre></td></tr></tbody></table>
- <p>新版本的<code>main</code>包含了一个<code>init_table</code>的调用,
- 这个函数用来初始化符号表.
- 这就是<code>main</code>和<code>init_table</code>的代码:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">#include <stdio.h>
- /* Called by yyparse on error. */
- /* 出错时被yyparse调用 */
- void
- yyerror (char const *s)
- {
- printf ("%s/n", s);
- }
- struct init
- {
- char const *fname;
- double (*fnct) (double);
- };
- struct init const arith_fncts[] =
- {
- "sin", sin,
- "cos", cos,
- "atan", atan,
- "ln", log,
- "exp", exp,
- "sqrt", sqrt,
- 0, 0
- };
- /* The symbol table: a chain of `struct symrec'. */
- /* 符号表: `struct symrec'链表 */
- symrec *sym_table;
- /* Put arithmetic functions in table. */
- /* 将数学函数放入符号表(注:保留字的实现方式) */
- void
- init_table (void)
- {
- int i;
- symrec *ptr;
- for (i = 0; arith_fncts[i].fname != 0; i++)
- {
- ptr = putsym (arith_fncts[i].fname, FNCT);
- ptr->value.fnctptr = arith_fncts[i].fnct;
- }
- }
- int
- main (void)
- {
- init_table ();
- return yyparse ();
- }
- </pre></td></tr></tbody></table>
- <p>靠简单地编辑初始化列表和添加必要的头文件,
- 你可以为计算器添加额外的功能.
- </p>
- <p>两个重要的函数允许对符号表进行搜索和安置操作.
- <code>putsym</code>函数需要传递要安置对象的名称和类型(<code>VAR</code>或<code>FNCT</code>).
- 对象被连接到链表的头部,一个指向这个对象的指针最后被返回.
- <code>getsym</code>函数要传递需要查找的符号的名称.
- 如果找到,指向那个符号的指针回返回,否则返回0.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">symrec *
- putsym (char const *sym_name, int sym_type)
- {
- symrec *ptr;
- ptr = (symrec *) malloc (sizeof (symrec));
- ptr->name = (char *) malloc (strlen (sym_name) + 1);
- strcpy (ptr->name,sym_name);
- ptr->type = sym_type;
- ptr->value.var = 0; /* Set value to 0 even if fctn. */ /* 置0即使是fctn */
- ptr->next = (struct symrec *)sym_table;
- sym_table = ptr;
- return ptr;
- }
- symrec *
- getsym (char const *sym_name)
- {
- symrec *ptr;
- for (ptr = sym_table; ptr != (symrec *) 0;
- ptr = (symrec *)ptr->next)
- if (strcmp (ptr->name,sym_name) == 0)
- return ptr;
- return 0;
- }
- </pre></td></tr></tbody></table>
- <p><code>yylex</code>函数现在必须能识别出变量,数字值和单字符算术操作符.
- 开头为非字数字的字符串被识别为变量还是函数依赖于符号表对它们的描述.
- </p>
- <p>字符串被传递到<code>getsym</code>用于在符号表中查找.
- 如果名称出现在表格中,指向它的位置的指针和它的类型会返回给<code>yyparse</code>.
- 如果尚未出现在符号表中,它会被安置为一个<code>VAR</code>使用函数<code>putsym</code>.
- 同样地,一个指针和它的类型(必须是<code>VAR</code>)被返回给<code>yyparse</code>.
- </p>
- <p><code>yylex</code>中处理数字制和算术运算符的代码并不需要更改.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">#include <ctype.h>
- int
- yylex (void)
- {
- int c;
- /* Ignore white space, get first nonwhite character. */
- /* 忽略空白,获取第一个非空白的字符 */
- while ((c = getchar ()) == ' ' || c == '/t');
- if (c == EOF)
- return 0;
- /* Char starts a number => parse the number. */
- /* 以数字开头 => 分析数字 */
- if (c == '.' || isdigit (c))
- {
- ungetc (c, stdin);
- scanf ("%lf", &yylval.val);
- return NUM;
- }
- /* Char starts an identifier => read the name. */
- /* 以标识符开头 => 读取名称 */
- if (isalpha (c))
- {
- symrec *s;
- static char *symbuf = 0;
- static int length = 0;
- int i;
- /* Initially make the buffer long enough
- for a 40-character symbol name. */
- /* 在开始的时候使缓冲区足够容纳40字符长的符号名称*/
- if (length == 0)
- length = 40, symbuf = (char *)malloc (length + 1);
- i = 0;
- do
- {
- /* If buffer is full, make it bigger. */
- /* 如果缓冲区已满,使它大一点 */
- if (i == length)
- {
- length *= 2;
- symbuf = (char *) realloc (symbuf, length + 1);
- }
- /* Add this character to the buffer. */
- /* 将这个字符加入缓冲区 */
- symbuf[i++] = c;
- /* Get another character. */
- /* 获取另外一个字符 */
- c = getchar ();
- }
- while (isalnum (c));
- ungetc (c, stdin);
- symbuf[i] = '/0';
- s = getsym (symbuf);
- if (s == 0)
- s = putsym (symbuf, VAR);
- yylval.tptr = s;
- return s->type;
- }
- /* Any other character is a token by itself. */
- /* 其余的字符是自己为记号的字符 */
- return c;
- }
- </pre></td></tr></tbody></table>
- <p>这个程序既有效又灵活.
- 你可以轻松地加入新的函数.
- 而且加入于预定义数值如<code>pi</code>或者<code>e</code>也是很简单的事情.
- </p>
- <hr size="6">
- <a name="Exercises"></a>
- <a name="SEC41"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC40"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC42"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC19"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC42"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t42"></a> 2.6 练习-Exercises </h2>
- <ol>
- <li>
- 向文件<tt>`math.h'</tt>中的初始列表添加新的函数.
- </li><li>
- 添加另外一个包括常量和它们数值的数组.
- 然活修改<code>init_table</code>将这些常量添加到符号表.
- 使这些常量类型为<code>VAR</code>最简单.
- </li><li>
- 使这个程序当用户引用一个未初始化的变量时报告一个错误.
- </li></ol>
- <hr size="6">
- <a name="Grammar-File"></a>
- <a name="SEC42"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC41"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC43"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC19"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="chapter"><a name="t43"></a> 3. Biosn的语法文件-Bison Grammar Files </h1>
- <p>Bison使用一个描述上下文无关文法的文件做为输入,
- 并制造一个实别改文法的正确实例的C语言函数.
- </p>
- <p>Bison语法输入文件通常以<samp>`.y'</samp>结尾.参阅 <a href="#SEC104">调用Bison-Invoking Bison</a>.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC43">3.1 Bison语法的提纲-Outline of a Bison Grammar</a></td><td> </td><td align="left" valign="top"> 语法文件的整体布局
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td><td> </td><td align="left" valign="top"> 终结符与非终结符
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC49">3.3 描述语法规则的语法-Syntax of Grammar Rules</a></td><td> </td><td align="left" valign="top"> 如何编写语法规则
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC50">3.4 递归规则-Recursive Rules</a></td><td> </td><td align="left" valign="top"> 编写递归规则
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC51">3.5 定义语言的语义-Defining Language Semantics</a></td><td> </td><td align="left" valign="top"> 语义值和动作
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC57">3.6 追踪位置-Tracking Locations</a></td><td> </td><td align="left" valign="top"> 位置和动作
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC61">3.7 Bison声明-Bison Declarations</a></td><td> </td><td align="left" valign="top"> 所有种类的Bison声明在这里讨论
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC72">3.8 在同一个程序中使用多个分析器-Multiple Parsers in the Same Program</a></td><td> </td><td align="left" valign="top"> 将多个Bison分析器放在一个程序中
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Grammar-Outline"></a>
- <a name="SEC43"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC42"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC44"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC42"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t44"></a> 3.1 Bison语法的提纲-Outline of a Bison Grammar </h2>
- <p>一个Bison语法文件有四个主要的部分,
- 就像如下所示,由恰当的分隔符分隔.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%{
- <var>Prologue</var>
- %}
- <var>Bison declarations</var>
- %%
- <var>Grammar rules</var>
- %%
- <var>Epilogue</var>
- </pre></td></tr></tbody></table>
- <p>注释包含在<samp>`/* … */'</samp>之中,并且可以在任意部分出现.
- 做为一个<acronym>GNU</acronym>扩展,<samp>`//'</samp>引进了一个直到这行末尾的注释.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC44">3.1.1 <var>Prologue</var>部分-The prologue</a></td><td> </td><td align="left" valign="top"> Prologue部分的语法和使用
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC45">3.1.2 <var>Bison Declarations</var>部分-The Bison Declarations Section</a></td><td> </td><td align="left" valign="top"> Bison declarations部分的语法和使用
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC46">3.1.3 语法规则部分-The Grammar Rules Section</a></td><td> </td><td align="left" valign="top"> Grammar Rules部分的语法和使用
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC47">3.1.4 <var>Epilogue</var>部分-The epilogue</a></td><td> </td><td align="left" valign="top"> Epilogue部分的语法和使用
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Prologue"></a>
- <a name="SEC44"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC43"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC45"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC43"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t45"></a> 3.1.1 <var>Prologue</var>部分-The prologue </h3>
- <p><var>Prologue</var>部分包括宏定义和在语法规则动作中使用的函数和变量的声明.
- 这些将复制到分析器文件的开头以便先于<code>yyparse</code>的定义.
- 你可以使用<samp>`#include'</samp>来从头文件获取声明.
- 如果你不需要任何的C声明,你可以省略这个部分的括号分隔符<samp>`%{'</samp>和<samp>`%}'</samp>.
- </p>
- <p>可以有多个与<var>Bison declarations</var>混合的<var>Prologue</var>部分.
- 这种做法允许你拥有相互引用的C和Bison声明.
- 例如,<code>%union</code>可以使用定义在头文件的数据类型,
- 并且你希望使用带有<code>YYSTYPE</code>类型做为参数的函数.
- 可以通过两个<var>Prologue</var>块来实现这个,
- 一个在<code>%union</code>之前,另一个在之后.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">%{
- #include <stdio.h>
- #include "ptypes.h"
- %}
- %union {
- long int n;
- tree t; /* <code>tree</code> is defined in <tt>`ptypes.h'</tt>. */
- /* <code>tree</code> 在<tt>`ptypes.h'</tt>中定义. */
- }
- %{
- static void print_token_value (FILE *, int, YYSTYPE);
- #define YYPRINT(F, N, L) print_token_value (F, N, L)
- %}
- …
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Bison-Declarations"></a>
- <a name="SEC45"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC44"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC46"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC43"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t46"></a> 3.1.2 <var>Bison Declarations</var>部分-The Bison Declarations Section </h3>
- <p><var>Bison declatations</var>部分包含了定义终结符和非终结符的声明,优先级等等.
- 在一些简单的语法中,可以不需要任何声明.
- 参阅 <a href="#SEC61"><var>Bison Declarations</var>部分-Bison Declarations</a>.
- </p>
- <hr size="6">
- <a name="Grammar-Rules"></a>
- <a name="SEC46"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC45"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC47"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC43"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t47"></a> 3.1.3 语法规则部分-The Grammar Rules Section </h3>
- <p><em>Grammar Rules</em>部分包含了一个或多个Bison语法规则.
- 参阅 <a href="#SEC49">用来表示语法规则的语法-Syntax of Grammar Rules</a>.
- </p>
- <p>在这里至少应该有一个语法规则,并且第一个<samp>`%%'</samp>(先于语法规则的那个)绝对不能省略,解释它在文件的最开头.
- </p>
- <hr size="6">
- <a name="Epilogue"></a>
- <a name="SEC47"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC46"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC48"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC43"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t48"></a> 3.1.4 <var>Epilogue</var>部分-The epilogue </h3>
- <p>就像<var>Prologue</var>部分被复制到开头一样,<var>Epilogue</var>部分被逐字地复制到分析器文件的结尾.
- 如果你想放一些代码却没必要放在<code>yyparse</code>的定义之前,这里是最方便的地方.
- 例如,<code>yylex</code>和<code>yyerror</code>的定义就经常放在这里.
- 因为C语言要求函数在使用之前必须声明.
- 你经常需要在<var>Prologue</var>部分声明类似<code>yylex</code>和<code>yyerror</code>的函数,
- 即使你在<var>Epilogue</var>部分已经定义了它们.
- 参阅 <a href="#SEC73">分析器C语言接口-Parser C-Language Interface</a>.
- </p>
- <p>如果最后一部分为空,你可以省略分隔它的分隔符<samp>`%%'</samp>.
- </p>
- <p>Bison分析器自己包含了许多以<samp>`yy'</samp>和<samp>`YY'</samp>开头宏和标识符的定义.
- 所以在<var>Epilogue</var>部分避免使用这种类型的名字(出了这个文档讨论的之外)是一个好主意.
- </p>
- <hr size="6">
- <a name="Symbols"></a>
- <a name="SEC48"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC47"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC49"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC42"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t49"></a> 3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal </h2>
- <p>Bison语法中的<em>符号(Symbols)</em>代表着语言的语法类型.
- </p>
- <p>一个<em>终结符(terminal symbol)</em>(也被称做<em>符号类型(token type)</em>代表了一类从构造上等价的记号.
- 你在语法中使用符号的意思就是一个这种类型的记号是允许的.
- Bison分析器将符号表示为数字码.
- <code>yylex</code>返回一个记号类型来指明一个被读入的记号是什么类型的.
- 你不需要了解那个码的数值是多少;
- 你使用代表它的符号就可以了.
- </p>
- <p>一个<em>非终结符(noterminal symbol)</em>代表一类从构造上等价的组.
- 符号名称用于编写语法规则.
- 按照惯例,所有的非终结符都应该是小写的.
- </p>
- <p>符号名称可以是字母,数字(不在开头),下划线和句点.
- 句点只在非终结符中有意义.
- </p>
- <p>在语法中书写终结符有三种方法:
- </p>
- <ul>
- <li>
- 一个<em>命名符号类型(named token type)</em>用类似C语言的标识符书写.
- 按照惯例,它们应该是大写字母.
- 每一个这种名称必须由一个Bison声明<code>%token</code>定义.
- 参阅 <a href="#SEC62">符号类型的名称-Token Type Names</a>.
- </li><li>
- <a name="IDX14"></a>
- <a name="IDX15"></a>
- <a name="IDX16"></a>
- 一个<em>字符记号类型(character token type</em>(或者<em>文字字符记号(literal character token)</em>
- 用如同C语言字符常量相同的语法书写;
- 例如,<code>'+'</code>是一个字符记号类型.
- 除非你要指明字符记号类型的语义值类型(参阅<a href="#SEC52">语义值的数据类型-Data Types of Semantic Values</a>一章),
- 结合性或优先级(参阅<a href="#SEC85">操作符优先级-Operator Precedence</a>一章),
- 否则没有必要声明它们.
- <p>按照惯例,一个字符记号类型只用于表示一个由特定字符组成的记号.
- 因此,记号类型<code>'+'</code>用于将字符<samp>`+'</samp>表示为一个记号.
- 没有对此惯例的强制要求,
- 但是如果你不按照惯例做,
- 你的程序会使其它的读者感到困惑.
- </p>
- <p>所有常用的C语言的字符转义序列都可以在Bison中使用,
- 但是你不能使用一个空字符作为一个字符文字.
- 因为它的数字码是0,这表示输入结束.(参阅<a href="#SEC76"><code>yylex</code>的调用惯例-Calling Convention for <code>yylex</code></a>一章).
- 并且,不像标准C 三字符词(trigraphs)(注:由"??"开头的九种转义,为了在缺少标准C标点的宿主上使用标准C,可参考标准C文档)
- 在Bison中并没有特殊意义并且反斜杠换行也是不允许的.
- </p>
- </li><li>
- <a name="IDX17"></a>
- <a name="IDX18"></a>
- <a name="IDX19"></a>
- 一个<em>文字串记号(literal string token)</em>用类似C语言中的字符串常量来书写;
- 例如,<code>"<="</code>是一个文字串记号.
- 除非你要指明文字串记号的语义值类型(参阅<a href="#SEC52">值类型-Value Type</a>一章),
- 结合性或优先级(参阅<a href="#SEC85">优先级-Precedence</a>一章),你没有必要声明它们.
- <p>你可以使用<code>%token</code>(参阅<a href="#SEC62">符号声明-Token Declarations</a>一章)将文字串记号关联一个符号名称作为别名.
- 如果你不这样做,词法分析器必须从<code>yytname</code>表中重新找到文字串记号的代码.
- (参阅<a href="#SEC76">调用惯例-Calling Convention</a>一章).
- </p>
- <p><strong>警告</strong>: 文字串记号在Yacc中不能工作.
- </p>
- <p>按照惯例,一个文字串记号只用于表示一个由特定串构成的记号.
- 因此,你用该使用类型<code>"<="</code>表示作为记号的字符串<samp>`<='</samp>.
- Bison并没有强制要求这种管理,但是如果你偏离了惯例,
- 阅读你程序的人会感到困惑.
- </p>
- <p>所有常用的C语言的字符转义序列都可以在Bison中使用,
- 但是你不能使用一个空字符作为一个字符文字.
- 因为它的数字码是0,这表示输入结束.
- (参阅 <a href="#SEC76"><code>yylex</code>的调用惯例-Calling Convention for <code>yylex</code></a>.)
- 并且,不像标准C,
- 三字符词(trigraphs)(注:由"??"开头的九种转义,为了在缺少标准C标点的宿主上使用标准C,可参考标准C文档)
- 在Bison中并没有特殊意义并且反斜杠换行也是不允许的.
- 一个文字串记号必须包括两个或更多个字符;
- 对于进包含一个字符的记号,你应该使用字符记号(参考以上).
- </p></li></ul>
- <p>怎样选择终结符的写法对于它的语法意义没有影响.
- 它只依赖于它出现在规则的什么地方以及什么时候分器起函数返回那个符号.
- </p>
- <p><code>yylex</code>的返回值通常是终结符,除非返回一个代表结束输入的0或者负值.
- 无论你采用那种方法在语法规则中书写符号类型,
- 你应该在<code>yylex</code>的定义中采用相同的写法.
- 单字符符号类型的数字码简单地就是那个字符的正数编码,
- 所以,即使当<code>char</code>是有符号时你需要将它转换成<code>unsigned char</code>来避免主机上符号扩展
- <code>yylex</code>仍可以使用相同的值来产生必要的代码.
- 每一个命名记号类型在分析器文件中变为一个C宏,
- 所以<code>yylex</code>可以使用名称代表那个编码.
- (这就是为什么句点在终结符中不起作用.)
- 参阅 <a href="#SEC76"><code>yylex</code>的调用惯例-Calling Convention for <code>yylex</code></a>.
- </p>
- <p>如果<code>yylex</code>是在另外的文件中定义的,
- 你需要安排符号类型的宏定义在那里是可见的.
- 在你运行Bison的时候使用<samp>`-d'</samp>选项
- 以便让它将这些宏定义写入一个另外的头文件<tt>`<var>name</var>.tab.h'</tt>.
- 你可以将它加入其它需要它的文件.
- 参阅 <a href="#SEC104">调用Bison-Invoking Bison</a>.
- </p>
- <p>如果你要编写一个可以移植到任何标准C宿主上的语法,
- 你必须只能从基本标准C字符集中选择使用非零字符记号类型.
- 这个字符集由10个数字,52个大小写英文字母,和在下列C语言字符串中的字符构成的:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">"/a/b/t/n/v/f/r !/"#%&'()*+,-./:;<=>?[//]^_{|}~"
- </pre></td></tr></tbody></table>
- <p><code>yylex</code>函数和Bison必须为字符记号使用一个一致的字符集和编码.
- 例如,如果你在<acronym>ASCII</acronym>环境中运行Bison,
- 但是在不兼容的例如<acronym>EBCDIC</acronym>的环境中编译和运行最终的程序,
- 最终程序可能不会工作.因为Bison产生的表格将字符记号假定为<acronym>ASCII</acronym>数字值.
- 发布带有Bison在<acronym>ASCII</acronym>环境中产生的C源文件的软件是标准的做法,
- 所以在与<acronym>ASCII</acronym>不兼容的平台的安装器必须在编译它们之前重新构建这些文件.
- </p>
- <p>符号<code>error</code>是一个保留用作错误恢复的终结符(参阅<a href="#SEC96">错误恢复-Error Recovery</a>一章);
- 你不应该为了其它的目的而使用它.
- 特别地,<code>yylex</code>永远不应该返回这个值(注:<code>error</code>).
- 除非你明确地在声明中赋予一个你的记号值为256,否则error记号的默认值是256.
- </p>
- <hr size="6">
- <a name="Rules"></a>
- <a name="SEC49"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC48"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC50"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC42"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t50"></a> 3.3 描述语法规则的语法-Syntax of Grammar Rules </h2>
- <p>一个Bison语法规则通常有如下的下形式:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example"><var>result</var>: <var>components</var>…
- ;
- </pre></td></tr></tbody></table>
- <p><var>reault</var>所在是这个规则描述的非终结符而<var>components</var>
- 是被这个规则组合在一起的多种终结符和非终结符.(参阅<a href="#SEC48">符号-Symbols</a>一章)
- </p>
- <p>例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp: exp '+' exp
- ;
- </pre></td></tr></tbody></table>
- <p>表明两组<code>exp</code>类型和一个<samp>`+'</samp>记号在中间,
- 可以结合成一个更大的<code>exp</code>类型组.
- </p>
- <p>规则中的空白只用来分隔符号.你可以在你希望的地方添加额外的空白.
- </p>
- <p>决定规则的语义的<var>动作</var>可以分散在部件中.一个动组看起来是这样:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">{<var>C statements</var>}
- </pre></td></tr></tbody></table>
- <p>通常只有一个动作跟随着部件.
- 参阅 <a href="#SEC54">动作-Actions</a>.
- </p>
- <a name="IDX20"></a>
- <p><var>result</var>的多种规则可以分别书写或者由垂直条<samp>`|'</samp>按如下的方法连接起来:
- </p>
- <p>在这种方式下依然有我们之特考虑的特殊规则.
- </p>
- <p>如果一个规则的<var>components</var>为空,它意味着<var>result</var>可以匹配空字符串.
- 例如,这就是一个定一个由逗号分隔的0个或多个<code>exp</code>组:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">expseq: /* empty */ /* 空 */
- | expseq1
- ;
- expseq1: exp
- | expseq1 ',' exp
- ;
- </pre></td></tr></tbody></table>
- <p>我们通常对每个没有部件的规则加上一个<samp>`/* empty */'</samp>的注释.
- </p>
- <hr size="6">
- <a name="Recursion"></a>
- <a name="SEC50"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC49"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC51"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC42"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t51"></a> 3.4 递归规则-Recursive Rules </h2>
- <p>一个规则被称为<em>递归的(recursive</em>)当它的<var>result</var>非终结符也出现在它的右手边.
- 因为这种方法是唯一可以定义一个特定事物的任意数字序列的方法,
- 几乎所有的Bison语法都需要使用递归.
- 考虑这个逗号分隔的一个或者多个表达式的递归定义:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">expseq1: exp
- | expseq1 ',' exp
- ;
- </pre></td></tr></tbody></table>
- <a name="IDX21"></a>
- <a name="IDX22"></a>
- <p>由于<code>expseq1</code>的递归使用是在有手端的最左符号,
- 我们称这种递归为<em>左递归(left recursion)</em>.
- 相反地,这里有一个相同地使用<em>右递归(right recursion)</em>的定义.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">expseq1: exp
- | exp ',' expseq1
- ;
- </pre></td></tr></tbody></table>
- <p>任意序列都可以使用作递归或者右递归定义,
- 但是通常你应该使用左递归,
- 因为它可以使用空间固定的栈来分析任意个数的元素序列.
- 由于即使规则只应用一次,在这之前,所有元素也都必须被移进到栈中,
- 右递归使用的Bison栈空间与序列中的元素个数成正比.
- 参阅 <a href="#SEC82">Bison分析器算法-The Bison Parser Alogorithm</a>.获得这方面的深入解释.
- </p>
- <a name="IDX23"></a>
- <p><em>间接(Indirect)</em>或者<em>相互(mutual)</em>递归当规则的结果没有在它的右手端出现
- 但是出现在其它右手端的非终结符规则的右手端时候发生.
- </p>
- <p>例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">expr: primary
- | primary '+' primary
- ;
- primary: constant
- | '(' expr ')'
- ;
- </pre></td></tr></tbody></table>
- <p>定义了两个相互递归的非终结符,因为它们互相引用.
- </p>
- <hr size="6">
- <a name="Semantics"></a>
- <a name="SEC51"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC50"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC52"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC42"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t52"></a> 3.5 定义语言的语义-Defining Language Semantics </h2>
- <p>语言的语法规则之决定了语言的语法.
- 语义值却是由与多种记号和组相关联的语义值和当各种组被识别时执行的动作决定的.
- </p>
- <p>例如,正是由于对每个表达式关联了正确的数值,计算器才可以正确的计算.
- 因为组<samp>`<var>x</var> + <var>y</var>'</samp>的动作是将<var>x</var>和<var>y</var>相关联的值相加,
- 所以计算器能正确地计算加法
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC52">3.5.1 语义值的数据类型-Data Types of Semantic Values</a></td><td> </td><td align="left" valign="top"> 为所有的语义值指定一个类型.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC53">3.5.2 多种值类型-More Than One Value Type</a></td><td> </td><td align="left" valign="top"> 指定多种可选的数据类型.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC54">3.5.3 动作-Actions</a></td><td> </td><td align="left" valign="top"> 动作是一个语法规则的语义定义.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC55">3.5.4 动作中值的数据类型-Data Types of Values in Actions</a></td><td> </td><td align="left" valign="top"> 为动作指定一个要操作的数据类型.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC56">3.5.5 规则中的动作-Actions in Mid-Rule</a></td><td> </td><td align="left" valign="top"> 多数动作在规则之后,
- 这一节讲述什么时候以及为什么要使用规则中间动作的特例.
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Value-Type"></a>
- <a name="SEC52"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC51"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC53"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC51"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t53"></a> 3.5.1 语义值的数据类型-Data Types of Semantic Values </h3>
- <p>在一个简单的程序中,对所有的语言结构的语义值使用同一个数据类型就足够用了.
- 在<acronym>RPN</acronym>和中缀计算器的例子中的确是这样.(参阅<a href="#SEC20">逆波兰记号计算器-Reverse Polish Notation Calculator</a>一章).
- </p>
- <p>Bison默认是对于所有语义值使用<code>int</code>类型.
- 如果要指明其它的类型,可以像这样将<code>YYSTYPE</code>定义成一个宏:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">#define YYSTYPE double
- </pre></td></tr></tbody></table>
- <p>这个宏定义比喻在语法文件的<var>Prologue</var>部分.
- (参阅<a href="#SEC43">Bison语法大纲-Outline of a Bison Grammar</a>一章)
- </p>
- <hr size="6">
- <a name="Multiple-Types"></a>
- <a name="SEC53"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC52"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC54"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC51"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t54"></a> 3.5.2 多种值类型-More Than One Value Type </h3>
- <p>在大多数程序中,你需要对不同种类的记号和组使用不同的数据类型.
- 例如,一个数字常量可能需要类型<code>int</code>或<code>long int</code>,
- 而一个字符常量可能许需要类型<code>char *</code>,
- 并且一个标识符需要一个指向符号表项的指针做为其语义值的类型.
- </p>
- <p>为了在一个分析器中使用多种语义值类型,
- Bison要求你做两件事情:
- </p>
- <ul>
- <li>
- 使用Bison声明<code>%union</code>指明全部可能的数据类型集.
- (参阅<a href="#SEC64">值类型集-The Collections of Value Types</a>一章).
- </li><li>
- 从这些类型中为每个符号(终结符或者非终结符)选择一个做为其语义值类型.
- 要做到这些,可以对记号使用Bison声明<code>%token</code>(参阅<a href="#SEC62">符号类型的名称-Token Type Names</a>一章);
- 并且对组使用Bison声明<code>%type</code>(参阅<a href="#SEC65">非终结符-Nonterminal Symbols</a>一章)
- </li></ul>
- <hr size="6">
- <a name="Actions"></a>
- <a name="SEC54"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC53"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC55"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC51"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t55"></a> 3.5.3 动作-Actions </h3>
- <p>当一个规则的实例被识别的时候,
- 同这个规则关联的包含C代码的动作会被执行.
- 大多数动作是用来从记号的语义值或者更小组的语义值计算整个组的语义值.
- </p>
- <p>一个动作由包含在大括号之内的几个C语句构成,很像一个C语句块.
- 一个动作可以包含任意数量的C语句.
- 然而,Bison并不搜索三字符词(trigraphs),
- 所以如果你的代码中使用了三字符词,你要保证它不影响嵌套的括号或者注释的边界,字符串或单个字符.
- </p>
- <p>一个动作可以安放在规则的任意部分;
- 它就在那个位置执行.
- 大多数规则仅有一个在规则所有部件最后的动作.
- 在规则之中的动作是富有技巧性的并且仅用于特殊的目的
- (参阅<a href="#SEC56">在规则中间的动作-Actions in Mid-Rule</a>一章).
- </p>
- <p>动作中的C代码可以使用结构<code>$<var>n</var></code>来引用匹配规则的部件的语义值.
- 这个结构代表了第<var>n</var>个部件的值.
- 正在被构建的组的语义值为<code>$$</code>.
- 当这些被复制到分析器文件的时候,Bison负责将这些结构翻译成适当类型的表达式.
- <code>$$</code>被翻译成一个可以修改的左值以便可以对它赋值.
- </p>
- <p>这里是一个典型的例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp: …
- | exp '+' exp
- { $$ = $1 + $3; }
- </pre></td></tr></tbody></table>
- <p>这个规则从两个由加号连接的稍小的<code>exp</code>组构建一个<code>exp</code>.
- 在这个动作中,<code>$1</code>和<code>$3</code>代着两个部件<code>exp</code>组的语义值.
- 它们是规则右手端第一个和第三个符号.
- 和被存储到<code>$$</code>以便成为刚刚被规则识别的加法表达式的语义值.
- 如果<samp>`+'</samp>记号有一个有用的语义值,可以通过<code>$2</code>引用它.
- </p>
- <p>注意到垂直杠字符<samp>`|'</samp>的确是一个分隔符,
- 并且动作只被附加到一个单一的规则上.
- 这是一点和Flex工具不同的地方.
- 在Flex中,<samp>`|'</samp>既代表"或者"也能代表"与下一个规则有着相同的动作".
- 在下面的例子中,动作仅在<samp>`b'</samp>被发现的时候触发.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">a-or-b: 'a'|'b' { a_or_b_found = 1; };
- </pre></td></tr></tbody></table>
- <a name="IDX24"></a>
- <p>如果你并没有指明一个规则的动作,Bison提供了默认的动作:
- <code>$$ = $1</code>. 因此,第一个符号的值变成了整个规则的值.
- 当然,仅当它们的数据类型相同时,默认动作才是有效的.
- 对于一个空规则,并没有有意义的默认动作;
- 除非这个规则的值无关紧要,否则每个空规则必须有明确的动作.
- </p>
- <p>在<code>$<var>n</var></code>的<var>n</var>中使用0或负值是允许的.
- 这使用来引用在匹配当前规则<em>之前</em>的栈中记号或组.
- 这是一个十分冒险的尝试.
- 你必须明确当前应用的规则处于的上下文才能可靠地使用它.
- 这里有一个可靠地使用这种方法的例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">foo: expr bar '+' expr { … }
- | expr bar '-' expr { … }
- ;
- bar: /* empty */
- { previous_expr = $0; }
- ;
- </pre></td></tr></tbody></table>
- <p>只要<code>bar</code>仅仅以上面展示的形式使用,
- <code>$0</code>就总是引用先前于<code>bar</code>的<code>foo</code>的定义中的<code>expr</code>.
- </p>
- <hr size="6">
- <a name="Action-Types"></a>
- <a name="SEC55"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC54"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC56"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC51"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t56"></a> 3.5.4 动作中值的数据类型-Data Types of Values in Actions </h3>
- <p>如果你为语义值只选择了一种数据类型,
- 那么<code>$$</code>和<code>$<var>n</var></code>结构总是那种类型.
- </p>
- <p>如果你已经使用了<code>%union</code>指定了多种数据类型,
- 那么你必须从这些类型中为每一个可以有语义值的终结符或非终结符声明一种.
- 之后当你每次使用<code>$$</code>或者<code>$<var>n</var></code>的时时侯,
- 它的数据类型由它引用的符号的类型决定.
- 在这个例子中:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp: …
- | exp '+' exp
- { $$ = $1 + $3; }
- </pre></td></tr></tbody></table>
- <p><code>$1</code>和<code>$3</code>引用了<code>exp</code>的实例,
- 所以它们都有为非终结符<code>exp</code>声明的数据类型.
- 如果使用了<code>$2</code>,它就会拥有为终结符<code>'+'</code>声明数据类型,
- 无论它可能是什么.
- </p>
- <p>另外,在你引用数值的时候,
- 在引用的开始<samp>`$'</samp>之后插入<samp>`<<var>type</var>>'</samp>,
- 你还可以指定数据类型,
- 例如,如果你已经定义了这里展示的数据类型:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%union {
- int itype;
- double dtype;
- }
- </pre></td></tr></tbody></table>
- <p>那么你可以用<code>$<itype>1</code>作为一个整数来引用规则的第一个子单元,
- 或者用<code>$<dtype>1</code>作为一个双精度数来引用.
- </p>
- <hr size="6">
- <a name="Mid_002dRule-Actions"></a>
- <a name="SEC56"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC55"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC57"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC51"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t57"></a> 3.5.5 规则中的动作-Actions in Mid-Rule </h3>
- <p>偶尔地,将一个动作放到规则之中是很用用处的.
- 这些规则的写法如同在规则之后的动作一样,
- 但是它们却在分析器识别之后的部件之前执行.
- </p>
- <p>一个规则中动作可以通过<code>$<var>n</var></code>来引用在它之前的部件,
- 但是不能引用接下来的部件,因为这个动作在它们被分析之前执行.
- </p>
- <p>规则中的动作自己也作为这个规则的一个部件.
- 这与在同一个规则的另一个动作有些不同(另一个动作通常在结尾):
- 当在<code>$<var>n</var></code>使用序号<var>n</var>的时候,
- 你必须把则个动作和符号一样也计算在内.
- </p>
- <p>规则中的动作也可以拥有语义值.
- 这个动作可以通过向<code>$$</code>复制来设置它的值,
- 并且规则之中的后一个动作可应使用<code>$<var>n</var></code>引用这个值.
- 由于没有符号可以命名这个动作,
- 所以没有办法为这个值事先声明一个数据类型.
- 每当你引用这个值的时候
- 你必须使用<samp>`$<…><var>n</var>'</samp>结构来指明一个数据类型.
- </p>
- <p>没有办法在规则中动作中为整个规则设定一个值,
- 因为对<code>$$</code>的赋值并没有那个效果(注:看上一段).
- 为整个规则赋值的唯一方法是通过规则末尾的普通动作实现.
- </p>
- <p>这理有一个来自假想编译器的例子,用于处理<code>let</code>语句.
- 格式为<samp>`let (<var>variable</var>) <var>statement</var>'</samp>
- 并在<var>statement</var>生存期创建一个名为<var>variable</var>的临时变量.
- 为了分析这个结构,
- 当<var>statement</var>被分析的时候,我们必须将<var>varible</var>放入符号表,
- 并在稍后移除它.
- 这就是这个规则如何工作的:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">stmt: LET '(' var ')'
- { $<context>$ = push_context ();
- declare_variable ($3); }
- stmt { $$ = $6;
- pop_context ($<context>5); }
- </pre></td></tr></tbody></table>
- <p>一旦<samp>`let (<var>variable</var>)'</samp>已经被识别,第一个动作就执行.
- 它使用了数据类型联合中的<code>context</code>,
- 并保存了一个当前语义上下文(可访问变量列表)的副本作为它的语义值.
- 然后调用<code>declare_variable</code>来向那个列表添加新的变量.
- 一旦第一个动作执行完毕,
- 嵌入的语句<code>stmt</code>就可以被分析了.
- 注意到规则中动作的编号是5,所以<samp>`stmt'</samp>的编号为6.
- </p>
- <p>在嵌入的语句<code>stmt</code>被分析之后,它的语义值边变为了整个<code>let</code>-语句的值.(注:<code>$$=$6;</code>)
- 之后,前一个动作的语义值(注<code>$<context>5</code>)被用来存储先前的变量列表.(注:<code>pop_context ($<context>5)</code>)
- 这将临时的<code>let</code>-变量从列表中删除.
- 这样作的目的是让它不出现在分析程序的其余部分的时候.
- </p>
- <p>由于分析器为了执行动作而进行强制分析,
- 在一个规则没有完全被识别之前执行动作经常会导致冲突.
- 例如,如下的两个规则,并没有规则中的动作,可以在分析器中共存.
- 因为分析器可以移进一个左大括号
- 并且查看之后跟随的符号来确定这是否是一个声明.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">compound: '{' declarations statements '}'
- | '{' statements '}'
- ;
- </pre></td></tr></tbody></table>
- <p>但是当我们向下面这样添加一个规则中的动作时,规则就失效了:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">compound: { prepare_for_local_variables (); }
- '{' declarations statements '}'
- | '{' statements '}'
- ;
- </pre></td></tr></tbody></table>
- <p>现在,当分析器还没有读到左到括号的时候,它就被迫决定是否执行规则中的动作.
- 换句话说,当分析器没有足够的信息作出正确选择的时候,
- 它就会强制使用一个或者其它的规则.
- (这个时候由于分析器仍在决定怎么办,
- 左大括号记号被称之为<em>超前扫描记号(look-ahead)</em>.
- 参阅 <a href="#SEC83">超前扫描记号-Look-Ahead Token</a>.)
- (注:这个时候两个规则的超前扫描记号都是<samp>`{'</samp>)
- </p>
- <p>你可能认为给这两个规则放置相同的动作可以解决这个问题,就像这样:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">compound: { prepare_for_local_variables (); }
- '{' declarations statements '}'
- | { prepare_for_local_variables (); }
- '{' statements '}'
- ;
- </pre></td></tr></tbody></table>
- <p>但是这种方法不可行,因为Bison并没有意识到两个动作是完全相同的.
- (Bison永远不会尝试理解动作中的C代码.)
- </p>
- <p>如果语法是这样的:可以依靠第一个记号(C语言就是这样)识别出一个声明.
- 那么将动作放到左大括号后是一个可行的解决方法.
- 就像这样:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">compound: '{' { prepare_for_local_variables (); }
- declarations statements '}'
- | '{' statements '}'
- ;
- </pre></td></tr></tbody></table>
- <p>现在接下来的声明或者语句的第一个记号(注:超前扫描记号)
- 在任何情况下都会告知Bison该使用哪一个规则.
- </p>
- <p>另外一种解决方法是将动作放入一个做为子规则的非终结符.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">subroutine: /* empty */
- { prepare_for_local_variables (); }
- ;
- compound: subroutine
- '{' declarations statements '}'
- | subroutine
- '{' statements '}'
- ;
- </pre></td></tr></tbody></table>
- <p>现在Bison不用却确定最终使用的规则就可执行规则<code>subroutine</code>中的动作.
- 注意到:现在动作已经在规则的结尾.
- 任何规则中间的动作都可以由这种方法转化为一个规则结尾的动作,
- 并且这也是Bison处理规则中间的动作的方法.
- </p>
- <hr size="6">
- <a name="Locations"></a>
- <a name="SEC57"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC56"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC58"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC42"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t58"></a> 3.6 追踪位置-Tracking Locations </h2>
- <p>虽然语法规则和语义值对于编写功能完善的分析器来说足够用了,
- 但是处理一些额外的信息特别是符号位置的信息也是非常有用的.
- </p>
- <p>处理位置的方法由一个数据类型和规则被匹配时执行的动作定义的.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC58">3.6.1 位置的数据类型-Data Type of Locations</a></td><td> </td><td align="left" valign="top"> 描述位置的数据类型.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC59">3.6.2 动作和位置-Actions and Locations</a></td><td> </td><td align="left" valign="top"> 在动作中使用位置.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC60">3.6.3 位置的默认动作-Default Action for Locations</a></td><td> </td><td align="left" valign="top"> 定义了一个计算位置的通用方法.
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Location-Type"></a>
- <a name="SEC58"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC57"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC59"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC57"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]&lt;/td>
- </td><td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t59"></a> 3.6.1 位置的数据类型-Data Type of Locations </h3>
- <p>由于所有的记号和组总是使用相同的类型,
- 定义一个位置的数据类型要比定义语义值的简单的多.
- </p>
- <p>位置的类型由一个名为<code>YYLTYPE</code>的宏定义.
- 当<code>YYLTYPE</code>没有被定义的时候,
- Bison使用含有四个成员的结构体作为默认的定义:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">typedef struct YYLTYPE
- {
- int first_line; /* 第一行 */
- int first_column; /* 第一列 */
- int last_line; /* 最后一行 */
- int last_column; /* 最后一列 */
- } YYLTYPE;
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Actions-and-Locations"></a>
- <a name="SEC59"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC58"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC60"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC57"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t60"></a> 3.6.2 动作和位置-Actions and Locations </h3>
- <p>动作不仅仅是为了定义语言的语义,
- 它还可以使用位置描述输出的分析器的行为.
- </p>
- <p>最明显的为语法组建立位置的方法与计算语义值的方法相似.
- 在一个给定的规则中,
- 多种结构可以用于访问被匹配元素的位置.
- 右手端第<var>n</var>个部件的位置是<code>@<var>n</var></code>
- 而左边的组的位置是<code>@$</code>.
- </p>
- <p>这是一个基本的使用位置的默认数据类型的例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp: …
- | exp '/' exp
- {
- @$.first_column = @1.first_column;
- @$.first_line = @1.first_line;
- @$.last_column = @3.last_column;ip
- @$.last_line = @3.last_line;
- if ($3)
- $$ = $1 / $3;
- else
- {
- $$ = 1;
- fprintf (stderr,
- "Division by zero, l%d,c%d-l%d,c%d",
- @3.first_line, @3.first_column,
- @3.last_line, @3.last_column);
- }
- }
- </pre></td></tr></tbody></table>
- <p>就像对语义值一样,有一个每当规则被匹配时的位置的默认动作.
- 它将<code>@$</code>的开始设置为第一个符号的开始并将<code>@$</code>的末尾设为最后一个符号的末尾.
- </p>
- <p>可以通过使用这个默认的动作来实现位置追踪的全自动.
- 上面的例子可以简单地这样重写:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp: …
- | exp '/' exp
- {
- if ($3)
- $$ = $1 / $3;
- else
- {
- $$ = 1;
- fprintf (stderr,
- "Division by zero, l%d,c%d-l%d,c%d",
- @3.first_line, @3.first_column,
- @3.last_line, @3.last_column);
- }
- }
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Location-Default-Action"></a>
- <a name="SEC60"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC59"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC61"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC57"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t61"></a> 3.6.3 位置的默认动作-Default Action for Locations </h3>
- <p>实际上,动作并不是计算位置的最好地方.
- 由于位置比语义值更普遍,
- 所以在输出的分析器里有用来重定义每个规则的默认动作(注:对位置的)的空间.
- <code>YYLLOC_DEFAULT</code>宏每当一个规则被匹配而关联的动作尚未执行之前被调用.
- 当处理一个语法错误要计算错误的位置的时候,它也会被调用.
- </p>
- <p>大多数时候,
- 这个宏足以胜过语义动作中专注于位置的代码.
- </p>
- <p><code>YYLOC_DEFAULT</code>宏带有三个参数.
- 第一个是组(计算结果)的位置.
- 当匹配一个规则时,
- 第二个参数标识了正在匹配的规则的所有右端元素的位置,
- 第三个参数是规则右端元素的大小;
- 当处理一个语法错误的时候,
- 第二个参数标识了在错误处理中丢弃的符号的位置,
- 第三个参数是丢弃符号的数量.
- </p>
- <p><code>YYLOC_DEFAULT</code>默认地被这样定义:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample"># define YYLLOC_DEFAULT(Current, Rhs, N) /
- do /
- if (N) /
- { /
- (Current).first_line = YYRHSLOC(Rhs, 1).first_line; /
- (Current).first_column = YYRHSLOC(Rhs, 1).first_column; /
- (Current).last_line = YYRHSLOC(Rhs, N).last_line; /
- (Current).last_column = YYRHSLOC(Rhs, N).last_column; /
- } /
- else /
- { /
- (Current).first_line = (Current).last_line = /
- YYRHSLOC(Rhs, 0).last_line; /
- (Current).first_column = (Current).last_column = /
- YYRHSLOC(Rhs, 0).last_column; /
- } /
- while (0)
- </pre></td></tr></tbody></table>
- <p>当<var>k</var>是正数的时候,
- 函数<code>YYRHSLOC (rhs,k)</code>返回的是第<var>k</var>个符号的位置.
- 当<var>k</var>和位置<var>n</var>都为零的时候,
- <code>YYRHSLOC(rhs,k)</code>返回的是刚刚被归约的符号的位置.
- </p>
- <p>当要自己定义宏<code>YYLLOC_DEFAULT</code>的时候,你要考虑以下几点:
- </p>
- <ul>
- <li>
- 所有的参数应该不受左端/右端的限制.
- 然而,只有第一个(结果)应该被<code>YYLOC_DEFAULT</code>修改.
- </li><li>
- 出于与语义动作一致性的考虑,
- 右手端有效索引的范围应该是从1到<var>n</var>.
- 当<var>n</var>是0的时候,只有0是有效索引并且它引用的是归约前的那个符号.
- 在错误处理中,<var>n</var>总是正数.
- </li><li>
- 因为实际的参数可能不在括号内,
- 如果需要的话,你应该加参数放在括号内.
- 同样地,当你的宏后紧跟一个分号时,
- 它应该被展开成可作为单独语句使用的东西.
- </li></ul>
- <hr size="6">
- <a name="Declarations"></a>
- <a name="SEC61"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC60"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC62"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC42"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t62"></a> 3.7 Bison声明-Bison Declarations </h2>
- <p><em>Bison声明(Bison declarations)</em>部分定义了用来描述语法的符号和语义值的数据类型.
- 参阅 <a href="#SEC48">符号-Symbols</a>.
- </p>
- <p>所有符号类型名称(但不是如<code>'+'</code>和<code>'*'</code>的单字符记号)必须被声明.
- 如果你要指明非终结符语义值的数据类型的话,那么它们也必须被声明
- (参阅<a href="#SEC53">多种值类型-More Than One Value Type</a>一章).
- </p>
- <p>默认地,文件的第一个规则也指明了开始符号.
- 如果你要其它的符号作为开始符号,你必须显示显式地声明它.
- (参阅<a href="#SEC7">语言与上下文无关文法-Language and Context-Free Grammars</a>一章)
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC62">3.7.1 符号类型名称-Token Type Names</a></td><td> </td><td align="left" valign="top"> 声明终结符
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC63">3.7.2 操作符优先级-Operator Precedence</a></td><td> </td><td align="left" valign="top"> 声明终结符的优先级和结合性
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC64">3.7.3 值类型集-The Collection of Value Types</a></td><td> </td><td align="left" valign="top"> 声明一组语义值类型
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC65">3.7.4 非终结符-Nonterminal Symbols</a></td><td> </td><td align="left" valign="top"> 声明非终结语义值的类型
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC66">3.7.5 在分析执行前执行一些动作-Performing Actions before Parsing</a></td><td> </td><td align="left" valign="top"> 在分析开始前执行的代码
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC67">3.7.6 释放被丢弃的符号-Freeing Discarded Symbols</a></td><td> </td><td align="left" valign="top"> 声明如何释放符号
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC68">3.7.7 消除冲突警告-Suppressing Conflict Warnings</a></td><td> </td><td align="left" valign="top"> 消除分析冲突时的警告
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC69">3.7.8 开始符号-The Start-Symbol</a></td><td> </td><td align="left" valign="top"> 指明开始符号
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC70">3.7.9 纯(可重入)分析器-A Pure (Reentrant) Parser</a></td><td> </td><td align="left" valign="top"> 请求一个可重入的分析器
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC71">3.7.10 Bison声明总结-Bison Declaration Summary</a></td><td> </td><td align="left" valign="top"> 一个所有Bison声明的总结
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Token-Decl"></a>
- <a name="SEC62"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC61"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC63"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC61"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t63"></a> 3.7.1 符号类型名称-Token Type Names </h3>
- <p>声明符号类型(终结符)的最基本的方法如下:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%token <var>name</var>
- </pre></td></tr></tbody></table>
- <p>Bison会在分析器中将这个声明转换成<code>#define</code>指令
- 以便<code>yylex</code>(如果在这个文件中使用了它)
- 可以是用名称<var>name</var>代表这个记号类型码.
- </p>
- <p>另外,如果你要指明结合性和优先级,
- 你可以使用<code>%left</code>,<code>%right</code>或者<code>%nonassoc</code>
- 代替<code>%token</code>.
- 参阅 <a href="#SEC63">操作符优先级-Operator Precedence</a>.
- </p>
- <p>你可以依靠附加一个十进制活十六进制整数紧跟着记号名称来显式地指定
- 一个符号类型的数字码.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%token NUM 300
- %token XNUM 0x12d // a GNU extension 一个GNU扩展
- </pre></td></tr></tbody></table>
- <p>然而,我们通常最好让Bison选择所有记号类型的数字码.
- Bison会自动地选择互不冲突或不与其它字符冲突的码.
- </p>
- <p>当栈类型是一个联合体的时候,
- 你必须使用<code>%token</code>或者其它记号声明来指明记号的语义值类型.
- 语义值类型由中括号分隔.
- (参阅<a href="#SEC53">多种值类型-More Than One Value Type</a>一章).
- </p>
- <p>例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%union { /* define stack type */ /* 定义栈类型 */
- double val;
- symrec *tptr;
- }
- %token <val> NUM /* define token NUM and its type */ /* 定义一个记号NUM和它的数据类型 */
- </pre></td></tr></tbody></table>
- <p>将文字串写在<code>%token</code>声明的结尾,
- 你可以把一个符号类型名称关联到文字串记号上.
- 例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%token arrow "=>"
- </pre></td></tr></tbody></table>
- <p>例如,一个C语言语法可以用同等的文字串记号指明这些名称
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%token <operator> OR "||"
- %token <operator> LE 134 "<="
- %left OR "<="
- </pre></td></tr></tbody></table>
- <p>一旦你使文字串和符号名称等价,
- 你可以在以后的声明或者语法规则中交替地使用它们.
- <code>yylex</code>函数可以使用符号名称或者文字串来获得符号类型数字码.
- (参阅<a href="#SEC76">调用惯例-Calling Convention</a>一章).
- </p>
- <hr size="6">
- <a name="Precedence-Decl"></a>
- <a name="SEC63"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC62"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC64"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC61"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t64"></a> 3.7.2 操作符优先级-Operator Precedence </h3>
- <p>使用<code>%left</code>,<code>%right</code>或者<code>%nonassoc</code>
- 可以一次声明一个记号并指明它的优先级和结合性.
- 这些被称做<em>优先级声明(precedence declarations)</em>.
- 获取更多这方面的信息,参阅 <a href="#SEC85">操作符优先级-Operator Precedence</a>.
- </p>
- <p>优先级的声明与<code>%token</code>的声明相同,或者是
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%left <var>symbols</var>…
- </pre></td></tr></tbody></table>
- <p>或者是
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%left <<var>type</var>> <var>symbols</var>…
- </pre></td></tr></tbody></table>
- <p>这些声明都与<code>%token</code>的目的相同.
- 但是额外地,它们还指明了<var>symbols</var>的结合性和相对优先级:
- </p>
- <ul>
- <li>
- 操作符的结合性决定了如何重复使用嵌套的操作符:
- <samp>`<var>x</var> <var>op</var> <var>y</var> <var>op</var> <var>z</var>'</samp>
- 是先组合<var>x</var>和<var>y</var>,还是先组合<var>y</var>和<var>z</var>.
- <code>%left</code>指明左结合性(先组合<var>x</var>和<var>y</var>)而
- <code>%right</code>指明了有结合性(先组合<var>y</var>和<var>z</var>).
- <code>%nonassoc</code>指明了无结合性,即<samp>`<var>x</var> <var>op</var> <var>y</var> <var>op</var> <var>z</var>'</samp>
- 被认为是一个语法错误.
- </li><li>
- 一个操作符的优先级决定了它如何与另外的操作符嵌套使用.
- 在一个优先级声明中声明的所有记号有相同的优先级,
- 如何嵌套使用它们取决于它们的结合性.
- 当两个记号在不同的优先级声明中,稍晚声明的拥有更高的优先级,并且先被组合.
- </li></ul>
- <hr size="6">
- <a name="Union-Decl"></a>
- <a name="SEC64"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC63"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC65"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC61"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t65"></a> 3.7.3 值类型集-The Collection of Value Types </h3>
- <p><code>%union</code>声明指明了语义值全部可能的数据类型集.
- 关键字<code>%union</code>后紧跟包含了C语言<code>union</code>同样的东西的一对大括号.
- </p>
- <p>例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%union {
- double val;
- symrec *tptr;
- }
- </pre></td></tr></tbody></table>
- <p>这说明了两个可选择的类型是<code>double</code>和<code>symrec*</code>.
- 它们被赋予了名称<code>val</code>和<code>tptr</code>;
- 这些名称用于在<code>%toke</code>和<code>%type</code>声明中为终结符或非终结符选择一个类型.
- (参阅<a href="#SEC65">非终结符-Nonterminal Symbols</a>一章).
- </p>
- <p>作为一个<acronym>POSIX</acronym>扩展,一个标志被允许紧跟在<code>union</code>后.
- 例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%union value {
- double val;
- symrec *tptr;
- }
- </pre></td></tr></tbody></table>
- <p>指明了联合题标志<code>value</code>,所以相应的C类型为<code>union value</code>.
- 如果你不知名一个标志,它默认地就为<code>YYSTYPE</code>.
- </p>
- <p>我们应该注意到,并不像C语言中的<code>union</code>声明一样,
- 在Bison中,你不需要在大括号结束的时候写上分号.
- </p>
- <hr size="6">
- <a name="Type-Decl"></a>
- <a name="SEC65"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC64"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC66"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC61"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t66"></a> 3.7.4 非终结符-Nonterminal Symbols </h3>
- <p>当你使用<code>%union</code>指明多种值类型的时候,
- 你必须为每个要使用其语义值的非终结符指明一个值类型.
- 通过<code>%type</code>可以做到这一点,像这样:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%type <<var>type</var>> <var>nonterminal</var>…
- </pre></td></tr></tbody></table>
- <p>这里的<var>nonterminal</var>是非终结符的名称,
- <var>type</var>是在<code>%union</code>中给定的名称来指定该非终结符的语义值类型.
- (参阅<a href="#SEC64">值类型集-The Collection of Value Types</a>一章).
- 你可以给任意多数量的非终结符以相同的数据类型,
- 如果它们有相同的值类型的话.
- 这时我们要使用空白来分隔符号名称.
- </p>
- <p>你也可以声明一个终结符的值类型.
- 为终结符使用相同的<code><<var>type</var>></code>结构可以做到这一点.
- 所有种类的记号声明都允许使用<code><<var>type</var>></code>.
- </p>
- <hr size="6">
- <a name="Initial-Action-Decl"></a>
- <a name="SEC66"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC65"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC67"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC61"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align=""left"" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t67"></a> 3.7.5 在分析执行前执行一些动作-Performing Actions before Parsing </h3>
- <p>有些时候,你的分析器需要在分析之前执行一些初始化.
- 通过使用<code>%initial-action</code>指令指定这种代码.
- </p>
- <dl>
- <dt><u>指令:</u> <b>%initial-action</b><i> { <var>code</var> }</i>
- <a name="IDX25"></a>
- </dt>
- <dd><a name="IDX26"></a>
- <p>声明了<var>code</var>必须在每次调用<code>yyparse</code>之前被调用.
- <var>code</var>可以使用<code>$$</code>和<code>@$</code> -- 超前扫描记号的初始值和位置 -- 和
- <code>%parse-param</code>.
- </p></dd></dl>
- <p>例如,如果你的位置需要使用一个文件名,你可以使用
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%parse-param { const char *filename };
- %initial-action
- {
- @$.begin.filename = @$.end.filename = filename;
- };
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Destructor-Decl"></a>
- <a name="SEC67"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC66"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC68"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC61"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t68"></a> 3.7.6 释放被丢弃的符号-Freeing Discarded Symbols </h3>
- <p>分析器可能会丢弃一些符号.
- 例如,在错误恢复中(参阅<a href="#SEC96">错误恢复-Error Recovery</a>一章),
- 分析器丢弃已经压入栈中为难符号,
- 以及来自剩余文件的为难记号直到脱离错误恢复状态。
- 如果这些符号带有堆信息,这些内存就会出现丢失.
- 然而这种行为对于例如编译器一样的批分析器是可以容忍的,
- 但不适用于可能"没有终点"的分析器如shells或者通信协议的实现.
- </p>
- <p><code>%destructor</code>指令允许定义当一个符号被丢弃时调用的代码.
- </p>
- <dl>
- <dt><u>指令:</u> <b>%destructor</b><i> { <var>code</var> } <var>symbols</var></i>
- <a name="IDX27"></a>
- </dt>
- <dd><a name="IDX28"></a>
- <p>声明了<var>code</var>必须在每次分析器丢弃<var>symbols</var>时调用.
- <var>code</var>应该使用<code>$$</code>来指明与<var>symbols</var>关联的语义值.
- 其余的分析器参数也是可用的.
- (参阅<a href="#SEC74">分析器函数<code>yyparse</code>-The Parser Funcation <code>yyparse</code></a>一章).
- </p>
- <p><strong>警告:</strong>对于版本1.875来说,这个特征仍然是实验性的.
- 主要原因是没有足够的用户反馈.
- 相应的语法仍可能会改变.
- </p></dd></dl>
- <p>例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">%union
- {
- char *string;
- }
- %token <string> STRING
- %type <string> string
- %destructor { free ($$); } STRING string
- </pre></td></tr></tbody></table>
- <p>保证了当一个<code>STRING</code>或者一个<code>string</code>将被丢弃时,
- 相关的内存也会被释放.
- </p>
- <p>注意到在将来,Bison会认为在动作中没有提及的右端成员也可以被销毁.
- 例如,在:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">comment: "/*" STRING "*/";
- </pre></td></tr></tbody></table>
- <p>分析器有权销毁<code>string</code>的语义值.
- 当然,这不适用于默认动作:
- 比较:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">typeless: string; // $$ = $1 does not apply; $1 is destroyed.
- typefull: string; // $$ = $1 applies, $1 is not destroyed.
- </pre></td></tr></tbody></table>
- <br>
- <a name="IDX29"></a>
- <p><em>被丢弃的符号(Discarded symbols)</em> 是如下几种:
- </p>
- <ul class="toc">
- <li>
- 在第一阶段的错误恢复中栈弹出符号.
- </li><li>
- 在第二阶段错误恢复中要到达的终结符.
- </li><li>
- 当分析器异常终止时(或者通过显式地调用<code>YYABORT</code>,或者一系列失败的错误恢复),
- 当前的超前扫描记号.
- </li></ul>
- <hr size="6">
- <a name="Expect-Decl"></a>
- <a name="SEC68"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC67"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC69"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC61"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t69"></a> 3.7.7 消除冲突警告-Suppressing Conflict Warnings </h3>
- <p>通常情况下,当出现任何的冲突的时候,Bison会作出警告
- (参阅<a href="#SEC84">移进/归约冲突-Shift/Recude Conflicts</a>一章),
- 但是大多数真正的语法含有的是可以通过预测的方法解决并且很难消除的无害的移进/归约冲突.
- 除非冲突的数量改变,我们渴望消除关于这些冲突的警告.
- 你可以使用<code>%expect</code>声明做到这一点.
- </p>
- <p>声明看起来是这样:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%expect <var>n</var>
- </pre></td></tr></tbody></table>
- <p>这里的<var>n</var>是一个十进制整数.
- 这个声明表明:如果有<var>n</var>个移进/归约冲突并且没有归约/归约冲突,
- Bison并不会作出警告.
- 如果有更多或更少的冲突或者有归约/归约冲突,Bison仍会作出警告.
- </p>
- <p>对于通常的<acronym>LALR</acronym>(1)分析器,归约/归约冲突更加棘手并且应该完全消除.
- Bison对于这些分析器总会报告归约/归约冲突.
- 对于<acronym>GLR</acronym>分析器来说,移进/归约冲突和归约/归约冲突都是很平常的情况(否则,就没有必要使用<acronym>GLR</acronym>分析).
- 因此,在<acronym>GLR</acronym>分析器中使用如下声明指定一个预期数目的归约/归约冲突也是可以的:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%expect-rr <var>n</var>
- </pre></td></tr></tbody></table>
- <p>通常来说,使用<code>%expect</code>包括了这些步骤:
- </p>
- <ul>
- <li>
- 不使用<code>%expect</code>而编译你的代码.
- 使用<samp>`-v'</samp>选项获取冲突发生的列表.
- Bison也会打印冲突的个数.
- </li><li>
- 检查每一个冲突来确定Bison默认的解决方法是你真正想要的.
- 如果不是,重写语法并回到开始.(注:第一步)
- </li><li>
- 添加一个<code>%expect</code>声明,从Bison打印的列表复制一个冲突的数目.
- </li></ul>
- <p>现在,如果你不更改冲突的数目,Bison会停止打扰你.
- 但是如果你改变了语法导致了更多或更少的冲突,
- Bison仍会警告你.
- </p>
- <hr size="6">
- <a name="Start-Decl"></a>
- <a name="SEC69"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC68"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC70"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC61"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t70"></a> 3.7.8 开始符号-The Start-Symbol </h3>
- <p>Bison默认地认为在语法叙述部分指明的第一个非终结符为语法的开始符号.
- 程序员可以使用如下的<code>%start</code>声明来克服这个约束
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%start <var>symbol</var>
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Pure-Decl"></a>
- <a name="SEC70"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC69"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC71"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC61"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t71"></a> 3.7.9 纯(可重入)分析器-A Pure (Reentrant) Parser </h3>
- <p>一个<em>可重入(reentrant)</em>程序是在执行过程中不变更的程序;
- 换句话说,它全部由<em>纯(pure)</em>(只读)代码构成.
- 当可异步执行的时候,可重入特性非常重要.
- 例如,从一个句柄调用不可重入程序可能是不安全的.
- 在带有多线程控制的系统中,
- 一个非可重入程序必须只能被互锁(interlocks)调用.
- </p>
- <p>通常地,Bison生成不可重入的分析器.
- 这对大多数情况足够用了,并且这种分析器提供了与Yacc的兼容性.
- (由于在<code>yylex</code>,<code>yylval</code>和<code>yyloc</code>通信中使用了静态分配的变量,
- 标准Yacc界面是不可重入的).
- </p>
- <p>作为另外一个选择,你可以声称一个纯,可重入的分析器.
- Bison声明<code>%pure-parse</code>表明你要产生一个可重入的分析器.
- 这个声明是这样:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%pure-parser
- </pre></td></tr></tbody></table>
- <p>这样做的结果是<code>yylval</code>和<code>yylloc</code>的通信变量变为一个<code>yyparse</code>中的局部变量,
- 并且对词法分析器函数<code>yylex</code>使用了不同的调用惯例.
- 参阅 <a href="#SEC79">纯分析器的调用惯例-Calling Convention for Pure Parsers</a>.以获取更多信息.
- 变量<code>yynerrs</code>也变为在<code>yyparse</code>中的局部变量
- (参阅<a href="#SEC80">错误报告函数<code>yyerror</code>-The Error Reporting Funcation <code>yyerror</code></a>一章).
- <code>yyparse</code>自己的调用惯例并没有改变.
- </p>
- <p>分析器是否为纯分析器与语法规则毫不相关.
- 你可以从任何有效的语法产生一个纯分析器或者不可重入分析器.
- </p>
- <hr size="6">
- <a name="Decl-Summary"></a>
- <a name="SEC71"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC70"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC72"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC61"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t72"></a> 3.7.10 Bison声明总结-Bison Declaration Summary </h3>
- <p>这是一个用来定义语法的声明的总结:
- </p>
- <dl>
- <dt><u>指令:</u> <b>%union</b>
- <a name="IDX30"></a>
- </dt>
- <dd><p>声明了语义值可能拥有的数据类型集.
- (参阅<a href="#SEC64">值类型集-The Collection of Value Types</a>一章).
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%token</b>
- <a name="IDX31"></a>
- </dt>
- <dd><p>声明一个未指定优先级和结合性的终结符(符号类型名称)
- (参阅<a href="#SEC62">符号类型名称-Token Type Names</a>一章).
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%right</b>
- <a name="IDX32"></a>
- </dt>
- <dd><p>声明一个右结合的终结符(符号类型名称)
- (参阅<a href="#SEC63">操作符优先级-Operator Precedence</a>一章).
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%left</b>
- <a name="IDX33"></a>
- </dt>
- <dd><p>声明一个左结合的终结符(符号类型名称)
- (参阅<a href="#SEC63">操作符优先级-Operator Precedence</a>一章).
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%nonassoc</b>
- <a name="IDX34"></a>
- </dt>
- <dd><p>声明一个没有结合性的终结符(符号类型名称).
- (参阅<a href="#SEC63">操作符优先级-Operator Precedence</a>一章).
- 按结合性的方法使用它是一个语法错误.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%type</b>
- <a name="IDX35"></a>
- </dt>
- <dd><p>声明非终结符的语义值类型.
- (参阅<a href="#SEC65">非终结符-Nonterminal Symbols</a>一章).
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%start</b>
- <a name="IDX36"></a>
- </dt>
- <dd><p>指明了语法的开始符号
- (参阅<a href="#SEC69">开始符号-The Start-Symbol</a>一章).
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%expect</b>
- <a name="IDX37"></a>
- </dt>
- <dd><p>声明了预期的移进/归约冲突的个数.
- (参阅<a href="#SEC68">消除冲突警告-Suppressing Conflict Warnings</a>一章).
- </p></dd></dl>
- <br>
- <p>为了改变<code>bison</code>的行为,使用如下指令
- </p>
- <dl>
- <dt><u>指令:</u> <b>%debug</b>
- <a name="IDX38"></a>
- </dt>
- <dd><p>在分析器文件中,如果<code>YYDEBUG</code>未定义,将其定义为1,
- 以便调式机制被编译.
- </p></dd></dl>
- <p>参阅 <a href="#SEC103">追踪你的分析器</a>.
- </p>
- <dl>
- <dt><u>指令:</u> <b>%defines</b>
- <a name="IDX39"></a>
- </dt>
- <dd><p>编写一个包括记号类型定义和其它声明的宏定义头文件.
- 如果分析器输出文件是<tt>`<var>name</var>.c'</tt>,
- 那么这个头文件就是<tt>`<var>name</var>.h'</tt>.
- </p>
- <p>除非<code>YYSTYPE</code>已经被定义成了一个宏,
- 否则输出头文件会声明<code>YYSTYPE</code>.
- 因此,如果你使用了需要其它定义的<code>%union</code>部件
- (参阅 <a href="#SEC53">多种值类型-More Than One Value Type</a>,)
- 或者你已经定义了宏<code>YYSTYPE</code>
- (参阅<a href="#SEC52">语义值的数据类型-Data Types of Semantic Values</a>一章),
- 你需要安排这些定义使它们在所有模块的前页,
- 例如,把它们放入一个你的分析器和任何其它模块都包含的头文件中.
- </p>
- <p>除非你的分析器是一个纯分析器,
- 否则输出的头文件将<code>yylval</code>声明为一个外部变量.
- 参阅 <a href="#SEC70">一个纯(可重入)分析器-A Pure (Reentrant) Parser</a>.
- </p>
- <p>如果你也使用了位置,
- 输出头文件使用声明与<code>YYSTYPE</code>和<code>yylval</code>类似的协议声明<code>YYLTYPE</code>和<code>yylloc</code>.
- 参阅 <a href="#SEC57">追踪位置-Semantic Values of Tokens</a>.
- </p>
- <p>如果你希望将<code>yylex</code>的定义放在一个另外的源文件中的话,
- 这个输出的头文件是通常必须的,
- 因为<code>yylex</code>需要引用头文件中提供的声明和记号类型码.
- 参阅 <a href="#SEC77">记号的语义值-Semantic Values of Tokens</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%destructor</b>
- <a name="IDX40"></a>
- </dt>
- <dd><p>指明了分析器如何回收同丢弃的符号相关联的内存.
- 参阅 <a href="#SEC67">释放丢弃的符号-Freeing Discarded Symbols</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%file-prefix="<var>prefix</var></b><i>"</i>
- <a name="IDX41"></a>
- </dt>
- <dd><p>指定一个所有Bison输出文件的前缀,就好像输入文件名为<tt>`<var>prefix</var>.y'</tt>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%locations</b>
- <a name="IDX42"></a>
- </dt>
- <dd><p>产生处理位置的代码(参阅<a href="#SEC81">使用动作的特殊特征-Special Features for Use in Actions</a>一章).
- 一旦语法使用了<samp>`@<var>n</var>'</samp>记号,这种模式就会被激活.
- 但是如果你的语法没有用到它,使用<samp>`%locations'</samp>可以获得更精确的语法错误信息.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%name-prefix="<var>prefix</var></b><i>"</i>
- <a name="IDX43"></a>
- </dt>
- <dd><p>重命名分析器使用的外部符号以便它们以<var>prefix</var>开始,而不是<samp>`yy'</samp>.
- 符号被重命名的精确列表是:
- <code>yyparse</code>, <code>yylex</code>, <code>yyerror</code>, <code>yynerrs</code>,
- <code>yylval</code>, <code>yylloc</code>, <code>yychar</code>, <code>yydebug</code>, 和可能使用的
- <code>yylloc</code>.
- 例如, 如果你使用<samp>`%name-prefix="c_"'</samp>, 名称就会变为 <code>c_parse</code>, <code>c_lex</code>等等.
- 参阅 <a href="#SEC72">同一个程序中的多个分析器-Multiple Parsers in the Same Program</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%no-parser</b>
- <a name="IDX44"></a>
- </dt>
- <dd><p>在分析器文件中不包含任何C代码,仅仅声称表格.
- 分析器文件仅仅包括<code>#define</code>指令和静态变量声明.
- </p>
- <p>这个选项也告诉Bison将语法动作的C代码以<code>switch</code>语句的形式
- 写入一个名为<tt>`<var>filename</var>.act'</tt>的文件.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%no-lines</b>
- <a name="IDX45"></a>
- </dt>
- <dd><p>在分析器文件中不生成任何<code>#line</code>预处理指令.
- Bison通常将这些指令写入分析器文件以便
- C编译器和调式器(debugger)可以将错误和目标代码与你的源文件(语法文件)关联起来.
- 这个指令使它们关联错误到分析器文件并将它视为一个独立的源文件.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%output="<var>filename</var></b><i>"</i>
- <a name="IDX46"></a>
- </dt>
- <dd><p>将分析器文件指定为<var>filename</var>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%pure-parser</b>
- <a name="IDX47"></a>
- </dt>
- <dd><p>请求一个纯(可重入)分析器程序(参阅<a href="#SEC70">一个纯(可重入)分析器-A Pure (Reentrant) Parser</a>一章).
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%token-table</b>
- <a name="IDX48"></a>
- </dt>
- <dd><p>在分析器文件中生成一个记号名称数组.
- 数组的名称是<code>yytname</code>;
- <code>yytname[<var>i</var>]</code>是Bison内部数字码为<var>i</var>的记号的名称.
- 前三个<code>yytname</code>的元素与预定义记号<code>"$end"</code>,<code>"error"</code>,
- 和<code>"$undefined"</code>相对应;
- 在这几个符号之后便是语法文件中定义的符号.
- </p>
- <p>对于单字符记号和文字串记号,
- 表格中的名称包含单引号或者双引号字符:
- 例如,<code>"'+'"</code>是一个单字符记号而 <code>"/"<=/""</code>是一个文字串记号.
- 字符串记号的所有字符一字不差地出现在符号表中;
- 即使双引号字符也不跳过.
- 例如,如果记号包含了三个字符<samp>`*"*'</samp>,在<code>yytname</code>的字符串为<samp>`"*"*"'</samp>.
- (在C语言中,那应被写成<code>"/"*/"*/""</code>).
- </p>
- <p>当你指定了<code>%token-table</code>,Bison也生成了<code>YYNTOKENS</code>, <code>YYNNTS</code>, and
- <code>YYNRULES</code>, 和<code>YYNSTATES</code>的宏定义:
- </p>
- <dl compact="compact">
- <dt> <code>YYNTOKENS</code></dt>
- <dd><p>最高记号数字加1
- </p></dd>
- <dt> <code>YYNNTS</code></dt>
- <dd><p>非终结符的数量
- </p></dd>
- <dt> <code>YYNRULES</code></dt>
- <dd><p>语法规则的数量
- </p></dd>
- <dt> <code>YYNSTATES</code></dt>
- <dd><p>分析器状态的数量(参阅<a href="#SEC91">分析器状态-Parser States</a>一章).
- </p></dd>
- </dl>
- </dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%verbose</b>
- <a name="IDX49"></a>
- </dt>
- <dd><p>向一个额外的输出文件写入包括分析器状态和对在那个状态的每一种超前扫描记号做了些什么的详细描述.
- 参阅 <a href="#SEC102">理解你的分析器-Understanding You Parser</a>,以获取更多信息.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%yacc</b>
- <a name="IDX50"></a>
- </dt>
- <dd><p>假定给定了<samp>`--yacc'</samp>选项,也就是模拟Yacc,包括它的命名惯例.
- 参阅 <a href="#SEC105">Bison选项-Bison Options</a>,获得更多信息.
- </p></dd></dl>
- <hr size="6">
- <a name="Multiple-Parsers"></a>
- <a name="SEC72"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC71"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC73"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC42"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC73"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t73"></a> 3.8 在同一个程序中使用多个分析器-Multiple Parsers in the Same Program </h2>
- <p>大多数程序使用Bison仅分析一种语言,因此仅包含一个Bison分析器.
- 但是如果你要在程序中分析多种语言该怎么办?
- 这样的话,你需要避免在不同的<code>yyparse</code>,<code>yylval</code>等等
- 不同定义的名称之间的冲突.
- </p>
- <p>要做到这一点,最简单的方法就是使用<samp>`-p <var>prefix</var>'</samp>选项
- (参阅<a href="#SEC104">调用Bison-Invking Bison</a>一章).
- 这个选项重命名了接口函数和Bison分析器变量,
- 使它们以<var>prefix</var>开头而不是<samp>`yy'</samp>.
- 你可以使用这个选项给予每个分析器互不冲突的独特的名称.
- </p>
- <p>重命名符号的精确列表为: <code>yyparse</code>, <code>yylex</code>,
- <code>yyerror</code>, <code>yynerrs</code>, <code>yylval</code>, <code>yylloc</code>,
- <code>yychar</code>和<code>yydebug</code>.
- 例如,如果你使用了<samp>`-p c'</samp>,
- 名称就变为<code>cparse</code>,<code>clex</code>等等.
- </p>
- <p><strong>所有其它与Bison相关的变量和宏定义并没有被重命名.</strong>
- 这些其它的东西并不是全局的;
- 所以在不同的分析器中使用相同的名称不不会产生冲突.
- 例如,<code>YYSTYPE</code>并未被重命名,
- 但是在不同的分析器中以不同的方式不冲突地定义
- (参阅<a href="#SEC52">语义值的数据类型-Data Types of Semantic Values</a>一章).
- </p>
- <p><samp>`-p'</samp>选项靠向分析器文件的开头添加宏定义的方式工作.
- 定义<code>yyparse</code>为<code><var>prefix</var>parse</code>,等等.
- 这种方式高效地在整个分析器文件中相互替代名称.
- </p>
- <hr size="6">
- <a name="Interface"></a>
- <a name="SEC73"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC72"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC74"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC42"> << </a>][<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC82"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="chapter"><a name="t74"></a> 4. 分析器C语言接口-Parser C-Language Interface </h1>
- <p>Bison分析器实际上是一个名为<code>yyparse</code>的C语言函数.
- 这里我们描述一下<code>yyparse</code>和它需要用到的函数的接口惯例.
- </p>
- <p>你应该记住,分析器使用了很多以<samp>`yy'</samp>和<samp>`YY'</samp>开头的标识符.
- 如果你在动作或者<var>epilogue</var>部分使用了这样一个标识符(不在这个手册之中),
- 你的程序可能会遇到麻烦.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC74">4.1 分析器函数<code>yyparse</code>-The Parser Function <code>yyparse</code></a></td><td> </td><td align="left" valign="top"> 如何调用<code>yyparse</code>以及它的返回值.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC75">4.2 词法分析器函数<code>yylex</code>-The Lexical Analyzer Function <code>yylex</code></a></td><td> </td><td align="left" valign="top"> 你必提供一个读入记号的函数<code>yylex</code>.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC80">4.3 错误报告函数<code>yyerror</code>-The Error Reporting Function <code>yyerror</code></a></td><td> </td><td align="left" valign="top"> 你必须提供一个函数<code>yyerror</code>.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC81">4.4 在动作中使用的特殊特征-Special Features for Use in Actions</a></td><td> </td><td align="left" valign="top"> 在动作中使用的特殊特征.
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Parser-Function"></a>
- <a name="SEC74"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC73"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC75"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC73"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC73"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC82"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t75"></a> 4.1 分析器函数<code>yyparse</code>-The Parser Function <code>yyparse</code> </h2>
- <p>你通过调用函数<code>yyparse</code>开始进行分析.
- 这个函数读入记号,执行动作,
- 并且最后如果它遇到输入结束或者不能恢复的错误就会返回.
- 你也可以编写一个让<code>yyparse</code>立即返回不再读入的动作.
- </p>
- <dl>
- <dt><u>Function:</u> int <b>yyparse</b><i> (void)</i>
- <a name="IDX51"></a>
- </dt>
- <dd><p>如果分析成功,<code>yyparse</code>返回值为0(当遇到输入结束的时候).
- </p>
- <p>如果分析失败,返回值则为1.(当遭遇语法错误的时候).
- </p></dd></dl>
- <p>在动作中,你可以使用这些宏使<code>yyparse</code>立即返回:
- </p>
- <dl>
- <dt><u>Macro:</u> <b>YYACCEPT</b>
- <a name="IDX52"></a>
- </dt>
- <dd><a name="IDX53"></a>
- <p>立即返回0(来报告分析成功).
- </p></dd></dl>
- <dl>
- <dt><u>Macro:</u> <b>YYABORT</b>
- <a name="IDX54"></a>
- </dt>
- <dd><a name="IDX55"></a>
- <p>立即返回1(来报告分析失败).
- </p></dd></dl>
- <p>如果你使用一个可重入的分析器,
- 你还可用可重入的方式以向它传送额外的信息.
- 为了做到这一点,使用<code>%parse-param</code>声明:
- </p>
- <dl>
- <dt><u>指令:</u> <b>%parse-param</b><i> {<var>argument-declaration</var>}</i>
- <a name="IDX56"></a>
- </dt>
- <dd><a name="IDX57"></a>
- <p>表明由<code>argument-declaration</code>声明的参数
- 是一个额外的<code>yyparse</code>参数.
- <var>argument-declaration</var>在声明函数或者原型时使用.
- <var>argument-declaration</var>中最后一个标识符必须为参数名称.
- </p>
- </dd></dl>
- <p>这里有一个例子.将这些写入分析器:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%parse-param {int *nastiness}
- %parse-param {int *randomness}
- </pre></td></tr></tbody></table>
- <p>然后向这样调用分析器
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">{
- int nastiness, randomness;
- … /* Store proper data in <code>nastiness</code> and <code>randomness</code>. */
- value = yyparse (&nastiness, &randomness);
- …
- }
- </pre></td></tr></tbody></table>
- <p>在语法动作中,用类似这样的表达式来引用数据:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp: … { …; *randomness += 1; … }
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Lexical"></a>
- <a name="SEC75"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC74"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC76"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC73"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC73"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC82"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t76"></a> 4.2 词法分析器函数<code>yylex</code>-The Lexical Analyzer Function <code>yylex</code> </h2>
- <p><em>词法分析器(lexical analyzer)</em>函数,<code>yylex</code>,
- 从输入流中识别记号并将它们返回给分析器(注:语法分析器).
- Bison并不自动生成这个函数;
- 你必须编写它以备<code>yyparse</code>调用.
- 这个函数有时候也被成为词法扫描器.
- </p>
- <p>在简单的程序中,<code>yylex</code>经常定义在Bison语法文件的末尾.
- 如果<code>yylex</code>定义在另外的文件中,
- 你需要安排符号类型宏定义在那里是可见的.
- 为了做到这一点,在运行Bison的时候使用<samp>`-d'</samp>选项以便它
- 将这些宏定义写入到另外的名为<tt>`<var>name</var>.tab.h'</tt>的头文件中.
- 你可以将它包含在需要它的其它源文件中.
- 参阅 <a href="#SEC104">调用-Bison-Invoking Bison</a>.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC76">4.2.1 <code>yylex</code>的调用惯例-Calling Convention for <code>yylex</code></a></td><td> </td><td align="left" valign="top"> <code>yyparse</code>如何调用<code>yylex</code>.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC77">4.2.2 记号的语义值-Semantic Values of Tokens</a></td><td> </td><td align="left" valign="top"> <code>yylex</code>是如何返回它已经读入的记号的语义值.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC78">4.2.3 记号的文字位置-Textual Locations of Tokens</a></td><td> </td><td align="left" valign="top"> 如果动作需要,<code>yylex</code>是如何返回记号的文字位置(行号,等等).
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC79">4.2.4 纯分析器的调用惯例-Conventions for Pure Parsers</a></td><td> </td><td align="left" valign="top"> 纯分析器的调用惯例有何不同
- (参阅<a href="#SEC70">一个纯(可重入)分析器-A Pure (Reentrant) Parser</a>一章).
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Calling-Convention"></a>
- <a name="SEC76"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC75"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC77"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC73"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC75"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC82"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t77"></a> 4.2.1 <code>yylex</code>的调用惯例-Calling Convention for <code>yylex</code> </h3>
- <p><code>yylex</code>的返回值必须是它刚刚发现的记号类型的正值数字码;
- 0或负值代表着输入的结束.
- </p>
- <p>当一个记号在语法规则中由它的名称引用时,
- 这个名称在语法文件中是一个宏,
- 这个宏定义了那个记号类型的恰当的数字码.
- 所以<code>yylex</code>可是使用这个名称来指明那个记号类型.
- 参阅 <a href="#SEC48">符号-Symbols</a>.
- </p>
- <p>当一个记号在语法文件中由一个字符引用时,
- 那个字符的数字码同样也是那个记号类型的数字码.
- 所以<code>yylex</code>可以简单地返回那个字符码,
- 并且可能转换为<code>unsigned char</code>以避免符号扩展.
- 但空字符绝对不能这样使用,
- 因为它的数字吗为0,
- 这意味这输入的结束.
- </p>
- <p>这里是一个展示这些东西的例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int
- yylex (void)
- {
- …
- if (c == EOF) /* Detect end-of-input. */ /* 检测到输入结束 */
- return 0;
- …
- if (c == '+' || c == '-')
- return c; /* Assume token type for `+' is '+'. */ /* 认定`+'的记号类型就是'+' */
- …
- return INT; /* Return the type of the token. */ /* 返回记号的类型 */
- …
- }
- </pre></td></tr></tbody></table>
- <p>设计这种接口的目的是为了可以不加更改地使用<code>lex</code>工具的输出<code>yylex</code>.
- </p>
- <p>如果语法使用了文字串记号,
- <code>yylex</code>决定记号类型马的方法有两种:
- </p>
- <ul>
- <li>
- 如果语法定义了文字串记号的符号名称别名,
- <code>yylex</code>可以像其它符号名称一样使用这些符号名称.
- 这种情况下,
- 语法文件中使用文字串记号对<code>yylex</code>没有影响.
- </li><li>
- <code>yylex</code>可以在<code>yytname</code>表中找到多字符记号.
- 这个记号的索引是这个记号的类型码.
- 多字符记号的名称由一个双引号,记号的字符和另外一个双引号记录在<code>yytname</code>中.
- 无论如何,记号(注:多字符记号)的字符不能是转义的;
- 它一字不差地出现在表格字符串的内容里.
- <p>这里有在<code>yytname</code>中搜索记号的代码.
- 这个代码假定记号的字符存储在<code>token_buffer</code>中.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">for (i = 0; i < YYNTOKENS; i++)
- {
- if (yytname[i] != 0
- && yytname[i][0] == '"'
- && ! strncmp (yytname[i] + 1, token_buffer,
- strlen (token_buffer))
- && yytname[i][strlen (token_buffer) + 1] == '"'
- && yytname[i][strlen (token_buffer) + 2] == 0)
- break;
- }
- </pre></td></tr></tbody></table>
- <p><code>yytname</code>表格只在你使用了<code>%token-table</code>声明才会生成.
- 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p></li></ul>
- <hr size="6">
- <a name="Token-Values"></a>
- <a name="SEC77"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC76"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC78"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC73"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC75"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC82"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t78"></a> 4.2.2 记号的语义值-Semantic Values of Tokens </h3>
- <p>在一个普通的(不可重入)的分析器中,
- 记号的语义值必须被存放在全局变量<code>yylval</code>中.
- 当你只使用一种语义值数据类型时,
- <code>yylval</code>就是那个类型.
- 因此,如果类型为<code>int</code>(默认的),
- 你可以这样编写你的<code>yylex</code>:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example"> …
- yylval = value; /* Put value onto Bison stack. */ /* 将值放入Bison栈中 */
- return INT; /* Return the type of the token. */ /* 返回记号类型 */
- …
- </pre></td></tr></tbody></table>
- <p>当你使用多种数据类型时,
- <code>yylval</code>的类型是一个由<code>%union</code>声明组成的联合体.
- (参阅<a href="#SEC64">值类型集-The Collections of Value Types</a>一章).
- 所以,当你存储一个记号的语义值的时候,
- 你必须使用恰当的联合体成员.
- 如果<code>%union</code>声明是这样的:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%union {
- int intval;
- double val;
- symrec *tptr;
- }
- </pre></td></tr></tbody></table>
- <p>那么<code>yylex</code>中的代码应该是这样:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example"> …
- yylval.intval = value; /* Put value onto Bison stack. */ /* 将值放入Bison栈中. */
- return INT; /* Return the type of the token. */ /* 返回记号的类型 */
- …
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Token-Locations"></a>
- <a name="SEC78"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC77"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC79"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC73"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC75"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC82"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t79"></a> 4.2.3 记号的文字位置-Textual Locations of Tokens </h3>
- <p>如果你在动作中使用了<samp>`@<var>n</var>'</samp>-特征(参阅<a href="#SEC57">追踪位置-Tracking Locations</a>一章)来追踪记号和组的文字位置,
- 那么你必须在<code>yylex</code>中提供这些信息.
- <code>yyparse</code>预期在全局变量<code>yyloc</code>中找到刚刚分析的记号的文字位置.
- 所以<code>yylex</code>必须在那个变量里存放正确的数据.
- </p>
- <p>默认地,<code>yyloc</code>的值是一个结构体并且你只需要初始化将被动作使用的成员.
- 四个成员分别是<code>first_line</code>, <code>first_column</code>,
- <code>last_line</code>和 <code>last_column</code>.
- 注意到:使用这个特征会使分析器的性能显著下降.
- </p>
- <a name="IDX58"></a>
- <p><code>yyloc</code>的数据类型为<code>YYLTYPE</code>.
- </p>
- <hr size="6">
- <a name="Pure-Calling"></a>
- <a name="SEC79"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC78"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC80"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC73"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC75"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC82"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t80"></a> 4.2.4 纯分析器的调用惯例-Conventions for Pure Parsers </h3>
- <p>当你使用Bison声明<code>%pure-parser</code>要求得到一个纯,可重入的分析器,
- 全局通信变量<code>yylval</code>和<code>yylloc</code>不能继续使用.
- (参阅 <a href="#SEC70">一个纯(可重入)分析器-A Pure (Reentrant Parser</a>.)
- 在这种分析器中,两个全局变量由传递给<code>yylex</code>的指针参数取代.
- 你必须如下你声明它们,并通过这些指针存储数据最后将它们传回.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int
- yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
- {
- …
- *lvalp = value; /* Put value onto Bison stack. */ /* 将值放入Bison栈 */
- return INT; /* Return the type of the token. */ /* 返回记号类型 */
- …
- }
- </pre></td></tr></tbody></table>
- <p>如果语法们文件没有使用<samp>`@'</samp>结构引用文字位置,
- 那么类型<code>YYLTYPE</code>就不会被定义.
- 在这种情况下,省略第二个参数;
- 仅用一个参数调用<code>yylex</code>.
- </p>
- <p>如果你希望传递额外的数据到<code>yylex</code>,
- 可以是用<code>%lex-param</code>,就像<code>%parse-param</code>一样
- (参阅<a href="#SEC74">分析器函数-Parser Function</a>一章).
- </p>
- <dl>
- <dt><u>指令:</u> <b>lex-param</b><i> {<var>argument-declaration</var>}</i>
- <a name="IDX59"></a>
- </dt>
- <dd><a name="IDX60"></a>
- <p>声明<code>argument-declaration</code>是一个额外的<code>yylex</code>参数.
- </p></dd></dl>
- <p>例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%parse-param {int *nastiness}
- %lex-param {int *nastiness}
- %parse-param {int *randomness}
- </pre></td></tr></tbody></table>
- <p>导致了如下的结果:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int yylex (int *nastiness);
- int yyparse (int *nastiness, int *randomness);
- </pre></td></tr></tbody></table>
- <p>如果添加了<code>%pure-parser</code>:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int yylex (YYSTYPE *lvalp, int *nastiness);
- int yyparse (int *nastiness, int *randomness);
- </pre></td></tr></tbody></table>
- <p>最后,如果<code>%pure-parser</code>和<code>%locations</code>都被使用:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
- int yyparse (int *nastiness, int *randomness);
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Error-Reporting"></a>
- <a name="SEC80"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC79"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC81"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC73"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC73"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC82"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t81"></a> 4.3 错误报告函数<code>yyerror</code>-The Error Reporting Function <code>yyerror</code> </h2>
- <p>Bison分析器侦测到一个<em>语法错误(syntax error)</em>
- 或者一个<em>分析错误(parse error)</em>
- 每当它读入了一个不能满足任何规则的记号.
- 一个语法动作也可以使用宏<code>YYERROR</code>显式地声明一个错误
- (参阅<a href="#SEC81">使用动作的特殊特征-Special Features for Use in Actions</a>一章).
- </p>
- <p>Bison分析器期望靠调用一个名为<code>yyerror</code>的错误处理报告函数报告错误.
- 这个函数必须由你提供.
- 每当<code>yyparse</code>发现一个语法错误的时候,
- <code>yyparse</code>就会调用它.
- <code>yyparse</code>只接受一个参数.
- 对于一个语法错误,
- 显示的字符串通常是<code>"syntax error"</code>.
- </p>
- <a name="IDX61"></a>
- <p>如果你在<var>Bison declarations</var>部分
- (参阅<a href="#SEC45"><var>Bison Declarations</var>部分-The Bison Declarations Section</a>一章)
- 使用了<code>%error-verbose</code>指令,
- 那么Bison会提供更加详细而明确的错误信息而不是仅有<code>"syntax error"</code>.
- </p>
- <p>分析器可以侦测到另外一种错误:栈溢出.
- 这在输入包含非常深层次的嵌套结构时发生.
- 你很难遇到这种情况,
- 因为Bison会自动将栈容量扩展到一个很大的极限.
- 但是如果溢出发生,
- <code>yyparse</code>会以通常的格式调用<code>yyerror</code>并带有字符串<code>"parser stack overflow"</code>.
- </p>
- <p>下面的定义对于简单的程序足够用了:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example" ;="">void
- yyerror (char const *s)
- {
- fprintf (stderr, "%s/n", s);
- }
- </pre></td></tr></tbody></table>
- <p>当<code>yyerror</code>返回到<code>yyparse</code>后,
- 如果你以已经写好了恰当的错误恢复语法规则(参阅<a href="#SEC96">错误恢复-Error Recovery</a>一章),
- <code>yyparse</code>会尝试进行错误恢复.
- 如果恢复是不可能的,<code>yyparse</code>会立即返回1.
- </p>
- <p>显然,在带有错误追踪的纯分析器中,
- <code>yyerror</code>应该会访问当前的位置.
- 由于历史原因,这些的确是<acronym>GLR</acronym>分析器的事情而不是Yacc分析器的事情.
- 例如,如果传递了<samp>`%locations %pure-parser'</samp>,那么<code>yyerror</code>的原型是:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">void yyerror (char const *msg); /* Yacc parsers. */ /* Yacc 分析器 */
- void yyerror (YYLTYPE *locp, char const *msg); /* GLR parsers. */ /* GLR 分析器 */
- </pre></td></tr></tbody></table>
- <p>如果使用了<samp>`%parse-param {int *nastiness}'</samp>,那么原型是:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">void yyerror (int *nastiness, char const *msg); /* Yacc parsers. */ /* Yacc 分析器 */
- void yyerror (int *nastiness, char const *msg); /* GLR parsers. */ /* GLR 分析器 */
- </pre></td></tr></tbody></table>
- <p>最终,<acronym>GLR</acronym>和Yacc分析器对绝对的纯分析器共享相同的<code>yyerror</code>调用惯例,
- 例如,当<code>yylex</code><em>和</em><code>%pure-parse</code>的调用惯例是纯调用,例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">/* Location tracking. */ /* 追踪位置 */
- %locations
- /* Pure yylex. */ /* 纯yylex */
- %pure-parser
- %lex-param {int *nastiness}
- /* Pure yyparse. */ /* 纯yyparse */
- %parse-param {int *nastiness}
- %parse-param {int *randomness}
- </pre></td></tr></tbody></table>
- <p>导致了如下用于所有种类分析器的原型:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
- int yyparse (int *nastiness, int *randomness);
- void yyerror (YYLTYPE *locp,
- int *nastiness, int *randomness,
- char const *msg);
- </pre></td></tr></tbody></table>
- <p>原型只是用来指明Bison产生的代码如何使用<code>yyerror</code>.
- Bison产生的代码通常忽略返回值,
- 所以<code>yyerror</code>可以返回任何类型,
- 包括<code>void</code>.
- 并且<code>yyerror</code>可以是一个变参函数(variadic funcation),
- 这就是为什么消息总在最后传递的原因.
- </p>
- <p><code>yyerror</code>在传统上返回一个经常被忽略的<code>int</code>,
- 但这仅仅出于纯历史的原因.
- <code>void</code>是更好的选择,
- 因为它更精确的反应了<code>yyerror</code>的返回类型.
- </p>
- <a name="IDX62"></a>
- <p>变量<code>yynerrs</code>包含了到目前位置遭遇的语法错误的数量.
- 这个变量通常是全局的;
- 但是如果你要求一个纯分析器(参阅<a href="#SEC70">一个纯(可重入)分析器-A Pure (Reentrant) Parser</a>一章),
- 那么这个变量就是一个只能被动作访问的局部变量.
- </p>
- <hr size="6">
- <a name="Action-Features"></a>
- <a name="SEC81"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC80"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC82"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC73"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC73"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC82"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t82"></a> 4.4 在动作中使用的特殊特征-Special Features for Use in Actions </h2>
- <p>这里是在动作中使用的Bison结构,变量和红的列表.
- </p>
- <dl>
- <dt><u>变量:</u> <b>$$</b>
- <a name="IDX63"></a>
- </dt>
- <dd><p>像一个变量一样工作,这个变量包含了由当前规则构成的组的语义值.
- 参阅 <a href="#SEC54">动作-Actions</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>$<var>n</var></b>
- <a name="IDX64"></a>
- </dt>
- <dd><p>像一个变量一样工作,这个变量包含了当前动作第<var>n</var>个部件的语义值.
- 参阅 <a href="#SEC54">动作-Actions</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>$<<var>typealt</var></b><i>>$</i>
- <a name="IDX65"></a>
- </dt>
- <dd><p>类似<code>$$</code>但是指明了<code>%union</code>声明中的<var>typealt</var>选项.
- 参阅 <a href="#SEC55">动作中值的数据类型-Data Types of Values in Actions</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>$<<var>typealt</var></b><i>><var>n</var></i>
- <a name="IDX66"></a>
- </dt>
- <dd><p>类似<code>$<var>n</var></code>但是指明<code>%union</code>声明中的<var>typealt</var>选项.
- 参阅 <a href="#SEC55">动作中值的数据类型-Data Types of Values in Actions</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYABORT;</b>
- <a name="IDX67"></a>
- </dt>
- <dd><p>立即从<code>yyparse</code>返回,表明分析失败.
- 参阅 <a href="#SEC74">分析器函数<code>yyparse</code>-The Parser Function <code>yyparse</code></a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYACCEPT;</b>
- <a name="IDX68"></a>
- </dt>
- <dd><p>立即从<code>yyparse</code>返回,表明分析成功.
- 参阅 <a href="#SEC74">分析器函数<code>yyparse</code>-The Parser Function <code>yyparse</code></a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYBACKUP</b><i> (<var>token</var>, <var>value</var>);</i>
- <a name="IDX69"></a>
- </dt>
- <dd><a name="IDX70"></a>
- <p>移出一个记号.
- 这个宏仅仅在一个只归约单一值的规则中使用,并且只在没有超前扫描记号的时候被允许使用.
- 这个宏也不允许在<acronym>GLR</acronym>分析器中使用.
- 这个宏建立一个超前带有记号类型<var>token</var>和语义值<var>value</var>的超前扫描记号;
- 然后丢弃将要被这个规则归约的值.
- </p>
- <p>如果这个宏在无效的情况下使用,
- 例如当已经存在超前扫描记号的情况下使用,
- 那么它会报告一个带有消息<samp>`cannot back up'</samp>的语法错误
- 并且执行一个普通的错误恢复程序.
- </p>
- <p>在上述任一种情况下,动作的其余部分不会被执行.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYEMPTY</b>
- <a name="IDX71"></a>
- </dt>
- <dd><a name="IDX72"></a>
- <p>当没有超前扫描记号的时候,值被存放在<code>yychar</code>中.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYERROR;</b>
- <a name="IDX73"></a>
- </dt>
- <dd><a name="IDX74"></a>
- <p>立即导致一个语法错误.
- 这个语句启动错误恢复就像分析器自己已经侦测到一个错误一样;
- 然而,它并不调用<code>yyerror</code>并且不打印任何消息.
- 如果你要打印一个错误消息,
- 在<samp>`YYERROR;'</samp>语句之前显式地调用<code>yyerror</code>.
- 参阅 <a href="#SEC96">错误恢复-Error Recovery</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYRECOVERING</b>
- <a name="IDX75"></a>
- </dt>
- <dd><p>当分析器从语法错误中恢复的时候,这个表达式的值为1.
- 其余时候值为0.
- 参阅 <a href="#SEC96">错误恢复-Error Recovery</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>yychar</b>
- <a name="IDX76"></a>
- </dt>
- <dd><p>包含当前超前扫描记号的变量.
- (在一个纯分析器中,这实际上是一个<code>yyparse</code>中的局部变量).
- 当没有超前扫描记号的时候,这个变量存储<code>YYEMPTY</code>的值.
- 参阅 <a href="#SEC83">超前扫描记号-Look-Ahead Tokens</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>yyclearin;</b>
- <a name="IDX77"></a>
- </dt>
- <dd><p>丢弃当前的超前扫描记号.
- 它主要用于错误恢复规则.
- 参阅 <a href="#SEC96">错误恢复-Error Recovery</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>yyerrok;</b>
- <a name="IDX78"></a>
- </dt>
- <dd><p>对后来的语法错误立即恢复产生错误消息.
- 它主要用于错误恢复规则.
- 参阅 <a href="#SEC96">错误恢复-Error Recovery</a>.
- </p></dd></dl>
- <dl>
- <dt><u>值:</u> <b>@$</b>
- <a name="IDX79"></a>
- </dt>
- <dd><a name="IDX80"></a>
- <p>像一个包含文字位置信息的结构一样工作.
- 这个位置是由当前规则构成的组的位置.
- 参阅 <a href="#SEC57">追踪位置-Tracking Locations</a>.
- </p>
- </dd></dl>
- <dl>
- <dt><u>值:</u> <b>@<var>n</var></b>
- <a name="IDX81"></a>
- </dt>
- <dd><a name="IDX82"></a>
- <p>像一个包含文字位置信息的结构一样工作.
- 这个位置是由当前规则的第<var>n</var>个部件的位置.
- 参阅 <a href="#SEC57">追踪位置-Tracking Locations</a>.
- </p></dd></dl>
- <hr size="6">
- <a name="Algorithm"></a>
- <a name="SEC82"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC81"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC83"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC73"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="chapter"><a name="t83"></a> 5. Bison分析器算法-The Bison Parser Algorithm </h1>
- <p>当Bison读取记号的时候,它将这些记号同它们的语义值一起压入栈中.
- 这个栈被称为<em>分析器栈(parser stack)</em>.
- 将一个记号压入栈在传统上被称为<em>移进(shifting)</em>.
- </p>
- <p>例如,假设中缀计算器已经读取<samp>`1 + 5 *'</samp>并且将要读取<samp>`3'</samp>.
- 分析器栈此时有四个元素,每个元素对应一个被移进的符号.
- </p>
- <p>但是这个栈并不是总含有每个被读入记号的元素.
- 当最后<var>n</var>个被移进的记号和组匹配语法规则部件时,
- 可以由那个规则将它们结合起来.
- 这叫做<em>归约(reduction)</em>.
- 这些栈中的记号和组被一个单一的组取代.
- 那个组的符号是这个规则的结果(左手端).
- 运行规则的动作是处理归约的一部分,
- 因为这就是什么在计算结果组的语义值.
- </p>
- <p>例如,如果中缀计算器的分析器栈包含这个:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">1 + 5 * 3
- </pre></td></tr></tbody></table>
- <p>并且下一个输入是一个换行符,
- 那么最后三个元素可通过这个规则被归约成15:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">expr: expr '*' expr;
- </pre></td></tr></tbody></table>
- <p>那么这个栈仅含有三个元素:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">1 + 15
- </pre></td></tr></tbody></table>
- <p>在整个时候可以进行另外一个结果为16的归约.
- 然后,换行符记号才可以被移进.
- </p>
- <p>分析器通过移进和归约尝试将整个输入化为一个符号为语法开始符号的单一组.
- (参阅<a href="#SEC7">语言与上下文无关文法-Languages and Context-Free Grammars</a>一章).
- </p>
- <p>这种类型的分析器被称之为<em>自底向上(bottom-up)</em>的分析器.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC83">5.1 超前扫描记号-Look-Ahead Tokens</a></td><td> </td><td align="left" valign="top"> 当分析器决定做什么的时候它查看的一个记号.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC84">5.2 移进/归约冲突-Shift/Reduce Conflicts</a></td><td> </td><td align="left" valign="top"> 冲突:移进和归约均有效.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC85">5.3 操作符优先级-Operator Precedence</a></td><td> </td><td align="left" valign="top"> 用于解决冲突的操作符优先级.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC90">5.4 上下文依赖优先级-Context-Dependent Precedence</a></td><td> </td><td align="left" valign="top"> 当一个操作符的优先级依赖上下文.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC91">5.5 分析器状态-Parser States</a></td><td> </td><td align="left" valign="top"> 分析器是一个带有栈的有限状态机.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC92">5.6 归约/归约冲突-Reduce/Reduce Conflicts</a></td><td> </td><td align="left" valign="top"> 在同一情况下可以应用两个规则.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC93">5.7 神秘的归约/归约冲突-Mysterious Reduce/Reduce Conflicts</a></td><td> </td><td align="left" valign="top"> 看起来不平等的归约/归约冲突.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC94">5.8 通用<acronym>LR</acronym> (<acronym>GLR</acronym>)分析-Generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) Parsing</a></td><td> </td><td align="left" valign="top"> 分析武断的上下文无关文法.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC95">5.9 栈溢出以及如何避免它-Stack Overflow, and How to Avoid It</a></td><td> </td><td align="left" valign="top"> 当栈溢出时发生的事情以及如何避免它.
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Look_002dAhead"></a>
- <a name="SEC83"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC82"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC84"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC82"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t84"></a> 5.1 超前扫描记号-Look-Ahead Tokens </h2>
- <p>Bison分析器并<em>不</em>总是在最后<var>n</var>个记号和组匹配一个规则时立即进行归约.
- 这是由于这种策略对于处理大多数语言来说是不够的.
- 相反,当可以进行一个归约的时候,
- 分析器有时"超前扫描"下一个记号来决定该怎么做.
- </p>
- <p>当读取一个记号时,
- 它并不是被马上移进而是首先成为不在栈中的<em>超前扫描记号(look-ahead token)</em>.
- 现在分析器可以对记号和组进行一个或更多的归约,而超前扫描记号仍在栈外.
- 这并不意味着所有可能的归约已经执行;
- 依赖于超前扫描记号的符号类型,
- 一些规则可以选择推迟它们的应用.
- </p>
- <p>这里有一个需要超前扫描记号的例子.
- 这三个规则定义了包括二进制加法操作符和一元后缀阶称操作符(<samp>`!'</samp>),
- 并且允许括弧分组.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">expr: term '+' expr
- | term
- ;
- term: '(' expr ')'
- | term '!'
- | NUMBER
- ;
- </pre></td></tr></tbody></table>
- <p>假定<samp>`1 + 2'</samp>已经被读取和移进;
- 分析器这时应该做什么?
- 如果接下来的记号是<samp>`)'</samp>,
- 那么前三个记号必须被归约成一个<code>expr</code>.
- 这是唯一有效的情况,
- 因为移进<samp>`)'</samp>会产生一系列的<code>term ')'</code>,
- 而没有规则允许这样.
- </p>
- <p>如果接下来的符号是<samp>`!'</samp>,
- 那么它必须马上被移进以便<samp>`2 !'</samp>可以被移进产生一个<code>term</code>.
- 如果不这样做,
- 分析器将会在移进之前进行归约,
- <samp>`1+2'</samp>会成为一个<code>expr</code>.
- 那是移进<samp>`!'</samp>就是不可能的,
- 因为这么做会使栈中产生序列<code>expr '!'</code>.
- 没有规则允许那样的序列.
- </p>
- <a name="IDX83"></a>
- <p>当前的超前扫描记号被存储在<code>yychar</code>中.
- 参阅 <a href="#SEC81">在动作中使用的特殊特征-Special Features for Use in Actions</a>.
- </p>
- <hr size="6">
- <a name="Shift_002fReduce"></a>
- <a name="SEC84"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC83"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC85"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC82"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t85"></a> 5.2 移进/归约冲突-Shift/Reduce Conflicts </h2>
- <p>假设我们正在分析一个有if-then和if-then-else语句的语言
- 并且这个语言带有如下一对规则:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">if_stmt:
- IF expr THEN stmt
- | IF expr THEN stmt ELSE stmt
- ;
- </pre></td></tr></tbody></table>
- <p>这里我们假定<code>IF</code>,<code>THEN</code>和<code>ELSE</code>是用来指定关键字的终结符.
- </p>
- <p>当<code>ELSE</code>被读入成为超前扫描记号,
- 栈中的内容(假定输入是有效的)刚好可以由第一个规则进行归约.
- 但是移进<code>ELSE</code>也是合法的,
- 因为这最终将会导致由第二个规则进行的归约.
- </p>
- <p>这种情况,移进或者归约都是有效的,被称为<em>移进/归约冲突(shift/reduce conflict)</em>.
- Bison被设计成选择<strong>移进</strong>来解决这些冲突,
- 除非有其它的操作符优先级的指导.
- 为了研究这样做得原因,
- 我们将它和另一种选择(注:选择归约)做一个对比.
- </p>
- <p>由于分析器选择移进<code>ELSE</code>.
- 这样作的结果是将else从句依附到最里面的if语句中,
- 并使下面两个输入在作用上等价.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">if x then if y then win (); else lose;
- if x then do; if y then win (); else lose; end;
- </pre></td></tr></tbody></table>
- <p>但如如果分析器选择在可能的时候归约而不是移进.
- 这样做的结果是将else从句依附到最外面的if语句中,
- 并使下面两个输入在作用上等价:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">if x then if y then win (); else lose;
- if x then do; if y then win (); end; else lose;
- </pre></td></tr></tbody></table>
- <p>冲突存在的原因是由于语法本身有歧义:
- 任一种简单的if语句嵌套的分析都是合法的.
- 已经建立的惯例是通过将else从句依附到最里面的if语句来解决歧义;
- 这就是Bison为什么选择移进而不是归约的原因.
- (在理想的情况下,最好编写一个非歧义的文法,
- 但是在这种情况下却很难办到.)
- 这种特殊的歧义在Algol 60的描述中首次出现并被成为"悬挂<code>else</code>"歧义.
- </p>
- <p>为了避免Bison警告那些可以预见的合法的移进/归约冲突,
- 我们可以使用<code>%expect <var>n</var></code>声明.
- 当移进/归约冲突的数目恰好是<var>n</var>的时候,
- Bison不会做出任何警告.
- 参阅 <a href="#SEC68">消除冲突警告-Suppressing Conflict Warnings</a>.
- </p>
- <p>有人抱怨上面<code>if_stmt</code>的定义,
- 但是冲突的确实在没有任何额外规则的时候出现.
- 这又一个完整的体现这个冲突的Bison输入文件:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%token IF THEN ELSE variable
- %%
- stmt: expr
- | if_stmt
- ;
- if_stmt:
- IF expr THEN stmt
- | IF expr THEN stmt ELSE stmt
- ;
- expr: variable
- ;
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Precedence"></a>
- <a name="SEC85"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC84"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC86"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC82"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t86"></a> 5.3 操作符优先级-Operator Precedence </h2>
- <p>移进/归约冲突也可能出现在算术表达式中.
- 在这里,移进并不总是优先的选择;
- Bison关于操作符优先级的声明允许你指定什么时候移进和什么时候归约.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC86">5.3.1 什么时候需要优先级-When Precedence is Needed</a></td><td> </td><td align="left" valign="top"> 一个展示为什么需要优先级的例子
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC87">5.3.2 指定操作符的优先级-Specifying Operator Precedence</a></td><td> </td><td align="left" valign="top"> 在Bison的语法中如何指定优先级
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC88">5.3.3 优先级使用的例子-Precedence Examples</a></td><td> </td><td align="left" valign="top"> 这些特性在前面的例子中是怎样使用的
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC89">5.3.4 优先级如何工作-How Precedence Works</a></td><td> </td><td align="left" valign="top"> 它们如何工作
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Why-Precedence"></a>
- <a name="SEC86"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC85"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC87"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC85"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t87"></a> 5.3.1 什么时候需要优先级-When Precedence is Needed </h3>
- <p>考虑下面的歧义文法片段
- (产生歧义的原因是输入<samp>`1 - 2 * 3'</samp>可以由两种方法进行分析):
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">expr: expr '-' expr
- | expr '*' expr
- | expr '<' expr
- | '(' expr ')'
- …
- ;
- </pre></td></tr></tbody></table>
- <p>假设分析器已经读入了记号<samp>`1'</samp>,<samp>`-'</samp>和<samp>`2'</samp>;
- 那么它是否应该使用减法操作符规则进行归约呢?
- 这依赖于下一个记号.
- 当然,如果下一个记号是<samp>`)'</samp>,我们必须归约,
- 由于没有规则可以归约<samp>`- 2 )'</samp>或者以它开始的记号序列,
- 所以移进是无效的.
- 但是如果下一个符号是<samp>`*'</samp>或者<samp>`<'</samp>,
- 我么有了一个选择:
- 移进和归约都可以,但是会产生不同的结果.
- </p>
- <p>要决定Bison应该怎么做,我们必须考虑结果.
- 如果下一个操作符记号<var>op</var>被移进,
- 那么它必须首先被归约以便允许进行另外一个归约的机会.
- 结果为<samp>`1 - (2 <var>op</var> 3)'</samp>.
- 另一方面,如果在移进<var>op</var>之前归约减法,
- 结果为<samp>`(1 - 2) <var>op</var> 3'</samp>.
- 很明显,选择移进或者归约依靠操作符<samp>`-'</samp>和<var>op</var>的相对优先级:
- <samp>`*'</samp>是该首先被移进,而不是<samp>`<'</samp>.
- </p>
- <a name="IDX84"></a>
- <p>当输入为<samp>`1 - 2 - 5'</samp>的时候会怎么样,
- 这应该是<samp>`(1 - 2) - 5'</samp>还是<samp>`1 - (2 - 5)'</samp>?
- 对于大多数操作符来说,我们选择前者.
- 这被成为<em>左结合(left association)</em>.
- 后面一种,<em>右结合(right association)</em>,
- 对于赋值操作符是理想的选择.
- 选择左结合或者有结合是
- 当栈包含<samp>`1 - 2'</samp>并且超前扫描记号是<samp>`-'</samp>时,分析器选择移进还是归约的问题:
- 移进代表着右结合.
- </p>
- <hr size="6">
- <a name="Using-Precedence"></a>
- <a name="SEC87"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC86"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC88"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC85"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t88"></a> 5.3.2 指定操作符的优先级-Specifying Operator Precedence </h3>
- <p>Bison允许你使用操作符优先级声明<code>%left</code>和<code>%right</code>指定这些选择.
- 每一个这样的声明包含了一个要声明其优先级和结合性的记号列表.
- <code>%left</code>声明使这些操作符成为左结合的,
- <code>%right</code>声明使这些操作符成为右结合的.
- 第三种选择是<code>%nonassoc</code>,它声明了
- "在一行中"有两个相同的操作符是一个语法错误.
- </p>
- <p>不同操作符的优先级由它们声明的顺序控制.
- 文件中的第一个<code>%left</code>或者<code>%right</code>声明的优先级最低,
- 下一个类似声明的操作符有稍高的优先级,以此类推.
- </p>
- <hr size="6">
- <a name="Precedence-Examples"></a>
- <a name="SEC88"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC87"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC89"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC85"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t89"></a> 5.3.3 优先级使用的例子-Precedence Examples </h3>
- <p>在我们的例子中,我们会发现下面的声明:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%left '<'
- %left '-'
- %left '*'
- </pre></td></tr></tbody></table>
- <p>在一个支持其它操作符的更完整的例子中,
- 我们会成组地声明具有相同优先级的操作符.
- 例如<code>'+'</code>和<code>'-'</code>一起声明.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%left '<' '>' '=' NE LE GE
- %left '+' '-'
- %left '*' '/'
- </pre></td></tr></tbody></table>
- <p>(在这里<code>NE</code>代表着"不相等"操作符",其它以此类推.
- 我们假定这些记号的长度多于一个字符并且因此由它们的名字代表而不是字符.)
- </p>
- <hr size="6">
- <a name="How-Precedence"></a>
- <a name="SEC89"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC88"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC90"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC85"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="subsection"><a name="t90"></a> 5.3.4 优先级如何工作-How Precedence Works </h3>
- <p>优先级声明的第一个作用是赋予声明的终结符以优先级.
- 第二个作用是赋予特定的规则以优先级:
- 每个规则从部件中最后一个提及的终结符中获取优先级.
- (你也可以明确的指明规则的优先级. 参阅 <a href="#SEC90">上下文依赖优先级-Context-Dependent Precedence</a>.)
- </p>
- <p>最终,解决中冲突的方法是比较正在考虑的规则和超前扫描记号的优先级.
- 如果超前扫描记号的优先级更高,那么选择移进.
- 如果规则的优先级更高,那么选择归约.
- 如果它们有相同的优先级,
- 那么靠那个优先级的结合性来作出选择.
- 由选项<samp>`-v'</samp>(参阅<a href="#SEC104">调用Bison-Invoking Bison</a>一章)制造的冗长的输出文件(The verbose output file)
- 说明了每个冲突是如何解决的.
- </p>
- <p>并不是所有的规则和记号都有优先级.
- 如果规则和超前扫描记号都没有优先级,
- 那么默认的动作是移进.
- </p>
- <hr size="6">
- <a name="Contextual-Precedence"></a>
- <a name="SEC90"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC89"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC91"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC82"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t91"></a> 5.4 上下文依赖优先级-Context-Dependent Precedence </h2>
- <p>一个操作符的优先级通常依赖于上下文.
- 这最开始听起来很古怪,但它的确很常见.
- 例如,典型地,一个负号操作符有比一元操作符更高的优先级
- 并且比二进制操作符的优先级稍低(低于乘法).
- </p>
- <p>Bison优先级声明,<code>%left</code>,<code>%right</code>和<code>%nonassoc</code>
- 对于一个给定的操作符只能使用一次;
- 所以通过这种方法,一个操作符只能有一种优先级.
- 对于上下文依赖优先级来说,你需要使用一种额外的机制:
- 规则的<code>%prec</code>修饰符.
- </p>
- <p><code>%prec</code>靠指定用于那个规则终结符的优先级来声明特定规则的优先级.
- 那个符号不需要以特殊的方式出现在规则中.
- 修饰符的语法为:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%prec <var>terminal-symbol</var>
- </pre></td></tr></tbody></table>
- <p>并且它写在规则的部件之后.
- 它的作用是赋予规则<var>terminal-symbol</var>的优先级而不考虑从普通方法推导出的优先级.
- 被改变的规则优先级会影响包含那个规则的冲突的解决方法.
- (参阅<a href="#SEC85">操作符优先级-Operator Precedence</a>一章).
- </p>
- <p>这是<code>%prec</code>如何解决负号问题的例子.
- 首先为一个虚构的名为<code>MINUS</code>的终结符声明优先级.
- 实际上没有记号是这种类型,
- 但是这个符号以它自己的优先级来使用.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">…
- %left '+' '-'
- %left '*'
- %left UMINUS
- </pre></td></tr></tbody></table>
- <p>现在可以在规则中使用<code>MINUS</code>的优先级.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">exp: …
- | exp '-' exp
- …
- | '-' exp %prec UMINUS
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Parser-States"></a>
- <a name="SEC91"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC90"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC92"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC82"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t92"></a> 5.5 分析器状态-Parser States </h2>
- <p>函数<code>yyparse</code>是使用有限状态机(finite-state-machine)来实现的.
- 压入分析器栈中的值不仅仅是符号类型码;
- 它们代表了整个在栈顶或者靠近栈顶的终结符和非终结符序列.
- 当前的状态收集了与决定下一步怎么做相关的之前输入的信息.
- </p>
- <p>每次读入一个超前扫描记号,
- 分析器就在一个表中搜索分析装当前状态和超前扫描记号类型.
- 这个表项能会说"移进超前扫描记号"
- 在这种情况下,它在指定了一个新的分析器状态的同时将这个状态压入栈顶.
- 或者,它(注:指表项)也可能说"使用第<var>n</var>个规则进行归约."
- 这意味着某些个数的记号合组被移出栈,取而代之的是一个组.
- 用另外一种说法,
- 那些个数(注:<var>n</var>)的状态被弹出栈,一个新状态被压入栈.
- </p>
- <p>还有另外一种选择:这个表可能会说那个超前扫描记号在当前的状态下是错误的.
- 这会引发错误处理.(参阅<a href="#SEC96">错误恢复-Error Recovery</a>一章).
- </p>
- <hr size="6">
- <a name="Reduce_002fReduce"></a>
- <a name="SEC92"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC91"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC93"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC82"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t93"></a> 5.6 归约/归约冲突-Reduce/Reduce Conflicts </h2>
- <p>一个归约/归约冲突发生在有两个或者更多规则可以被用于相同输入序列的情况下.
- 这通常表明了一个语法中的严重错误.
- </p>
- <p>例如,这里是一个试图定义零个或者更多<code>word</code>组的错误.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">sequence: /* empty */
- { printf ("empty sequence/n"); }
- | maybeword
- | sequence word
- { printf ("added word %s/n", $2); }
- ;
- maybeword: /* empty */
- { printf ("empty maybeword/n"); }
- | word
- { printf ("single word %s/n", $1); }
- ;
- </pre></td></tr></tbody></table>
- <p>这个错误是一个歧义:有多种方法可以将单一的<code>word</code>分析成一个<code>sequence</code>.
- 它可以归约为一个<code>maybeword</code>然后通过第二个规则归约为一个<code>sequence</code>.
- 另外,什么都没有可以通过第一个规则归约为一个<code>sequence</code>,
- 可以使用<code>sequence</code>的第三个规则将它和<code>word</code>结合起来.
- </p>
- <p>也有多种方法将什么都没有归约成一个<code>sequence</code>.
- 可以直接通过第一个规则归约或者间接通过<code>maybeword</code>然后通过第二个规则归约.
- </p>
- <p>你可能认为这没有什么区别,
- 因为不论任意的输入是否有效它没有什么变化.
- 但是它却影响这该执行哪一条规则.
- 一种分析顺序运行了第二个规则的动作,
- 另一个则运行了第一个和第三个规则的动作.
- 在这个例子中,程序的输出有所变化.
- </p>
- <p>Bison靠选择首先出现在语法中的规则解决归约/归约冲突,
- 但是依靠这种策略是十分冒险的事情.
- 必须仔细研究每一个归约/归约冲突并且通常要消灭它们.
- 这里有一个正确定义<code>sequence</code>的方法:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">sequence: /* empty */
- { printf ("empty sequence/n"); }
- | sequence word
- { printf ("added word %s/n", $2); }
- ;
- </pre></td></tr></tbody></table>
- <p>这里是另外一个产生归约/归约冲突的普通例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">sequence: /* empty */
- | sequence words
- | sequence redirects
- ;
- words: /* empty */
- | words word
- ;
- redirects:/* empty */
- | redirects redirect
- ;
- </pre></td></tr></tbody></table>
- <p>这里的目的是定一个可以包含<code>word</code>或<code>redirect</code>组的序列.
- <code>sequence</code>,<code>words</code>和<code>redirects</code>的定义都是没有问题的,
- 但是三个在一起却产生微妙的歧义:
- 即使一个空输入可以有无限多种分析的方式.
- </p>
- <p>考虑:什么都没有可以是一个<code>words</code>.
- 或者它可以是两个在一行的<code>words</code>,或者三个,或者任意个.
- 它同样也可以是一个<code>words</code>后跟三个<code>redirects</code>和另外一个<code>words</code>.
- 等等.
- </p>
- <p>这有两种改正这些规则的方法.
- 第一,使它成为一个单层序列:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">sequence: /* empty */
- | sequence word
- | sequence redirect
- ;
- </pre></td></tr></tbody></table>
- <p>第二,防止<code>words</code>或者<code>redirects</code>为空:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">sequence: /* empty */
- | sequence words
- | sequence redirects
- ;
- words: word
- | words word
- ;
- redirects:redirect
- | redirects redirect
- ;
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Mystery-Conflicts"></a>
- <a name="SEC93"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC92"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC94"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC82"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t94"></a> 5.7 神秘的归约/归约冲突-Mysterious Reduce/Reduce Conflicts </h2>
- <p>[untranslated]
- Sometimes reduce/reduce conflicts can occur that don't look warranted.
- [/untranslated]
- 这里有一个例子:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%token ID
- %%
- def: param_spec return_spec ','
- ;
- param_spec:
- type
- | name_list ':' type
- ;
- return_spec:
- type
- | name ':' type
- ;
- type: ID
- ;
- name: ID
- ;
- name_list:
- name
- | name ',' name_list
- ;
- </pre></td></tr></tbody></table>
- <p>这个文法看起来可以用一个单一的超前扫描记号分析:
- 当正在读入<code>para_spec</code>的时候.
- 如果<code>ID</code>后面紧跟一个分号,那么它是一个<code>name</code>.
- 如果<code>ID</code>后面跟随另外一个<code>ID</code>,那么它是一个<code>type</code>.
- 换句话说,这是一个<acronym>LR</acronym>(1)文法.
- </p>
- <a name="IDX85"></a>
- <a name="IDX86"></a>
- <p>然而,像大多数分析器产生器一样,Bison实际上并不能处理所有的<acronym>LR</acronym>(1)文法.
- 在这个文法中,两个位于<code>param_spec</code>的开始,并同样地位于<code>return_spec</code>开始
- ,在<code>ID</code>之后的上下文十分相似,以致于Bison认为它们是相同的.
- 它们看起来相似因为相同的规则集是活动的--归约到<code>name</code>的规则和归约到<code>type</code>的规则.
- Bison在那个处理阶段没有能力决定这些规则在两个上下文中需要不同的超前扫描记号,
- 所以它为两种情况制造了同一个分析器状态.
- 结合两个上下文会在稍后引起一个冲突.
- 在分析器术语中,
- 这种情况意味着这个文法不是<acronym>LALR</acronym>(1)文法.
- </p>
- <p>通常来讲,最好是修补漏洞而不是将漏洞写入文档.
- 但是这个特殊的漏洞很难被修复;
- 处理<acronym>LR</acronym>(1)文法的分析器生成器很难编写并且倾向于制造很大的分析器.
- 在实践中,Bison显得更为实用.
- </p>
- <p>当问题产生时,
- 你通常可以通过指明两个被混淆的分析器状态
- 并且添加使它们看起来截然不同的额外的东西
- 来修补它,
- 在上面的例子中,
- 如下地向<code>return_spec</code>添加一个规则会消除这个问题:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%token BOGUS
- …
- %%
- …
- return_spec:
- type
- | name ':' type
- /* This rule is never used. */ /* 这个规则永远不会被使用 */
- | ID BOGUS
- ;
- </pre></td></tr></tbody></table>
- <p>这样做改正这个问题,
- 因为在<code>return_spec</code>开始部分<code>ID</code>后的上下文中引进了一个可能的额外的活动规则.
- 这个规则在<code>param_spec</code>相应的上下文中并不是活动的,
- 所以两个上下文接受了不同的分析器状态.
- 只要<code>yylex</code>永远不产生记号<code>BOGUS</code>,
- 新增的规则就不能改变分析输入的实际方法.
- </p>
- <p>在这个特殊的例子中,还有另外一种解决问题的方法:
- 直接使用使用<code>ID</code>来替代<code>name</code>来重写<code>return_spec</code>的规则.
- 这样做也使两个混淆的上下文有了不同的活动集,
- 因为<code>return_spec</code>的活动集激活了<code>return_spec</code>的规则而不是<code>name</code>的.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">param_spec:
- type
- | name_list ':' type
- ;
- return_spec:
- type
- | ID ':' type
- ;
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Generalized-LR-Parsing"></a>
- <a name="SEC94"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC93"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC95"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC82"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t95"></a> 5.8 通用<acronym>LR</acronym> (<acronym>GLR</acronym>)分析-Generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) Parsing </h2>
- <p>Bison产生<em>确定性(determinstic)</em>的分析器.
- 这种分析器基于先前输入和额外的超前扫描记号的摘要,
- 唯一性地选择进行归约的时机和如何进行归约.
- 结果,通常,Bison处理一个上下文无关文法语言族的自己.
- 由于歧义文法含有可以使用多种可能的归约序列的字符串,
- 所以在这种情况下不能使用确定的分析器.
- 这种情况同样适用于需要多于一个超前扫描记号的语言,
- 因为分析器缺乏做出决定所需要的必要信息,
- 这时它必须被制作成一个移进-归约分析器.
- 最终,如同之前提到的(参阅<a href="#SEC93">神秘的冲突-Mystery Conflicts</a>一章),
- 有这样一些语言,Bison关于如何总结输入的特殊选择目前看起来缺少必要的信息.
- </p>
- <p>当你在你的语法文件中使用<samp>`%glr-parser'</samp>声明的时候,
- Bison产生一个使用不同算法的分析器,这种分析器被称为通用<acronym>LR</acronym>(或<acronym>GLR</acronym>)分析器.
- 一个Bison <acronym>GLR</acronym>分析器使用同样基本的算法做为一个普通的Bison分析器进行分析,
- 但当存在一个不能被优先级规则(参阅<a href="#SEC85">优先级-Precedence</a>一章)解决的移进/归约冲突,
- 或者一个归约/归约冲突时却有着与普通Bison分析器不同的行为.
- 当一个<acronym>GLR</acronym>分析器遭遇这种情况的时候,
- 它高效地<em>分裂(splits)</em>成多个分析器,
- 每个对应一种可能的移进或者归约.
- 这些分析器如常地进行分析,使用锁步(lock-step)消耗记号.
- 一些栈遭遇了其它的冲突并且进一步分裂,
- 一个Bison <acronym>GLR</acronym>分析栈是一个取代状态序列的高效的分析树.
- </p>
- <p>实际上,每个栈代表一个关于正确分析的猜想.
- 剩余的输入可能会表明一个猜想是错误的,
- 在这种情况下,不正确的栈静静地消失.
- 另外,每个栈中的语义动作被保存而不是立即执行.
- 但一个栈消失时,它存储的的语义动作永远不会被执行.
- 当一个归约使两个栈等价的时候,
- 它们的语义动作集和导致归约的状态都会被保存.
- 我们说两个栈是等价的
- 当它们都代表相同的状态序列,
- 并且每对相应的状态代表一个产生相同输入流片段的语法符号.
- </p>
- <p>每当分析器从有多个分析状态转换为一个分析状态时,
- 在执行了原来保存的动作后,
- 这个分析器将转变到通常的<acronym>LALR</acronym>(1)分析算法.
- 在这个转换过程中,一些栈上的状态含有可能的动作集(实际上是多个集)的语义值.
- 分析器试图从这些动作中挑选一个被<samp>`%prec'</samp>声明指定的有最高动态优先级的动作.
- 否则,如果可选择的动作并未被优先级排序,
- 但对两个规则使用<samp>`%merge'</samp>声明了相同的合并函数,
- Bison评价并解决它们之后调用合并函数求得结果.
- 否则它会报告一个歧义.
- </p>
- <p>对<acronym>GLR</acronym>分析树使用这样一种数据结构是可能的,
- 这种结构可以以线性的时间(相对输入的大小)处理任意的<acronym>LALR</acronym>(1)文法,
- 在最坏情况下以二次方的时间处理任何非歧义文法(不一定是<acronym>LALR</acronym>(1)),
- 在最坏情况下以三次方的时间处理任何普通(可能是歧义的)上下文无关文法.
- 然而Bison当前使用一种更简单的数据结构,
- 这中数据结构需要与输入长度乘以输入的任意前需要缀最大栈数目成比例的时间.
- 因此,实际上,歧义或者不确定文法可能需要指数的时间和空间来处理.
- 然而,这种非常糟糕例子通常情况下很难见到.
- 文法中的不确定性通常是局部的--分析器一次只对很少一些记号"产生疑惑".
- 因此,当前的数据结构在大多数情况下足够用了.
- 特别地,对于文法的<acronym>LALR</acronym>(1)部分,它(注:通用<acronym>GLR</acronym>分析器)
- 仅仅比默认的Biosn分析器稍慢.
- </p>
- <p>想获得更详细的<acronym>GLR</acronym>分析器的说明,请参阅:
- Elizabeth
- Scott, Adrian Johnstone and Shamsa Sadaf Hussain, Tomita-Style
- Generalised <acronym>LR</acronym> Parsers, Royal Holloway, University of
- London, Department of Computer Science, TR-00-12,
- <a href="http://www.cs.rhul.ac.uk/research/languages/publications/tomita_style_1.ps">http://www.cs.rhul.ac.uk/research/languages/publications/tomita_style_1.ps</a>,
- (2000-12-24).
- </p>
- <hr size="6">
- <a name="Stack-Overflow"></a>
- <a name="SEC95"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC94"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC96"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> &lt;&lt; </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC82"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC96"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t96"></a> 5.9 栈溢出以及如何避免它-Stack Overflow, and How to Avoid It </h2>
- <p>如果太多的记号被移进而没有被归约,
- Bison分析器栈可能会溢出.
- 在这种情况发生时,
- 分析器函数<code>yyparse</code>返回非零值,
- 暂停执行并调用<code>yyerror</code>来报告错误.
- </p>
- <p>由于Bison分析器拥有生长的栈,
- 达到上限通常是由于使用右递归而不是左递归而产生的.
- 参阅 <a href="#SEC50">递归规则-Recursive Rules</a>.
- </p>
- <a name="IDX87"></a>
- <p>靠定义宏<code>YYMAXDEPTH</code>,你可以控制栈溢出之前的最大深度.
- 我们应该用正数定义这个宏.
- 这个值是在溢出之前被移进(而没被归约)的记号的最大数目.
- </p>
- <p>允许的栈空间不需要一次分配完毕.
- 如果你为<code>YYMAXDEPTH</code>指定了一个很大的数字,
- 分析器实际上在开始之分配了一个空间很小的栈,
- 随个阶段性的需求,分析器会扩大栈的容量.
- 增大空间的分配自动并且沉默地进行.
- 因此,你不需要为了不需要多少空间的普通输入节省空间
- 而将<code>YYMAXDEPTH</code>定义的很小.
- </p>
- <p>然而,我们同样不要把<code>YYMAXDEPTH</code>定义的很大以至于
- 在计算栈容量时产生算术溢出.
- 并且我们也不要将<code>YYMAXDEPTH</code>定义的比<code>YYINITDEPTH</code>还小.
- </p>
- <a name="IDX88"></a>
- <p>如果你没有定义<code>YYMAXDEPTH</code>,那么它的默认值是10000.
- </p>
- <a name="IDX89"></a>
- <p>你可靠定义宏<code>YYINITDEPTH</code>为一个正值来控制栈初始分配的空间.
- 除非你使用C99或者其它允许变长数组的语言和编译器,
- 对于C语言<acronym>LALR</acronym>(1)分析器来说,
- 这个值必须为编译时常量.
- <code>YYINITDEPTH</code>的默认值为200.
- </p>
- <p>不要让<code>YYINITDEPTH</code>过大以至于当计算栈空间时发生溢出.
- 同样地,不要让<code>YYINITDEPTH</code>大于<code>YYMAXDEPTH</code>.
- </p>
- <p>由于C和C++语义上的区别,
- 利用C++编译器编译的用C语言编写的<acronym>LALR</acronym>(1)分析器不能生长.
- (注:指栈不能生长)
- 在这种情况下(作为C++来编译C分析器),
- 我们建议你增加<code>YYINITDEPTH</code>的大小.
- 在不久的将来,
- 我们会提供涉及到这个问题的C++输出.
- </p>
- <hr size="6">
- <a name="Error-Recovery"></a>
- <a name="SEC96"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC95"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC97"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC82"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC97"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="chapter"><a name="t97"></a> 6. 错误恢复-Error Recovery </h1>
- <p>我们通常不能接受让一个程序在遇到语法错误时就终止.
- 例如,一个编译器应该充分的从错误中恢复
- 以便分析输入文件的其余部分并且检查其中的错误;
- 一个计算器应该接受其它的表达式.
- </p>
- <p>在每个输入都是一行的简单互交命令分析器中,
- 让<code>yyparse</code>在遇到错误时返回1并且
- 使调用者忽略剩下的输入行(然后重新调用<code>yyparse</code>就足够了.
- 但是这对于编译器来说显然不够,
- 因为为它忘记了导致错误的全部构造上下文.
- 在编译器输入中,深入到一个函数内部的语法错误,
- 并不应该使编译器对待后面的行像对待源文件的开始一样.
- </p>
- <a name="IDX90"></a>
- <p>你可以靠编写一个识别特殊记号<code>error</code>的规则来定义如何从语法错误中恢复.
- 它总是一个已经被定义(你不需要声明它)并且保留做错误处理使用的终结符.
- 每当一个语法错误发生时,Bison分析器就产生一个<code>error</code>记号;
- 如果你在当前的上下文中提供了一个识别该记号的规则,
- 那么分析可以继续进行.
- </p>
- <p>例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">stmnts: /* empty string */ /* 空字符串 */
- | stmnts '/n'
- | stmnts exp '/n'
- | stmnts error '/n'
- </pre></td></tr></tbody></table>
- <p>这个例子的第四个规则说明了一个错误后紧跟一个换行
- 对任何<code>stmnts</code>是有效的添加.
- </p>
- <p>如果错误发生在<code>exp</code>中间的话会发生什么情况?
- 这个错误恢复规则,被精确地解释为应用于一个<code>stmnts</code>,一个<code>error</code>
- 和一个换行的精确序列.
- 如果一个错误发生在一个<code>exp</code>中间,
- 那么在栈中最后的<code>stmnts</code>之后很可能有一些额外的记号或者自表达式,
- 即有一些记号在下一个换行之前被读入.
- 所以这个规则并不按通常的方法应用.
- </p>
- <p>但是Bison可以靠丢弃部分语义上下文和部分输入来强制地使这个规则(注:错误恢复规则)适用于这种情况.
- 首先,它从栈中丢弃状态和对象直到回到一个可以接受<code>error</code>的状态.
- (这意味着分析过的子表达式被丢弃,并且回到最后一个完整的<code>stmnts</code>.)
- 这时<code>error</code>记号可以被移进.
- 之后,如果旧的超前扫描记号不能接受移进下一个记号,
- 分析器如读记号并且丢弃它们直到找到一个可以接受的记号.
- 在这个例子中,Bison读入并丢弃输入直到下一个换行符以便应用第四个规则.
- 注意到丢弃的符号通常是内存泄露之源,参阅<a href="#SEC67">释放丢弃的符号-Freeing Discarded Symbols</a>以获取更多信息.
- </p>
- <p>在语法中,对于错误恢复规则的选择就是对错误恢复策略的选择.
- 一个简单而使用的策略是如果检测到一个错误,跳过当前输入行的剩余部分:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">stmnt: error ';' /* On error, skip until ';' is read. */ /* 当错误出现时,跳过剩余部分直到读入 ';' */
- </pre></td></tr></tbody></table>
- <p>为一个已经分析的作括号恢复匹配一个右括号也是非常实用的.
- 否则,右括号很可能不匹配地出现并且引发另外的更严重的错误消息:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">primary: '(' expr ')'
- | '(' error ')'
- …
- ;
- </pre></td></tr></tbody></table>
- <p>错误恢复策略是必要的猜测.
- 当它们猜测的时候,一个语法错误通常会导致另外一个错误.
- 在上面的例子中,
- 错误规则猜测:一个错误是由于一个<code>stmnt</code>中的错误输入引起的.
- 假设一个伪造的分号被插入到一个有效的<code>stmt</code>中间.
- 在错误恢复规则从第一错误恢复之后,分析器会立刻发现另外一个错误,
- 因为在伪造的分号之后的文字也是一个无效的<code>stmt</code>.
- </p>
- <p>为了阻止错误的倾泄而出,
- 分析器在第一个错误之后立即发现另一个错误时,不会输出错误消息;
- 仅在三个连续的数据记号被成功归约之后,分析器才会恢复输出错误消息.
- </p>
- <p>注意到接受<code>error</code>记号的规则像其它任何规则一样也可以有动作.
- </p>
- <a name="IDX91"></a>
- <p>你可以通过使用宏<code>yyerrok</code>使错误消息立即恢复.
- 如果你在错误恢复规则的动作中使用它,
- 没有任何错误消息会被抑制.
- 这个宏不需要任何参数;
- <samp>`yyerrok;'</samp>是一个有效的C语句.
- </p>
- <a name="IDX92"></a>
- <p>先前的超前扫描记号在一个错误后会被立即再分析.
- 如果这是不可接受的,
- 那么宏<code>yyclearin</code>可以用于清除这个记号.
- 将语句<samp>`yyclearin;'</samp>写入错误恢恢复规则的动作中.
- </p>
- <p>例如,假设在遭遇一个语法错误时,
- 一个错误处理程序被调用用于将输入流前进到重新开始分析的地方.
- 词法分析器返回的下一个记号很可能是正确的.
- 前一个超前扫描记号应该用<samp>`yyclearin;'</samp>丢弃.
- </p>
- <a name="IDX93"></a>
- <p>宏<code>YYRECOVERING</code>代表一个表达式.
- 这个表达式在分析器从语法错误中恢复时值为1,在其它的时候值为0.
- 值为1指明了要抑制新的语法错误产生的错误消息.
- </p>
- <hr size="6">
- <a name="Context-Dependency"></a>
- <a name="SEC97"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC96"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC98"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC96"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC101"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="chapter"><a name="t98"></a> 7. 处理上下文依赖-Handling Context Dependencies </h1>
- <p>Bison的分析模式是首先分析记号,之后将它们组合成更大的句法单元.
- 在许多语言中,一个记号的意义受到上下文的影响.
- 尽管这破坏了Bison范例,
- 某些技术(被称为<em>kludges</em>)可以使你有能力为这种语言编写Bison分析器.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC98">7.1 符号类型中的语义信息-Semantic Info in Token Types</a></td><td> </td><td align="left" valign="top"> 对记号的分析可能依赖于语义上下文.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC99">7.2 词法关联-Lexical Tie-ins</a></td><td> </td><td align="left" valign="top"> 对记号的分析可能依赖于语言构造的上下文.
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC100">7.3 词法关联和错误恢复-Lexical Tie-ins and Error Recovery</a></td><td> </td><td align="left" valign="top"> 词法关联含有如何编写错误恢复规则的暗示.
- </td></tr>
- </tbody></table>
- <p>(实际上, "kludge"意思是既不干净也不健壮地完成某项工作的技术)
- </p>
- <hr size="6">
- <a name="Semantic-Tokens"></a>
- <a name="SEC98"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC97"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC99"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC97"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC97"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC101"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t99"></a> 7.1 符号类型中的语义信息-Semantic Info in Token Types </h2>
- <p>C语言就有上下文依赖:
- 标识符使用的方法依赖于当当前的意义.
- 例如,考虑这个:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">foo (x);
- </pre></td></tr></tbody></table>
- <p>这看起来是一个函数调用语句,但如果<code>foo</code>是一个typedef名称,
- 那么这实际上是一个<code>x</code>的声明.
- C语言的Bison分析器如何决定怎么分析这个输入呢?
- </p>
- <p><acronym>GNU</acronym> C使用的办法是让它们有不同的记号类型,
- <code>INDENTIFIER</code>和<code>TYPENAME</code>.
- 当<code>yylex</code>发现一个标识符,
- 它搜索当前的标识符声明以便决定返回什么样的记号类型:
- 如果标识符由一个typedef声明的,就返回<code>TYPENAME</code>,否则返回<code>IDENTIFIER</code>.
- </p>
- <p>这时,语法规则就可以通过对要识别的记号类型的选择来表达上下文依赖.
- <code>IDENTIFIER</code>可以作为一个表达式被接受,但是<code>TYPENAME</code>却不能.
- <code>TYPENAME</code>可以开始一个声明,但是<code>IDENTIFIER</code>却不可以.
- 在标识符的意义<em>不</em>明显的上下文中,
- 例如在可以隐藏一个typedef名称的声明中,
- <code>TYPENAME</code>和<code>IDENTIFIER</code>都是可接受的--
- 并没有一个针对没一种记号类型的规则.
- </p>
- <p>如果在接近分析标识符的地方决定允许什么种类的标识符,
- 那么这个技术可以简单的应用.
- 但是在C语言中却不总是这样:
- C允许重新声明之前声明的带有明确类型的typedef名称.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">typedef int foo, bar, lose;
- static foo (bar); /* redeclare <code>bar</code> as static variable */ /* 重新声明<code>bar</code>为一个静态变量 */
- static int foo (lose); /* redeclare <code>foo</code> as function */ /* 重新声明<code>foo</code>为一个函数 */
- </pre></td></tr></tbody></table>
- <p>不幸的是,这个名称被一个复杂的句法结构--"声明符"所分隔.
- </p>
- <p>结果,C语言的Bison分析器的某些部分要被复制,并且要改变所有非终结符的名称:
- 一次是为了分析可以被重定义的typedef声明,
- 一次是为了分析不能被重定义的声明.
- 这里是复制的部分.
- 为了简洁省略了动作.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">initdcl:
- declarator maybeasm '='
- init
- | declarator maybeasm
- ;
- notype_initdcl:
- notype_declarator maybeasm '='
- init
- | notype_declarator maybeasm
- ;
- </pre></td></tr></tbody></table>
- <p>在这里<code>initdcl</code>可以重新声明一个typedef名称,
- 但是<code>notype_initdcl</code>却不能.
- <code>declarator</code>和<code>notype_declarator</code>的区别在于同一类型的不同种类.
- </p>
- <p>这种技术和词法关联技术(在下一节描述)有一些相似之处.
- 它们的区别是,这里的信息是全局的并且用于程序的其它目的.
- 一个真正的词法关联含有一个受上下文控制的特殊目的标志.
- </p>
- <hr size="6">
- <a name="Lexical-Tie_002dins"></a>
- <a name="SEC99"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC98"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC100"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC97"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC97"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC101"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t100"></a> 7.2 词法关联-Lexical Tie-ins </h2>
- <p>另外一种处理上下文依赖的方法是<em>词法关联(lexical tie-in)</em>:
- 一个由Bison动作设置的标志,
- 它的目的是改变分析记号的方式.
- </p>
- <p>例如,假设我们有一种类似C的语言,
- 但是它带有一个特殊的<samp>`hex (<var>hex-expr</var>)'</samp>结构.
- 在关键字<code>hex</code>之后是一个括号之中全部为十六进制整数的表达式.
- 特别地,在那个上下文中,记号<samp>`a1b'</samp>必须被看做是一个整数而不是一个标识符.
- 这里就是你如何处理它:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%{
- int hexflag;
- int yylex (void);
- void yyerror (char const *);
- %}
- %%
- …
- expr: IDENTIFIER
- | constant
- | HEX '('
- { hexflag = 1; }
- expr ')'
- { hexflag = 0;
- $$ = $4; }
- | expr '+' expr
- { $$ = make_sum ($1, $3); }
- …
- ;
- constant:
- INTEGER
- | STRING
- ;
- </pre></td></tr></tbody></table>
- <p>这里我们假设<code>yylex</code>观察<code>hexflag</code>的值;
- 当它的值非零时,所有的整数被分析成十六进制数,
- 并且带有字母的标识符也尽可能的被翻译成整数.
- </p>
- <p><code>hexflag</code>出现在分析器文件的<var>Prologue</var>部分以便动作可以访问它
- (参阅<a href="#SEC44"><var>Prologue</var>部分-The Prologue</a>一章).
- 你还必须在<code>yylex</code>中编写代码来获得这个标志.
- </p>
- <hr size="6">
- <a name="Tie_002din-Recovery"></a>
- <a name="SEC100"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC99"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC101"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC97"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC97"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC101"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t101"></a> 7.3 词法关联和错误恢复-Lexical Tie-ins and Error Recovery </h2>
- <p>词法关联对你使用的任何错误恢复规则都有严格的要求.
- 参阅 <a href="#SEC96">错误恢复-Error Recovery</a>.
- </p>
- <p>这样的原因是错误恢复规则的目的是放弃对一个结构的分析并且恢复到某个更大的结构中去.
- 不例如,在类似C的语言中,
- 一个典型的错误恢复规则是跳过记号直到下一个分号,
- 并且开始分析一个新的语句,
- 像这样:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">stmt: expr ';'
- | IF '(' expr ')' stmt { … }
- …
- error ';'
- { hexflag = 0; }
- ;
- </pre></td></tr></tbody></table>
- <p>如果在<samp>`hex (<var>expr</var>)'</samp>之中存在一个语法错误,
- 这个错误恢复规则就会被应用,
- 完整的<samp>`hex (<var>expr</var>)'</samp>的动作永远都不会执行.
- 所以对于其余的输入或者直到下一个关键字<code>hex</code>,
- <code>hexflag</code>仍然被置1.这会导致标识符被错误地解释为整数.
- </p>
- <p>为了避免这个错误,错误恢复规则自己要将<code>hexflag</code>清零.
- </p>
- <p>也有可能存在一个与表达式一起工作的错误恢复规则.
- 例如,可能有一个应用于括号匹配的规则,
- 并且它跳跃到右括号:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">expr: …
- | '(' expr ')'
- { $$ = $2; }
- | '(' error ')'
- …
- </pre></td></tr></tbody></table>
- <p>如果这个规则在<code>hex</code>结构中执行,
- 它不会放弃那个结构(由于它作于在结构内部的括号(注:结构指<code>hex</code>结构)).
- 因此,它不应该将标志清零:
- <code>hex</code>结构的其余部分应该在该标志仍然有效的情况下被分析.
- </p>
- <p>如果有一个错误规则依靠当时的状况可能放弃<code>hex</code>结构也可能不放弃的话,
- 我们该怎么办?
- 没有办法编写一个可以决定是否放弃<code>hex</code>结构的动作.
- 所以,如果你使用了词法关联,
- 最好保证你的错误恢复规则不是这种类型.
- 你必须要确定每个规则总是要清零或总不要清零.
- </p>
- <hr size="6">
- <a name="Debugging"></a>
- <a name="SEC101"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC100"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC102"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC97"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC104"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="chapter"><a name="t102"></a> 8. 调式你的分析器-Debugging Your Parser </h1>
- <p>开发分析器可能是一种挑战,特别当你不理解它的算法的时候
- (参阅<a href="#SEC82">Bison分析器算法-The Bison Parser Algorithm</a>一章).
- 即使是这样,有些时候一个关于自动的详细描述可能会有所帮助
- (参阅<a href="#SEC102">理解你的分析器- Understanding Your Parser</a>一章),
- 或者跟踪分析器的执行可以给你关于为它什么做出不正确的行为一些灵感.
- (参阅<a href="#SEC103">跟踪你的分析器- Tracing Your Parser</a>一章).
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td><td> </td><td align="left" valign="top"> 理解你的分析器的结构
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC103">8.2 跟踪你的分析器-Tracing Your Parser</a></td><td> </td><td align="left" valign="top"> 跟踪你的分析器的执行
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Understanding"></a>
- <a name="SEC102"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC101"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC103"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC101"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC101"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC104"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t103"></a> 8.1 理解你的分析器-Understanding Your Parser </h2>
- <p>如同本文档其它部分描述的
- (参阅<a href="#SEC82">Bison分析器算法-The Bison Parser Algorithm</a>一章),
- Bison分析器是<em>移进/归约自动机(shift/reduce automata)</em>.
- 在一些情况下(比你希望的要更频繁),
- 调整或者简单的修正一个分析器需要考虑这个自动机.
- Bions提供了它(自动机)的两种表示方法,文本的或者图形的(作为一个<acronym>VCG</acronym>文件).
- </p>
- <p>当指定选项<samp>`--report'</samp>或者<samp>`--verbose'</samp>时Bison生成文本文件,
- 参阅 <a href="#SEC104">调用Bison-Invoking Bison</a>.
- 它的名称由移除分析器输出文件名<samp>`.tab.c'</samp>或者<samp>`.c'</samp>而添加<samp>`.output'</samp>取代.
- 因此,如果输入文件是<tt>`foo.y'</tt>,
- 那么默认的分析器文件为<tt>`foo.tab.c'</tt>.
- 结果,冗长(verbose)输出文件为<tt>`foo.output'</tt>.
- </p>
- <p>下面的语法文件<tt>`calc.y'</tt>将在稍后使用:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">%token NUM STR
- %left '+' '-'
- %left '*'
- %%
- exp: exp '+' exp
- | exp '-' exp
- | exp '*' exp
- | exp '/' exp
- | NUM
- ;
- useless: STR;
- %%
- </pre></td></tr></tbody></table>
- <p><code>bison</code> 报告:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">calc.y: warning: 1 useless nonterminal and 1 useless rule
- calc.y:11.1-7: warning: useless nonterminal: useless
- calc.y:11.10-12: warning: useless rule: useless: STR
- calc.y: conflicts: 7 shift/reduce
- </pre></td></tr></tbody></table>
- <p>当指定<samp>`--report=state'</samp>,
- 除了文件<tt>`calc.tab.c'</tt>,
- 它还创建了包含如下详细信息的文件<tt>`calc.outut'</tt>.
- 输出和精确表述的顺序可能有所不同,
- 但是对此的解释是相同的.
- </p>
- <p>第一个部分包括了由前面的与/或结合性解决的冲突的详细信息.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">Conflict in state 8 between rule 2 and token '+' resolved as reduce.
- Conflict in state 8 between rule 2 and token '-' resolved as reduce.
- Conflict in state 8 between rule 2 and token '*' resolved as shift.
- …
- </pre></td></tr></tbody></table>
- <p>下一个部分列出了仍然有冲突的状态清单.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">State 8 conflicts: 1 shift/reduce
- State 9 conflicts: 1 shift/reduce
- State 10 conflicts: 1 shift/reduce
- State 11 conflicts: 4 shift/reduce
- </pre></td></tr></tbody></table>
- <a name="IDX94"></a>
- <a name="IDX95"></a>
- <a name="IDX96"></a>
- <a name="IDX97"></a>
- <a name="IDX98"></a>
- <a name="IDX99"></a>
- <p>下一个部分报告了没有用处的记号,非终结符和规则.
- 没用处的非终结符和规则被移除以便产生一个更小的分析器,
- 但是没用记号被保留,因为它们可能被扫描器使用,
- (应该注意到"没用处的"和"没被使用的"之间的区别).
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">Useless nonterminals:
- useless
- Terminals which are not used:
- STR
- Useless rules:
- #6 useless: STR;
- </pre></td></tr></tbody></table>
- <p>下一个部分重新制造了Bison使用的精确语法:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">Grammar
- Number, Line, Rule
- 0 5 $accept -> exp $end
- 1 5 exp -> exp '+' exp
- 2 6 exp -> exp '-' exp
- 3 7 exp -> exp '*' exp
- 4 8 exp -> exp '/' exp
- 5 9 exp -> NUM
- </pre></td></tr></tbody></table>
- <p>并且报告了使用的符号:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">Terminals, with rules where they appear
- $end (0) 0
- '*' (42) 3
- '+' (43) 1
- '-' (45) 2
- '/' (47) 4
- error (256)
- NUM (258) 5
- Nonterminals, with rules where they appear
- $accept (8)
- on left: 0
- exp (9)
- on left: 1 2 3 4 5, on right: 0 1 2 3 4
- </pre></td></tr></tbody></table>
- <a name="IDX100"></a>
- <a name="IDX101"></a>
- <a name="IDX102"></a>
- <p>Bison之后进入到自己的自动机,
- 并且用<em>项目(items)</em>集,也被成为<em>指明规则(pointed rules)</em>,来描述每个状态.
- 每个都是一个产生式规则,并且带有表示输入光标的点号.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">state 0
- $accept -> . exp $ (rule 0)
- NUM shift, and go to state 1
- exp go to state 2
- </pre></td></tr></tbody></table>
- <p>这些有如下含义: "状态0相应地处于分析的开始,
- 在初始规则中,处于开始符号(这里是<code>exp</code>)的右端.
- 当分析器归约了一个产生的<code>exp</code>的规则并返回这个状态之后,
- 控制流跳转到状态2.
- 如果没有这样的非终结符转化并且超前扫描记号是<code>NUM</code>,
- 那么这个记号被移进到分析器栈中,控制流跳转到状态1.
- 任何其它的超前扫描记号都会引发一个语法错误."
- </p>
- <a name="IDX103"></a>
- <a name="IDX104"></a>
- <a name="IDX105"></a>
- <a name="IDX106"></a>
- <p>即使状态0中的唯一活动规则看起来是规则0,
- 报告将<code>NUM</code>列举为一个超前扫描记号,
- 这是因为<code>NUM</code>可以在任何转向<code>exp</code>的规则的开头.
- 默认地,Bison报告项目集的核心(<em>core</em> or <em>kernel</em> of the item set).
- 但是如果你想查看更详细的信息,你可以使用选项<samp>`--report=itemset'</samp>调用<code>bison</code>
- 来列出所有的项目,包括那些可以由此派生的.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">state 0
- $accept -> . exp $ (rule 0)
- exp -> . exp '+' exp (rule 1)
- exp -> . exp '-' exp (rule 2)
- exp -> . exp '*' exp (rule 3)
- exp -> . exp '/' exp (rule 4)
- exp -> . NUM (rule 5)
- NUM shift, and go to state 1
- exp go to state 2
- </pre></td></tr></tbody></table>
- <p>在状态1中...
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">state 1
- exp -> NUM . (rule 5)
- $default reduce using rule 5 (exp)
- </pre></td></tr></tbody></table>
- <p>规则5,<samp>`exp: NUM;'</samp>是完整的.
- 无论超前扫描记号(<samp>`$default'</samp>)是什么,分析器都会归约它.
- 如果是从状态0跳转过来,在归约之后会回到到状态0,并且之后会跳转到状态2(<samp>`exp: go to state 2'</samp>).
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">state 2
- $accept -> exp . $ (rule 0)
- exp -> exp . '+' exp (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp . '/' exp (rule 4)
- $ shift, and go to state 3
- '+' shift, and go to state 4
- '-' shift, and go to state 5
- '*' shift, and go to state 6
- '/' shift, and go to state 7
- </pre></td></tr></tbody></table>
- <p>在状态2中,自动机只能进行归约符号.
- 例如,根据项目<samp>`exp -> exp . '+' exp'</samp>,如果超前扫描记号为<samp>`+'</samp>,
- 它会被移进到分析器栈中,并且状态机控制会跳转到状态4,
- 对应项目<samp>`exp -> exp '+' . exp'</samp>.
- 由于没有默认动作,任何非上述列出的记号会引起一个语法错误.
- </p>
- <p>状态3被称为<em>终态(finial state)</em>)或者<em>接受态(accepting state)</em>:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">state 3
- $accept -> exp $ . (rule 0)
- $default accept
- </pre></td></tr></tbody></table>
- <p>初始规则已经完成(已经读取开始符号和输入终结),
- 分析成功退出.
- </p>
- <p>状态4到7解释的很直接,留给读者自己分析:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">state 4
- exp -> exp '+' . exp (rule 1)
- NUM shift, and go to state 1
- exp go to state 8
- state 5
- exp -> exp '-' . exp (rule 2)
- NUM shift, and go to state 1
- exp go to state 9
- state 6
- exp -> exp '*' . exp (rule 3)
- NUM shift, and go to state 1
- exp go to state 10
- state 7
- exp -> exp '/' . exp (rule 4)
- NUM shift, and go to state 1
- exp go to state 11
- </pre></td></tr></tbody></table>
- <p>正如报告开始部分声明的,<samp>`State 8 conflicts:1 shift/reduce'</samp>:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">state 8
- exp -> exp . '+' exp (rule 1)
- exp -> exp '+' exp . (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp . '/' exp (rule 4)
- '*' shift, and go to state 6
- '/' shift, and go to state 7
- '/' [reduce using rule 1 (exp)]
- $default reduce using rule 1 (exp)
- </pre></td></tr></tbody></table>
- <p>的确,有两个与超前扫描记号<samp>`/'</samp>关联的动作:
- 或者移进(并且转到状态7),或者归约规则1.
- 这个冲突意味着或者语法是歧义的或者分析器缺少做出正确决定的信息.
- 这个语法确实是歧义的,因为我们并未指明<samp>`/'</samp>的优先级,
- 句子<samp>`NUM + NUM / NUM'</samp>可以被分析为对应于移进<samp>`/'</samp>的<samp>`NUM + (NUM / NUM)'</samp>,
- 也可以被分析为对应于归约规则1的<samp>`(NUM + NUM) / NUM'</samp>.
- </p>
- <p>由于在<acronym>LALR</acronym>(1)分析中只能做出一个动作,
- Bison武断地选择不使用归约,参阅<a href="#SEC84">移进/归约冲突-Shift/Reduce Conflicts</a>.
- 被丢弃的动作被报告于方括号中.
- </p>
- <p>注意到先前的所有状态只有一个单一可能的动作:
- 或者移进下一个记号并且转到相应的状态,
- 或者归约一个规则.
- 在其它的情况下,
- 例如,
- 当移进<em>和</em>归约都是可能的或者<em>多个</em>归约都是可能的,
- 这是需要超前扫描记号来选择动作.
- 状态8就是这样一种状态:如果超前扫描记号是<samp>`*'</samp>或者<samp>`/'</samp>
- 那么多做是移进,否则动作是归约动作1.
- 换句话说,前两项,对应于规则1,当超前扫描记号是<samp>`*'</samp>的时候是不符合条件的,
- 因为我们指明了<samp>`*'</samp>有比<samp>`+'</samp>更高的优先级.
- 更普通地说,
- 一些项目仅在某些可能的超前扫描记号下是符合条件的.
- 当使用选项<samp>`--report=look-ahead'</samp>,Bison会指明这些超前扫描记号:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">state 8
- exp -> exp . '+' exp [$, '+', '-', '/'] (rule 1)
- exp -> exp '+' exp . [$, '+', '-', '/'] (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp . '/' exp (rule 4)
- '*' shift, and go to state 6
- '/' shift, and go to state 7
- '/' [reduce using rule 1 (exp)]
- $default reduce using rule 1 (exp)
- </pre></td></tr></tbody></table>
- <p>其余的状态与之类似:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">state 9
- exp -> exp . '+' exp (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp '-' exp . (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp . '/' exp (rule 4)
- '*' shift, and go to state 6
- '/' shift, and go to state 7
- '/' [reduce using rule 2 (exp)]
- $default reduce using rule 2 (exp)
- state 10
- exp -> exp . '+' exp (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp '*' exp . (rule 3)
- exp -> exp . '/' exp (rule 4)
- '/' shift, and go to state 7
- '/' [reduce using rule 3 (exp)]
- $default reduce using rule 3 (exp)
- state 11
- exp -> exp . '+' exp (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp . '/' exp (rule 4)
- exp -> exp '/' exp . (rule 4)
- '+' shift, and go to state 4
- '-' shift, and go to state 5
- '*' shift, and go to state 6
- '/' shift, and go to state 7
- '+' [reduce using rule 4 (exp)]
- '-' [reduce using rule 4 (exp)]
- '*' [reduce using rule 4 (exp)]
- '/' [reduce using rule 4 (exp)]
- $default reduce using rule 4 (exp)
- </pre></td></tr></tbody></table>
- <p>注意到状态11包含冲突不仅仅因为缺少<samp>`/'</samp>相对于<samp>`+'</samp>,<samp>`-'</samp>和<samp>`*'</samp>的优先级,
- 还由于并未指定<samp>`/'</samp>的结合性.
- </p>
- <hr size="6">
- <a name="Tracing"></a>
- <a name="SEC103"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC102"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC104"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC101"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC101"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC104"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t104"></a> 8.2 跟踪你的分析器-Tracing Your Parser </h2>
- <p>如果Bison语法编译正确但是在运行的时候并未达到你想要的目的,
- <code>yydeug</code>分析器追踪特性可以帮你指明原因.
- </p>
- <p>有多种方法激活追踪机制的编译:
- </p>
- <dl compact="compact">
- <dt> 宏 <code>YYDEBUG</code></dt>
- <dd><a name="IDX107"></a>
- <p>当你编译分析器的时候,将宏<code>YYDEBUG</code>定义成非零指.
- 这种方式与<acronym>POSIX</acronym> Yacc兼容.
- 你可以使用<samp>`-DYYDEBUG=1'</samp>作为一个编译器选项或者你可以将<samp>`define YYDEBUG 1'</samp>
- 放入语法文件的<var>Prologue</var>部分.(参阅<a href="#SEC44"><var>Prologue</var>部分- The Prologue</a>一章).
- </p>
- </dd>
- <dt> 选项 <samp>`-t'</samp>, <samp>`--debug'</samp></dt>
- <dd><p>当你运行Bison(参阅<a href="#SEC104">调用Bison-Invoking Bison</a>一章)时,
- 使用<samp>`-t'</samp>选项.
- 这也与<acronym>POSIX</acronym>兼容.
- </p>
- </dd>
- <dt> 指令 <samp>`%debug'</samp></dt>
- <dd><a name="IDX108"></a>
- <p>加入<code>%debug</code>指令(参阅<a href="#SEC71">Bison声明总结-Bison Declaration Summary</a>一章).
- 这是一个Bison扩展,当Bison为不使用预处理器的语言输出分析器的时候很实用.
- 除非你要考虑<acronym>POSIX</acronym>可移植性问题,
- 否则这是一个很好的解决方案.
- </p></dd>
- </dl>
- <p>我们建议你应该总是激活调式选项以便随时进行调试.
- </p>
- <p>追踪机制使用<code>YYFPRINTF (stderr, <var>format</var>, <var>args</var>)</code>形式的宏调用输出信息.
- 在这里<var>format</var>和<var>args</var>是普通的<code>printf</code>的格式和参数.
- 如果你定义<code>YYDEBUG</code>为一个非零值但是没有定义<code>YYFPRINTF</code>,
- <code><stdio.h></code>自动被加入并且<code>YYPRINTF</code>被定义为<code>fprintf</code>.
- </p>
- <p>一旦你使用了追踪机制编译程序,
- 请求一个追踪的方法是在变量<code>yydebug</code>中存储一个非零值.
- 你可以考编写C代码(也许在<code>main</code>中)做到这一点,
- 你也可以使用C调试器来改变这个值.
- </p>
- <p>当<code>yydebug</code>为非零的时候,分析器执行的每一步都产生一个写入<code>stderr</code>一两行的追踪信息.
- 追踪信息告诉你这些东西:
- </p>
- <ul>
- <li>
- 每次调用<code>yylex</code>时,读取记号的种类.
- </li><li>
- 每次移进记号的时候,分析器栈的深度和完整的内容.
- (参阅<a href="#SEC91">分析器状态-Parser States</a>一章)
- </li><li>
- 每次归约一个规则时,这个规则是哪个规则,和在归约之后状态栈的完整内容.
- </li></ul>
- <p>弄清这些信息的意思有助于查阅由Bison选项<samp>`-v'</samp>产生的列表文件(listing file).
- (参阅<a href="#SEC104">调用Bison-Invoking Bison</a>一章).
- 这个文件按照各种规则的位置展示了每个状态的意义,
- 还展示了每个状态会怎样处理每个输入记号.
- 当你阅读连续的追踪信息时,
- 你可以看到分析器按照它在列表文件中的指示工作.
- 最终你会到达发生不期望事情的地方,
- 并且你会发现语法的哪一个部分存在问题.
- </p>
- <p>分析器文件是一个C程序,你可以使用C调式器调试它,
- 但是我们很难解释它在做些什么.
- 分析器函数是一个有限状态机解释器,
- 除了动作以外它反复执行相同的代码.
- 只有变量的值才能表示它正在语法的那个地方工作.
- </p>
- <a name="IDX109"></a>
- <p>调试信息通常给出了每个读入记号的符号类型而不是它的语义值.
- 你可以定一个名为<code>YYPRINT</code>的宏来打印这个值.
- 如果你定义<code>YYPRINT</code>,
- 它应带有三个参数.
- 分析器将传递标准I/O流,记号类型的数字码和记号指(从<code>yylval</code>中).
- </p>
- <p>这里有一个适用于多功能计算器的<code>YYPRINT</code>
- (参阅<a href="#SEC38"><code>mfcalc</code>的声明部分-Declarations for <code>mfcalc</code></a>一章):
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample">%{
- static void print_token_value (FILE *, int, YYSTYPE);
- #define YYPRINT(file, type, value) print_token_value (file, type, value)
- %}
- … %% … %% …
- static void
- print_token_value (FILE *file, int type, YYSTYPE value)
- {
- if (type == VAR)
- fprintf (file, "%s", value.tptr->name);
- else if (type == NUM)
- fprintf (file, "%d", value.val);
- }
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="Invocation"></a>
- <a name="SEC104"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC103"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC105"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC101"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC108"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="chapter"><a name="t105"></a> 9. 调用Bison-Invoking Bison </h1>
- <p>调用Bison的通常方法如下:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">bison <var>infile</var>
- </pre></td></tr></tbody></table>
- <p>这里的<var>file</var>是通常以<samp>`.y'</samp>结尾的语法文件名.
- 分析器文件名由<tt>`.tab.c'</tt>代替<samp>`.y'</samp>取得.
- 因此,<samp>`bison foo.y'</samp>产生<tt>`foo.tab.c'</tt>,
- <samp>`bison hack/foo.y'</samp>产生<tt>`hack/foo.tab.c'</tt>.
- 如果你在你语法文件中使用C++代码而不是C,
- 把它命名为<tt>`foo.ypp'</tt>或者<tt>`foo.y++'</tt>.
- 那么,输出文件的扩展名类型给定的输入
- (分别为<tt>`foo.tab.cpp'</tt>和<tt>`foo.tab.c++'</tt>.
- </p>
- <p>例如:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">bison -d <var>infile.yxx</var>
- </pre></td></tr></tbody></table>
- <p>将会产生<tt>`infile.tab.cxx'</tt>和<tt>`infile.tab.hxx'</tt>,并且
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">bison -d -o <var>output.c++</var> <var>infile.y</var>
- </pre></td></tr></tbody></table>
- <p>会产生<tt>`output.c++'</tt>和<tt>`outfile.h++'</tt>.
- </p>
- <p>为了与<acronym>POSIX</acronym>兼容,
- 标准的Bison发行版也包含一个名为<code>yacc</code>的脚本,
- 该脚本使用<samp>`-y'</samp>选项调用Bison.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC105">9.1 Bison选项-Bison Options</a></td><td> </td><td align="left" valign="top"> 按简写选项的字母顺序详细描述所有选项
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC106">9.2 选项交叉键-Option Cross Key</a></td><td> </td><td align="left" valign="top"> 按字母顺序列出长选项
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC107">9.3 Yacc库-Yacc Library</a></td><td> </td><td align="left" valign="top"> 与Yacc兼容的<code>yylex</code>和<code>main</code>
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Bison-Options"></a>
- <a name="SEC105"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC104"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC106"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC104"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC104"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC108"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t106"></a> 9.1 Bison选项-Bison Options </h2>
- <p>Bison既支持传统的单字母选项也支持可记忆长选项名称.
- 用<samp>`--'</samp>取代<samp>`-'</samp>来指明常长项名称.
- Bison允许选项名称缩写只要它们是唯一的.
- 当长选项带有一个参如,如<samp>`--file-prefix'</samp>,
- 用<samp>`='</samp>连接选项名称和参数.
- </p>
- <p>这里有一个Bison可以是用的选项清单,
- 按照短选项字母顺序排列.
- 在它之后是一个常选项的交叉键.
- </p>
- <p>操作模式:
- </p><dl compact="compact">
- <dt> <samp>`-h'</samp></dt>
- <dt> <samp>`--help'</samp></dt>
- <dd><p>打印一个Bison命令行选项的总结并退出.
- </p>
- </dd>
- <dt> <samp>`-V'</samp></dt>
- <dt> <samp>`--version'</samp></dt>
- <dd><p>打印Bison的版本号并退出.
- </p>
- </dd>
- <dt> <samp>`-y'</samp></dt>
- <dt> <samp>`--yacc'</samp></dt>
- <dd><p>与<samp>`-o y.tab.c'</samp>等价;
- 分析器输出文件名为<tt>`y.tab.c'</tt>,
- 并且其它输出称为<tt>`y.output'</tt>和<tt>`y.tab.h'</tt>.
- 这个选项的目的是模拟Yacc的输出文件命名惯例.
- 因此,如下的shell脚本可以替代Yacc,
- 并且Bison发行版包含一个这种为<acronym>POSIX</acronym>兼容的脚本.
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">#! /bin/sh
- bison -y "$@"
- </pre></td></tr></tbody></table></dd>
- </dl>
- <p>调整分析器:
- </p>
- <dl compact="compact">
- <dt> <samp>`-S <var>file</var>'</samp></dt>
- <dt> <samp>`--skeleton=<var>file</var>'</samp></dt>
- <dd><p>指明要使用的骨架(skeleton).
- 除非你正在开发Bison否你很可能不需要这个选项.
- </p>
- </dd>
- <dt> <samp>`-t'</samp></dt>
- <dt> <samp>`--debug'</samp></dt>
- <dd><p>在分析器文件中,定义宏<code>YYDEBUG</code>为1,如果还没有定义它,
- 以便调试机制被编译.
- 参阅 <a href="#SEC103">追踪你的分析器-Tracing Your Parser</a>.
- </p>
- </dd>
- <dt> <samp>`--locations'</samp></dt>
- <dd><p><code>%locations</code>的伪装.参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p>
- </dd>
- <dt> <samp>`-p <var>prefix</var>'</samp></dt>
- <dt> <samp>`--name-prefix=<var>prefix</var>'</samp></dt>
- <dd><p><code>%name-prefix="<var>prefix</var>"</code>的伪装.
- 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p>
- </dd>
- <dt> <samp>`-l'</samp></dt>
- <dt> <samp>`--no-lines'</samp></dt>
- <dd><p>在分析器文件中不放入任何的<code>#line</code>预处理器命令.
- Bison通常将它们放入分析器文件以便C编译起和调试器将错误关联到你的源文件,
- 语法文件.
- 这个选项会关联错误到分析器文件,将它视为一个独立的源文件.
- </p>
- </dd>
- <dt> <samp>`-n'</samp></dt>
- <dt> <samp>`--no-parser'</samp></dt>
- <dd><p><code>%no-parser</code>的伪装.
- 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p>
- </dd>
- <dt> <samp>`-k'</samp></dt>
- <dt> <samp>`--token-table'</samp></dt>
- <dd><p><code>%token-table</code>的伪装.
- 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p></dd>
- </dl>
- <p>调整输出:
- </p>
- <dl compact="compact">
- <dt> <samp>`-d'</samp></dt>
- <dt> <samp>`--defines'</samp></dt>
- <dd><p>伪装<code>%defines</code>,例如,向一个额外的文件写入语法中记号类型名称的宏定义和一些其它的声明.
- 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p>
- </dd>
- <dt> <samp>`--defines=<var>defines-file</var>'</samp></dt>
- <dd><p>与上述相同,但是保存到文件<var>defines-file</var>.
- </p>
- </dd>
- <dt> <samp>`-b <var>file-prefix</var>'</samp></dt>
- <dt> <samp>`--file-prefix=<var>prefix</var>'</samp></dt>
- <dd><p><code>%verbose</code>的伪装,例如,指明所有Bison输出文件的前缀.
- 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p>
- </dd>
- <dt> <samp>`-r <var>things</var>'</samp></dt>
- <dt> <samp>`--report=<var>things</var>'</samp></dt>
- <dd><p>向一个额外的输出文件写入如下<var>things</var>的详细描述清,并由逗号分隔:
- </p>
- <dl compact="compact">
- <dt> <code>state</code></dt>
- <dd><p>语法,冲突(解决的和未解决的)以及<acronym>LALR</acronym>自动机.
- </p>
- </dd>
- <dt> <code>look-ahead</code></dt>
- <dd><p>包含<code>state</code>并且增加每个规则的超前扫描记号集自动机的描述.
- </p>
- </dd>
- <dt> <code>itemset</code></dt>
- <dd><p>包含<code>state</code>并且增加每个状态的全部项目集的自动机而不仅仅是它核心的自动机.
- </p></dd>
- </dl>
- <p>例如,在下面的语法中
- </p>
- </dd>
- <dt> <samp>`-v'</samp></dt>
- <dt> <samp>`--verbose'</samp></dt>
- <dd><p><code>%verbose</code>的伪装,例如,向额外的输出文件写入语法和分析器的详细描述.
- 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p>
- </dd>
- <dt> <samp>`-o <var>filename</var>'</samp></dt>
- <dt> <samp>`--output=<var>filename</var>'</samp></dt>
- <dd><p>为分析器文件指明<var>filename</var>.
- </p>
- <p>其它输出文件的名称像<samp>`-v'</samp>和<samp>`-d'</samp>选项的描述一样由<var>filename</var>构成.
- </p>
- </dd>
- <dt> <samp>`-g'</samp></dt>
- <dd><p>输出一个由Bison计算的<acronym>LALR</acronym>(1)语法自动机的<acronym>VCG</acronym>定义.
- 如果语法文件是<tt>`foo.y'</tt>,
- <acronym>VCG</acronym>输出文件将会是<tt>`foo.vcg'</tt>.
- </p>
- </dd>
- <dt> <samp>`--graph=<var>graph-file</var>'</samp></dt>
- <dd><p><var>-graph</var>的行为和<samp>`-g'</samp>的行为一样.
- 唯一的区别在于它含有一个指明输出图形文件的可选参数.
- </p></dd>
- </dl>
- <hr size="6">
- <a name="Option-Cross-Key"></a>
- <a name="SEC106"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC105"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC107"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC104"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC104"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC108"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t107"></a> 9.2 选项交叉键-Option Cross Key </h2>
- <p>这里有一个选项列表,按照长选项的字母排序,来帮助你找到相应的所写选项.
- </p>
- <hr size="6">
- <a name="Yacc-Library"></a>
- <a name="SEC107"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC106"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC108"> > </a>]</td>
- <td align="left" valign="middle"> &nbsp; </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC104"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC104"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC108"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t108"></a> 9.3 Yacc库-Yacc Library </h2>
- <p>Yacc库包含<code>yyerror</code>和<code>main</code>函数的默认实现.
- 通常情况下,这些默认实现没有什么用处,但是<acronym>POSIX</acronym>要求它们.
- 要使用Yacc库,使用选项<samp>`-ly'</samp>链接你的程序.
- 注意到Bison实现的Yacc库在<acronym>GNU</acronym>通用许可证下发行.
- (参阅<a href="#SEC3">GNU GENERAL PUBLIC LICENSE</a>一章).
- </p>
- <p>如果你使用Yacc库的<code>yyerror</code>函数,
- 你应该如下地声明<code>yyerror</code>:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int yyerror (char const *);
- </pre></td></tr></tbody></table>
- <p>Bison忽略<code>yyerror</code>返回的<code>int</code>值.
- 如果你使用Yacc库的<code>main</code>函数,
- 你的<code>yyparse</code>函数应该有如下原型:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">int yyparse (void);
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="FAQ"></a>
- <a name="SEC108"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC107"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC109"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC104"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC114"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="chapter"><a name="t109"></a> 10. 常见问题-Frequently Asked Questions </h1>
- <p>许多关于Bison的问题会偶尔出现.
- 这里提到一些.
- </p>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC109">10.1 分析器栈溢出-Parser Stack Overflow</a></td><td> </td><td align="left" valign="top"> 突破栈限制
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC110">10.2 我如何复位分析器-How Can I Reset the Parser</a></td><td> </td><td align="left" valign="top"> <code>yyparse</code>保持一些状态
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC111">10.3 被销毁的字符串-Strings are Destroyed</a></td><td> </td><td align="left" valign="top"> <code>yylval</code>丢掉了字符串的追踪
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC112">10.4 C++分析器-C++ Parsers</a></td><td> </td><td align="left" valign="top"> 使用C++编译器编译分析器
- </td></tr>
- <tr><td align="left" valign="top"><a href="#SEC113">10.5 实现跳转/循环-Implementing Gotos/Loops</a></td><td> </td><td align="left" valign="top"> 在计算器中控制流
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="Parser-Stack-Overflow"></a>
- <a name="SEC109"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC108"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC110"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC108"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC108"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC114"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t110"></a> 10.1 分析器栈溢出-Parser Stack Overflow </h2>
- <table><tbody><tr><td> </td><td><pre name="code" class="display">我的分析器返回带有<samp>`parser stack overflow'</samp>的消息.
- 我能做些什么?
- </pre></td></tr></tbody></table>
- <p>这个问题已经在其它地方讨论过了参阅 <a href="#SEC50">Recursive Rules</a>.
- </p>
- <hr size="6">
- <a name="How-Can-I-Reset-the-Parser"></a>
- <a name="SEC110"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC109"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC111"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC108"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC108"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC114"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t111"></a> 10.2 我如何复位分析器-How Can I Reset the Parser </h2>
- <p>下面的现象有许多征兆,导致了下面典型的问题:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="display">我调用了<code>yyparse</code>多次,
- 当输入正确时,它正确地工作;
- 但是当发现一个分析错误的时,所有其它的调用也失败了.
- 我如何才能重置<code>yyparse</code>的错误标志?
- </pre></td></tr></tbody></table>
- <p>或者:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="display">我的分析器包含了一个对<samp>`#include'</samp>类似特性的支持.
- 当我从<code>yyparse</code>调用<code>yyparse</code>时,即使我指明我需要一个<code>%pure-parser</code>,
- 它仍然会失败.
- </pre></td></tr></tbody></table>
- <p>这些典型的问题并不产生于Bison自己而是产生于Lex生成的扫描器.
- 出于速度的目的,这些扫描器使用容量很大的缓冲区,
- 它们可能不会注意到输入文件的变化.
- 作为一个例子,考虑下面的源文件,
- </p>
- <p><tt>`first-line.l'</tt>:
- </p>
- <pre name="code" class="verbatim">%{
- #include <stdio.h>
- #include <stdlib.h>
- %}
- %%
- .*/n ECHO; return 1;
- %%
- int
- yyparse (char const *file)
- {
- yyin = fopen (file, "r");
- if (!yyin)
- exit (2);
- /* One token only. */ /* 只有一个记号 */
- yylex ();
- if (fclose (yyin) != 0)
- exit (3);
- return 0;
- }
- int
- main (void)
- {
- yyparse ("input");
- yyparse ("input");
- return 0;
- }
- </pre>
- <p>如果文件<tt>`input'</tt>包含
- </p>
- <pre name="code" class="verbatim">input:1: Hello,
- input:2: World!
- </pre>
- <p>那么你并未两次取得第一行,而是:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">$ <kbd>flex -ofirst-line.c first-line.l</kbd>
- $ <kbd>gcc -ofirst-line first-line.c -ll</kbd>
- $ <kbd>./first-line</kbd>
- input:1: Hello,
- input:2: World!
- </pre></td></tr></tbody></table>
- <p>因此,无论什么时候改变<code>yyin</code>,
- 你必须告诉Lex声称的扫描器丢弃当前的缓冲转换到新的缓冲中.
- 这依赖于你的Lex的实现;可以参阅它的文档获取更多信息.
- 对于Flex,在每一个<code>yyin</code>的改变后调用<samp>`YY_FLUSH_BUFFER'</samp>可以做到这一点.
- 如果你的Flex生成扫描器需要读取多个输入流来处理类似文件包含的特性,
- 你可以考虑使用FLex函数如<samp>`yy_switch_to_buffer'</samp>来操纵多个输入缓冲.
- </p>
- <p>如果你的FLex声称扫描器使用了开始条件(参阅<cite>The Flex Manual</cite>中`Start conditions'一章<a href="http://blog.csdn.net/sirouni2003/article/details/flex.html#Start-conditions">(flex)Start conditions</a>),
- 你还可能复位扫描器状态,例如,
- 使用一个<code>BEGIN (0)</code>调用,退回到开始条件.
- </p>
- <hr size="6">
- <a name="Strings-are-Destroyed"></a>
- <a name="SEC111"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC110"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC112"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC108"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC108"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC114"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t112"></a> 10.3 被销毁的字符串-Strings are Destroyed </h2>
- <table><tbody><tr><td> </td><td><pre name="code" class="display">我的分析器好像销毁了旧字符串,或者它可能失去了对它们的追踪.
- 它报告<samp>`"bar", "bar"'</samp>或者甚至<samp>`"foo/nbar", "bar"'</samp>而不是
- 报告<samp>`"foo", "bar"'</samp>.
- </pre></td></tr></tbody></table>
- <p>这个错误可能是发送到Bison"错误报告"列表中最频繁的一个,
- 但它只是一个对扫描器角色产生的误解.
- 考虑如下的Lex代码:
- </p>
- <pre name="code" class="verbatim">%{
- #include <stdio.h>
- char *yylval = NULL;
- %}
- %%
- .* yylval = yytext; return 1;
- /n /* IGNORE */ /* 忽略 */
- %%
- int
- main ()
- {
- /* Similar to using $1, $2 in a Bison action. */
- /* 类似在Bison动作中使用的$1,$2 */
- char *fst = (yylex (), yylval);
- char *snd = (yylex (), yylval);
- printf ("/"%s/", /"%s/"/n", fst, snd);
- return 0;
- }
- </pre>
- <p>如果你编译并且运行这段代码,你得到:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">$ <kbd>flex -osplit-lines.c split-lines.l</kbd>
- $ <kbd>gcc -osplit-lines split-lines.c -ll</kbd>
- $ <kbd>printf 'one/ntwo/n' | ./split-lines</kbd>
- "one
- two", "two"
- </pre></td></tr></tbody></table>
- <p>这是由于<code>yytext</code>是一个在动作中用于<em>读取</em>的缓冲区,
- 但是如果你要保留它,你必须复制它(例如,使用<code>strdup</code>).
- 应注意到输出可能依赖于你的Lex实现怎么处理<code>yytext</code>.
- 例如当指定了Lex兼容性选项<samp>`-l'</samp>(它引发了选项<samp>`%array'</samp>),
- Flex产生了不同的行为:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="example">$ <kbd>flex -l -osplit-lines.c split-lines.l</kbd>
- $ <kbd>gcc -osplit-lines split-lines.c -ll</kbd>
- $ <kbd>printf 'one/ntwo/n' | ./split-lines</kbd>
- "two", "two"
- </pre></td></tr></tbody></table>
- <hr size="6">
- <a name="C_002b_002b-Parsers"></a>
- <a name="SEC112"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC111"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC113"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC108"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC108"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC114"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t113"></a> 10.4 C++分析器-C++ Parsers </h2>
- <table><tbody><tr><td> </td><td><pre name="code" class="display">我如何产生使用C++代码的分析器?
- </pre></td></tr></tbody></table>
- <p>我们正致力于Bison的C++输出,
- 但是不幸的是,由于缺少时间,骨架尚未完成.
- 它的功能很强大,但是由于多方面的关系,
- 它<em>可能</em>破坏向后兼容性的额外工作.
- 由于C++骨架尚未编入文档,
- 我们并不认为我们自己必须超这个接口努力,
- 尽管如此,我们会尽最大努力保证兼容性.
- </p>
- <p>另一种可能是使用正规C分析器并使用C++编译器进行编译.
- 倘若你能忍受一些简单C++规则,例如不能在联合体中加入"真正的类"(例如,
- 带有构造函数的结构体),这个就可以正常工作.
- 因此,在<code>%union</code>中应该使用指向类的指针.
- </p>
- <hr size="6">
- <a name="Implementing-Gotos_002fLoops"></a>
- <a name="SEC113"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC112"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC114"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC108"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC108"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC114"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="section"><a name="t114"></a> 10.5 实现跳转/循环-Implementing Gotos/Loops </h2>
- <table><tbody><tr><td> </td><td><pre name="code" class="display">我的简单计算器支持变量,赋值和函数,
- 但是我如何才能实现跳转或循环?
- </pre></td></tr></tbody></table>
- <p>虽然这个文档中包含的例子很有教学性,
- 但它模糊了分析器(它的工作是恢复文字的结构并将它转化为程序模块)
- 和处理这些结构的过程(如执行)之间的区别.
- 这在被称为直接线性程序中工作良好.
- 例如直接执行模式:一个接一个的执行简单指令.
- </p>
- <a name="IDX110"></a>
- <a name="IDX111"></a>
- <p>如果你需要的更丰富的模式,
- 你可能需要分析器生一种表示它(注:分析器)已经恢复的结构的树;
- 这种树被通常成为<em>抽象语法树(abstract syntax tree)</em>或者简写为<em><acronym>AST</acronym></em>.
- 之后,用多种方法遍历这棵树会激活对它的执行或翻译,
- 这最终会导致产生一个解释起或者编译器.
- </p>
- <p>这个主题超出了这个手册的讨论范围,
- 读者可以参阅这方面的专门文献.
- </p>
- <hr size="6">
- <a name="Table-of-Symbols"></a>
- <a name="SEC114"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC113"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC115"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC108"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC115"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="appendix"><a name="t115"></a> A. Bison符号-Bison Symbols </h1>
- <dl>
- <dt><u>变量:</u> <b>@$</b>
- <a name="IDX112"></a>
- </dt>
- <dd><p>在动作中,规则左手端的位置
- 参阅 <a href="#SEC57">位置概述-Locations Overview</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>@<var>n</var></b>
- <a name="IDX113"></a>
- </dt>
- <dd><p>在动作中,规则右端第<var>n</var>个符号的位置.
- 参阅 <a href="#SEC57">位置概述-Locations Overview</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>$$</b>
- <a name="IDX114"></a>
- </dt>
- <dd><p>在动作中,规则左端的语义值.
- 参阅 <a href="#SEC54">动作-Actions</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>$<var>n</var></b>
- <a name="IDX115"></a>
- </dt>
- <dd><p>在动作中,规则右端第<var>n</var>个符号的语义值.
- 参阅 <a href="#SEC54">动作-Actions</a>.
- </p></dd></dl>
- <dl>
- <dt><u>分隔符:</u> <b>%%</b>
- <a name="IDX116"></a>
- </dt>
- <dd><p>用于分隔语法规则部分和Bison声明部分或者<var>epilogue</var>部分.
- 参阅 <a href="#SEC18">Bison语法文件的布局-The Overall Layout of a Bison Grammar</a>.
- </p></dd></dl>
- <dl>
- <dt><u>分隔符:</u> <b>%{<var>code</var>%}</b>
- <a name="IDX117"></a>
- </dt>
- <dd><p>在<samp>`%{'</samp>和<samp>`%}'</samp>之间的代码不做任何解释被直接复制到输出文件.
- 这些代码组成了输入文件的<var>Prologue</var>部分.
- 参阅 <a href="#SEC43">Bison语法的提纲-Outline of a Bison Grammar</a>.
- </p></dd></dl>
- <dl>
- <dt><u>结构:</u> <b>/*…</b><i>*/</i>
- <a name="IDX118"></a>
- </dt>
- <dd><p>注释分隔符,类似C.
- </p></dd></dl>
- <dl>
- <dt><u>分隔符:</u> <b>:</b>
- <a name="IDX119"></a>
- </dt>
- <dd><p>分隔动作的结果和它的部件.
- 参阅 <a href="#SEC49">描述语法规则的语法-Syntax of Grammar Rules</a>.
- </p></dd></dl>
- <dl>
- <dt><u>分隔符:</u> <b>;</b>
- <a name="IDX120"></a>
- </dt>
- <dd><p>结束一个规则. 参阅 <a href="#SEC49">描述语法规则的语法-Syntax of Grammar Rules</a>.
- </p></dd></dl>
- <dl>
- <dt><u>分隔符:</u> <b>|</b>
- <a name="IDX121"></a>
- </dt>
- <dd><p>分隔同一个非终结符结果的不同规则.
- 参阅 <a href="#SEC49">描述语法规则的语法-Syntax of Grammar Rules</a>.
- </p></dd></dl>
- <dl>
- <dt><u>符号:</u> <b>$accept</b>
- <a name="IDX122"></a>
- </dt>
- <dd><p>预定义非终结符,
- 它的唯一规则为<samp>`$accept: <var>start</var>
- $end'</samp>,
- 这里的<var>start</var>是开始符号.
- 参阅 <a href="#SEC69">开始符号- The Start-Symbol</a>.
- 它不能在语法中使用.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%debug</b>
- <a name="IDX123"></a>
- </dt>
- <dd><p>激活分析器调试.
- 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%defines</b>
- <a name="IDX124"></a>
- </dt>
- <dd><p>为扫描器创建一个头文件的Bison声明.
- 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%destructor</b>
- <a name="IDX125"></a>
- </dt>
- <dd><p>指明分析器如何回收被丢弃符号相关的内存.
- 参阅 <a href="#SEC67">释放丢弃的符号- Freeing Discarded Symbols</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%dprec</b>
- <a name="IDX126"></a>
- </dt>
- <dd><p>在分析的时候赋予规则一个优先级来解决归约/归约冲突的Bison声明.
- 参阅 <a href="#SEC11">编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers</a>.
- </p></dd></dl>
- <dl>
- <dt><u>符号:</u> <b>$end</b>
- <a name="IDX127"></a>
- </dt>
- <dd><p>用来标记流结束的预定义记号,不能在语法中使用.
- </p></dd></dl>
- <dl>
- <dt><u>符号:</u> <b>error</b>
- <a name="IDX128"></a>
- </dt>
- <dd><p>一个保留的用于错误恢复的记号名称.
- 这个记号可以用在语法规则中用来允许Bison分析器在不终止处理的前提下
- 识别一个错误.
- 实际上,一个包含错误的句子可被认为是有效的.
- 遇到一个语法错误时,
- 记号<code>error</code>成为了当前的超前扫描记号.
- 与<code>error</code>相应的动作被执行,并且超前扫描记号被重置为
- 最初引起错误的记号.
- 参阅 <a href="#SEC96">错误恢复-Error Recovery</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%error-verbose</b>
- <a name="IDX129"></a>
- </dt>
- <dd><p>请求冗长模式的Bison声明,
- 指明了当调用<code>yyerror</code>时的错误消息字符串.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%file-prefix="<var>prefix</var></b><i>"</i>
- <a name="IDX130"></a>
- </dt>
- <dd><p>设置输出文件前缀的Bison声明.参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%glr-parser</b>
- <a name="IDX131"></a>
- </dt>
- <dd><p>声称<acronym>GLR</acronym>分析器的Bison声明.
- 参阅 <a href="#SEC11">编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%initial-action</b>
- <a name="IDX132"></a>
- </dt>
- <dd><p>在分析器前运行代码.参阅 <a href="#SEC66">在分析前执行动作- Performing Actions before Parsing</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%left</b>
- <a name="IDX133"></a>
- </dt>
- <dd><p>为操作符指定左结合性的Bison声明.
- 参阅 <a href="#SEC63">操作符优先级-Operator Precedence</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%lex-param</b><i> {<var>argument-declaration</var>}</i>
- <a name="IDX134"></a>
- </dt>
- <dd><p>指明<code>yylex</code>的额外参数的Bison声明.
- 参阅 <a href="#SEC79">纯分析器的调用惯例-Calling Conventions for Pure Parsers</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%merge</b>
- <a name="IDX135"></a>
- </dt>
- <dd><p>赋予规则一个合并函数的Bison声明.
- 如果有一个归约/归约冲突的规则带有相同的合并函数,
- 那么这个函数被应用于两个语义值来获得单一的结果.
- 参阅 <a href="#SEC11">Writing <acronym>GLR</acronym> Parsers-编写<acronym>GLR</acronym>分析器</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%name-prefix="<var>prefix</var></b><i>"</i>
- <a name="IDX136"></a>
- </dt>
- <dd><p>重命名外部符号的Bison声明.参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%no-lines</b>
- <a name="IDX137"></a>
- </dt>
- <dd><p>在分析器文件中避免产生<code>#line</code>指令的Bison声明. 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%nonassoc</b>
- <a name="IDX138"></a>
- </dt>
- <dd><p>声明一个无结合性记号.
- 参阅 <a href="#SEC63">操作符优先级-Operator Precedence</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%output="<var>filename</var></b><i>"</i>
- <a name="IDX139"></a>
- </dt>
- <dd><p>设置分析器文件的Bison声明 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%parse-param</b><i> {<var>argument-declaration</var>}</i>
- <a name="IDX140"></a>
- </dt>
- <dd><p>指定<code>yyparse</code>接受的额外参数的Bison声明.
- 参阅 <a href="#SEC74">分析器函数<code>yyparse</code>- The Parser Function <code>yyparse</code></a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%prec</b>
- <a name="IDX141"></a>
- </dt>
- <dd><p>给特定的规则指定优先级的Bison声明.
- 参阅 <a href="#SEC90">上下文依赖优先级-Context-Dependent Precedence</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%pure-parser</b>
- <a name="IDX142"></a>
- </dt>
- <dd><p>请求一个纯(可重入)分析器的Bison声明.
- 参阅 <a href="#SEC70">一个纯(可重入)分析器-A Pure (Reentrant) Parser</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%right</b>
- <a name="IDX143"></a>
- </dt>
- <dd><p>指定记号右结合性的Bison声明.
- 参阅 <a href="#SEC63">操作符优先级-Operator Precedence</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%start</b>
- <a name="IDX144"></a>
- </dt>
- <dd><p>指定开始符号的Bison声明参阅 <a href="#SEC69">开始符号-The Start-Symbol</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%token</b>
- <a name="IDX145"></a>
- </dt>
- <dd><p>声明记号但不指定优先级.
- 参阅 <a href="#SEC62">记号类型名称-Token Type Names</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%token-table</b>
- <a name="IDX146"></a>
- </dt>
- <dd><p>在分析器文件中加入符号名称表的Bison声明.
- 参阅 <a href="#SEC71">声明总结-Decl Summary</a>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%type</b>
- <a name="IDX147"></a>
- </dt>
- <dd><p>声明非终结符的Bison声明.
- 参阅 <a href="#SEC65">非终结符-Nonterminal Symbols</a>.
- </p></dd></dl>
- <dl>
- <dt><u>符号:</u> <b>$undefined</b>
- <a name="IDX148"></a>
- </dt>
- <dd><p>所有<code>yylex</code>返回的未定义值被映射到这个预定义符号.
- 它不能在语法中使用,[untranslated]rather,use <code>error</code>.
- </p></dd></dl>
- <dl>
- <dt><u>指令:</u> <b>%union</b>
- <a name="IDX149"></a>
- </dt>
- <dd><p>指定多种可能语义值数据类型的Bison声明.
- 参阅 <a href="#SEC64">值类型集-The Collection of Value Types</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYABORT</b>
- <a name="IDX150"></a>
- </dt>
- <dd><p>通过使<code>yyparse</code>立即返回1,来伪装发生一个未恢复的语法错误的宏.
- 并不调用错误报告函数<code>yyerrpr</code>.
- 参阅 <a href="#SEC74">分析器函数<code>ppyarse</code>-The Parser Function <code>yyparse</code></a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYACCEPT</b>
- <a name="IDX151"></a>
- </dt>
- <dd><p>通过使<code>yyparse</code>立即返回0,来伪装语言的一个完整的表达已经被读取的宏.
- 参阅 <a href="#SEC74">分析器函数<code>ppyarse</code>-The Parser Function <code>yyparse</code></a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYBACKUP</b>
- <a name="IDX152"></a>
- </dt>
- <dd><p>从分析器栈中丢弃一个值并伪造一个超前扫描记号的宏.
- 参阅 <a href="#SEC81">在动作中使用的特殊特征-Special Features for Use in Actions</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>yychar</b>
- <a name="IDX153"></a>
- </dt>
- <dd><p>包含当前超前扫描记号的正数值的外部整数变量.
- (在一个纯分析器中,它是一个在<code>yyparse</code>中的局部变量).
- 错误恢复规则可能要检查这个变量.
- 参阅 <a href="#SEC81">在动作中使用的特殊特征-Special Features for Use in Actions</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>yyclearin</b>
- <a name="IDX154"></a>
- </dt>
- <dd><p>在错误恢复规则中使用的宏.它清除先前的超前扫描记号.
- 参阅 <a href="#SEC96">错误恢复-Error Recovery</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYDEBUG</b>
- <a name="IDX155"></a>
- </dt>
- <dd><p>使分析器带有追踪代码的宏.
- 参阅 <a href="#SEC103">跟踪你的分析器-Tracing Your Parser</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>yydebug</b>
- <a name="IDX156"></a>
- </dt>
- <dd><p>默认被置0的外部整数变量.
- 如果<code>yydebug</code>被赋予一个非零值,
- 分析器会输入关于输入符号和分析器动作的信息.
- 参阅 <a href="#SEC103">跟踪你的分析器-Tracing Your Parser</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>yyerrok</b>
- <a name="IDX157"></a>
- </dt>
- <dd><p>使分析器在一个语法错误之后立即恢复到正常模式的宏.
- 参阅 <a href="#SEC96">错误恢复-Error Recovery</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYERROR</b>
- <a name="IDX158"></a>
- </dt>
- <dd><p>一个假装刚刚发现一个语法错误的宏:
- 调用<code>yyerror</code>然后执行通常的错误恢复如果可能的话(参阅<a href="#SEC96">错误恢复-Error Recovery</a>一章)
- 或者(如果恢复是不可能的)使<code>yyparse</code>返回1.
- 参阅 <a href="#SEC96">错误恢复-Error Recovery</a>.
- </p></dd></dl>
- <dl>
- <dt><u>函数:</u> <b>yyerror</b>
- <a name="IDX159"></a>
- </dt>
- <dd><p>用户提供的当发现错误时被<code>yyparse</code>调用的函数.
- 参阅 <a href="#SEC80">错误报告函数<code>yyerror</code>-The Error Reporting Function <code>yyerror</code></a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYERROR_VERBOSE</b>
- <a name="IDX160"></a>
- </dt>
- <dd><p>一个在<var>Prologue</var>部分用<code>#define</code>定义的陈旧的宏,
- 当调用<code>yyerror</code>时,它请求详细的错误消息字符串.
- 你把<code>YYERROR_VERBOSE</code>定义成什么东西并没有影响,
- 有影响的只是你是否定义了它.
- 使用<code>%error-verbose</code>是更好的选择.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYINITDEPTH</b>
- <a name="IDX161"></a>
- </dt>
- <dd><p>指定分析器栈初始大小的宏.
- 参阅 <a href="#SEC95">栈溢出-Stack Overflow</a>.
- </p></dd></dl>
- <dl>
- <dt><u>函数:</u> <b>yylex</b>
- <a name="IDX162"></a>
- </dt>
- <dd><p>用户提供的词法分析器函数,
- 不带有任何参数来获得下一个记号.
- 参阅 <a href="#SEC75">词法分析器函数<code>yylex</code>-The Lexical Analyzer Function <code>yylex</code></a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYLEX_PARAM</b>
- <a name="IDX163"></a>
- </dt>
- <dd><p>一个用于指明<code>yyparse</code>传递到<code>yylex</code>的额外参数(或者额外参数列表)的陈旧的宏.
- 不赞成继续使用这个宏,它只被Yacc类似分析器支持.
- 参阅 <a href="#SEC79">纯分析器的调用惯例-Calling Conventions for Pure Parsers</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>yylloc</b>
- <a name="IDX164"></a>
- </dt>
- <dd><p><code>yylex</code>应该将一个记号的行列号放入这个外部变量.
- (在纯分析器中,它是一个<code>yyparse</code>的局部变量,
- 它的地址被传递到<code>yylex</code>).
- 如果你在语法动作中不使用<samp>`@'</samp>特性,你可以忽略这个变量.
- 参阅 <a href="#SEC78">记号的文字位置-Textual Locations of Tokens</a>.
- </p></dd></dl>
- <dl>
- <dt><u>Type:</u> <b>YYLTYPE</b>
- <a name="IDX165"></a>
- </dt>
- <dd><p><code>yyloc</code>的数据类型;默认地为一个带有四个成员的结构体.
- 参阅 <a href="#SEC58">位置的数据类型-Data Types of Locations</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>yylval</b>
- <a name="IDX166"></a>
- </dt>
- <dd><p><code>yylex</code>应该将记号相关的语义值放入这个变量.
- (在纯分析器中,它是一个<code>yyparse</code>中的局部变量,并且它的地址被传递到<code>yylex</code>.)
- 参阅 <a href="#SEC77">记号的语义值-Semantic Values of Tokens</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYMAXDEPTH</b>
- <a name="IDX167"></a>
- </dt>
- <dd><p>指明分析器栈最大容的宏.
- 参阅 <a href="#SEC95">栈溢出-Stack Overflow</a>.
- </p></dd></dl>
- <dl>
- <dt><u>变量:</u> <b>yynerrs</b>
- <a name="IDX168"></a>
- </dt>
- <dd><p>一个全局变量,每次出现语法错误时自增1.
- (在纯分析器中,它是一个<code>yyparse</code>中的局部变量.)
- 参阅 <a href="#SEC80">错误报告函数<code>yyerror</code>-The Error Reporting Function <code>yyerror</code></a>.
- </p></dd></dl>
- <dl>
- <dt><u>函数:</u> <b>yyparse</b>
- <a name="IDX169"></a>
- </dt>
- <dd><p>Bison产生的分析器函数;调用这个函数开始分析.
- 参阅 <a href="#SEC74">分析器函数<code>yyparse</code>-The Parser Function <code>yyparse</code></a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYPARSE_PARAM</b>
- <a name="IDX170"></a>
- </dt>
- <dd><p>指明<code>yyparse</code>应该接受的参数名成的陈旧宏.
- 不赞成继续使用这个宏,它只被Yacc类似分析器支持.
- 参阅 <a href="#SEC79">纯分析器的调用惯例-Calling Conventions for Pure Parsers</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYRECOVERING</b>
- <a name="IDX171"></a>
- </dt>
- <dd><p>一个宏,它的值指明了分析器是否正在从错误中恢复.
- 参阅 <a href="#SEC81">动作中使用的特殊特征-Special Features for Use in Actions</a>.
- </p></dd></dl>
- <dl>
- <dt><u>宏:</u> <b>YYSTACK_USE_ALLOCA</b>
- <a name="IDX172"></a>
- </dt>
- <dd><p>用于控制当C语言<acronym>LALR</acronym>(1)分析器需要扩展它的栈时,<code>alloca</code>的使用.
- 如果定义为0,分析器会使用<code>malloc</code>来扩展它的栈.
- 如果定义为1,分析器则会使用<code>alloca</code>.
- 除了0和1以外的值保留用于Bison以后的扩展.
- 如果没有被定义,
- <code>YYSTACK_USA_ALLOCA</code>默认为0.
- </p>
- <p>如果你定义<code>YYSTACK_USE_ALLOCA</code>为1,
- 你有责任使<code>alloca</code>是可见的,
- 例如,使用<acronym>GCC</acronym>,或者包含<code><stdlib.h></code>.
- 此外,在更普通的情况下,
- 如果你的代码可能运行在一个有限栈容量和不可信任栈溢出检查的主机上的时候,
- 你应将<code>YYMAXDEPTH</code>设为当调用<code>alloca</code>时,
- 在一个在任何目标主机不会产生栈溢出的值.
- 你可以检查Bison生成的代码来决定适当的数值.
- 这需要在底层详细实现的专业技术.
- </p>
- </dd></dl>
- <dl>
- <dt><u>类型:</u> <b>YYSTYPE</b>
- <a name="IDX173"></a>
- </dt>
- <dd><p>语义值的数据类型;默认为<code>int</code>.
- 参阅 <a href="#SEC52">语义值的数据类型-Data Types of Semantic Values</a>.
- </p></dd></dl>
- <hr size="6">
- <a name="Glossary"></a>
- <a name="SEC115"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC114"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC116"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC114"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC116"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="appendix"><a name="t116"></a> B. 词汇表-Glossary </h1>
- <dl compact="compact">
- <dt> Backus-Naur Form (<acronym>BNF</acronym>; also called "Backus Normal Form")</dt>
- <dt> Backus-Naur 范式 (<acronym>BNF</acronym>; 也被称为 "Backus正规范式")</dt>
- <dd><p>由John Backus倡导的,最初用于描述上下文无关文法的正式方法.
- 在Peter Naur他的称为Algol60报告的1960-01-02委员会文档中得到少许改进.
- 参阅 <a href="#SEC7">语言与上下文无关文法-Languages and Context-Free Grammars</a>.
- </p>
- </dd>
- <dt> Context-free grammars</dt>
- <dt> 上下文无关文法</dt>
- <dd><p>描述可以使用而不考虑上下文的规则的文法.
- 因此,如果有一个规则说一个整数可做为一个表达式使用,
- 那么,整数<em>在任何地方</em>都是一个允许的表达式.
- 参阅 <a href="#SEC7">语言与上下文无关文法-Languages and Context-Free Grammars</a>.
- </p>
- </dd>
- <dt> Dynamic allocation</dt>
- <dt> 动态分配</dt>
- <dd><p>在执行期间分配内存,而不是在编译期间或者进入一个函数时.
- </p>
- </dd>
- <dt> Empty string</dt>
- <dt> 空字符串</dt>
- <dd><p>模拟集合论中的空集,
- 空字符串是长度为0的字符串.
- </p>
- </dd>
- <dt> Finite-state stack machine</dt>
- <dt> 有限状态栈机</dt>
- <dd><p>一种含有多种离散状态的机器,每个时刻只有一种状态.
- 当处理输入的时候,机器按照机器逻辑的指定从一个状态转换到另一个状态.
- 对于分析器来说,输入就是要分析的语言,
- 状态对应于语法规则中的各个阶段.
- 参阅 <a href="#SEC82">Bison分析器算法-The Bison Parser Algorithm</a>.
- </p>
- </dd>
- <dt> Generalized <acronym>LR</acronym> (<acronym>GLR</acronym>)</dt>
- <dt> 通用<acronym>LR</acronym> (<acronym>GLR</acronym>)</dt>
- <dd><p>一种可以处理包括那些不是<acronym>LALR</acronym>(1)的上下文无关文法的分析算法.
- 它用来解决Bison通常的<acronym>LALR</acronym>(1)算法不能解决的冲突.
- 它高效地分裂成多个分析器,尝试所有可能的分析,丢弃那些在额外上下文提示下失败的分析器.
- 参阅 <a href="#SEC94">通用<acronym>LR</acronym>分析-Generalized <acronym>LR</acronym> Parsing</a>.
- </p>
- </dd>
- <dt> Grouping</dt>
- <dt> 分组</dt>
- <dd><p>一个(通常)在语法上可再分的语言结构;
- 例如C中的`expression'或者'declaration'.
- 参阅 <a href="#SEC7">语言和上下文无关文法-Languages and Context-Free Grammars</a>.
- </p>
- </dd>
- <dt> Infix operator</dt>
- <dt> 中缀操作符</dt>
- <dd><p>放置在操作数中间指定某些操作的算术操作符.
- </p>
- </dd>
- <dt> Input stream</dt>
- <dt> 输入流</dt>
- <dd><p>在设备或程序间的连续数据流.
- </p>
- </dd>
- <dt> Language construct</dt>
- <dt> 语言结构</dt>
- <dd><p>一种语言的典型应用模式.
- 例如,一种C语言的结构是<code>if</code>语句.
- 参阅 <a href="#SEC7">语言和上下文无关文法-Languages and Context-Free Grammars</a>.
- </p>
- </dd>
- <dt> Left associativity</dt>
- <dt> 左结合性</dt>
- <dd><p>拥有左结合性的操作符被从左至右地分析:
- <samp>`a+b+C'</samp>首先计算<samp>`a+b'</samp>然后和<samp>`c'</samp>一起计算.
- 参阅 <a href="#SEC85">操作符优先级-Operator Precedence</a>.
- </p>
- </dd>
- <dt> Left recursion</dt>
- <dt> 左递归</dt>
- <dd><p>一个结果符号同样是第一个部件符号的规则;
- 例如:
- <samp>`expseq1 : expseq1 ',' exp;'</samp>.
- 参阅 <a href="#SEC50">递归规则-Recursive Rules</a>.
- </p>
- </dd>
- <dt> Left-to-right parsing</dt>
- <dt> 自左至右分析</dt>
- <dd><p>同过自左至右分析一个个地分析记号来分析一个句子.
- 参阅 <a href="#SEC82">Bison 分析器算法-The Bison Parser Algorithm</a>.
- </p>
- </dd>
- <dt> Lexical analyzer (scanner)</dt>
- <dt> 词法分析器 (扫描器)</dt>
- <dd><p>一个读取输入流并逐个返回记号的函数.
- 参阅 <a href="#SEC75">词法分析器函数<code>yylex</code>-The Lexical Analyzer Function <code>yylex</code></a>.
- </p>
- </dd>
- <dt> Lexical tie-in</dt>
- <dt> 词法关联</dt>
- <dd><p>一个由语法规则动作设置的标志用来改变分析记号的方法.
- 参阅 <a href="#SEC99">词法关联-Lexical tie-in</a>.
- </p>
- </dd>
- <dt> Literal string token</dt>
- <dt> 字符串文字记号</dt>
- <dd><p>一个由两个或者更多字符组成的记号.参阅 <a href="#SEC48">符号-Symbols</a>.
- </p>
- </dd>
- <dt> Look-ahead token</dt>
- <dt> 超前扫描记号</dt>
- <dd><p>一个已经读取但未移进的记号.
- 参阅 <a href="#SEC83">超前扫描记号-Look-Ahead Tokens</a>.
- </p>
- </dd>
- <dt> <acronym>LALR</acronym>(1)</dt>
- <dd><p>一种Bison(像大多数其它分析器一样)可以处理的上下文无关文法.
- <acronym>LR</acronym>(1)的子集.
- 参阅 <a href="#SEC93">令人迷惑的归约/归约冲突-Mysterious Reduce/Reduce Conflicts</a>.
- </p>
- </dd>
- <dt> <acronym>LR</acronym>(1)</dt>
- <dd><p>一种上下文无关文法,
- 它在大多数时侯需要一个超前扫描记号来消除任何输入片段的歧义.
- </p>
- </dd>
- <dt> Nonterminal symbol</dt>
- <dt> 非终结符</dt>
- <dd><p>一个代表可以通过规则表达为更小结构的语法结构;
- 换句话说,一个不是记号的结构.
- 参阅 <a href="#SEC48">符号-Symbols</a>.
- </p>
- </dd>
- <dt> Parser</dt>
- <dt> 分析器</dt>
- <dd><p>一个靠分析从词法分析器传递过来的记号的语法结构来识别有效句子的函数.
- </p>
- </dd>
- <dt> Postfix operator</dt>
- <dt> 后缀操作符</dt>
- <dd><p>放置在操作数后执行某些操作的算术操作符.
- </p>
- </dd>
- <dt> Reduction</dt>
- <dt> 归约</dt>
- <dd><p>依照一个语法规则将非终结符和/或终结符的序列替换为非终结符.
- 参阅 <a href="#SEC82">Bison分析器算法-The Bison Parser Algorithm</a>.
- </p>
- </dd>
- <dt> Reentrant</dt>
- <dt> 可重入</dt>
- <dd><p>一个可重入的子程序是一个可以被任意次地并行调用并且调用间相互不干扰的子程序.
- 参阅 <a href="#SEC70">一个纯(可重入)分析器-A Pure (Reentrant) Parser</a>.
- </p>
- </dd>
- <dt> Reverse polish notation</dt>
- <dt> 逆波兰记号</dt>
- <dd><p>一种所有操作符都是后缀操作符的语言.
- </p>
- </dd>
- <dt> Right recursion</dt>
- <dt> 右递归</dt>
- <dd><p>一个结果记号也是它最后部件记号的规则;
- 例如 <samp>`expseq1: exp ',' expseq1;'</samp>.
- 参阅 <a href="#SEC50">递归规则-Recursive rules</a>.
- </p>
- </dd>
- <dt> Semantics-语义</dt>
- <dd><p>在计算机语言中,语义由每个语言实例的动作指明,
- 例如,每个语句的意义.
- 参阅 <a href="#SEC51">定义语言的语义-Defining Language Semantics</a>.
- </p>
- </dd>
- <dt> Shift-移进</dt>
- <dd><p>我们说一个分析器移进当它决定进从流中进一步分析输入而不是
- 立即归约一些已经识别的规则.
- 参阅 <a href="#SEC82">Bison分析器算法-The Bison Parser Algorithm</a>.
- </p>
- </dd>
- <dt> Single-character literal</dt>
- <dt> 单字符文字</dt>
- <dd><p>一个被识别和解释为它自己的单一字符.
- 参阅 <a href="#SEC8">从正规文法转换到Bison输入-From Formal Rules to Bison Input</a>.
- </p>
- </dd>
- <dt> Start symbol</dt>
- <dt> 开始符号</dt>
- <dd><p>代表要分析语言的一个完整有效的表述的非终结符.
- 在语言描述中,开始符号通常被列为第一个非终结符.
- 参阅 <a href="#SEC69">开始符号-The Start-Symbol</a>.
- </p>
- </dd>
- <dt> Symbol table</dt>
- <dt> 符号表</dt>
- <dd><p>用来识别和使用已经存在的符号信息的数据结构.
- 在进行分析器符号表存储符号名称和相关数据.
- 参阅 <a href="#SEC37">多功能计算器-Multi-function Calc</a>.
- </p>
- </dd>
- <dt> Syntax error</dt>
- <dt> 语法错误</dt>
- <dd><p>一个发生在分析无效语法的输入流时的错误.
- 参阅 <a href="#SEC96">错误恢复-Error Recovery</a>.
- </p>
- </dd>
- <dt> Token</dt>
- <dt> 记号</dt>
- <dd><p>一个基本的不可再分的语言单元.
- 在语法中,描述一个记号的符号是终结符.
- Bison分析器的输入是来自词法分析器的记号流.
- 参阅 <a href="#SEC48">Symbols-符号</a>.
- </p>
- </dd>
- <dt> Terminal symbol</dt>
- <dt> 终结符</dt>
- <dd><p>在语法中不包含含规则因此语法上不可再分的语法符号.
- 它表示的输入片段是一个记号.
- 参阅 <a href="#SEC7">语言与上下文无关文法-Languages and Context-Free Grammars</a>.
- </p></dd>
- </dl>
- <hr size="6">
- <a name="Copying-This-Manual"></a>
- <a name="SEC116"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC115"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC117"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC115"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC119"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="appendix"><a name="t117"></a> C. 复制这个手册-Copying This Manual </h1>
- <table class="menu" border="0" cellspacing="0">
- <tbody><tr><td align="left" valign="top"><a href="#SEC117">C.1 GNU Free Documentation License</a></td><td> </td><td align="left" valign="top"> 复制这个手册的许可.
- </td></tr>
- </tbody></table>
- <hr size="6">
- <a name="GNU-Free-Documentation-License"></a>
- <a name="SEC117"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC116"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC118"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC116"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC116"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC119"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h2 class="appendixsec"><a name="t118"></a> C.1 GNU Free Documentation License </h2>
- <p align="center"> Version 1.2, November 2002
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="display">Copyright © 2000,2001,2002 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
- </pre></td></tr></tbody></table>
- <ol>
- <li>
- PREAMBLE
- <p>The purpose of this License is to make a manual, textbook, or other
- functional and useful document <em>free</em> in the sense of freedom: to
- assure everyone the effective freedom to copy and redistribute it,
- with or without modifying it, either commercially or noncommercially.
- Secondarily, this License preserves for the author and publisher a way
- to get credit for their work, while not being considered responsible
- for modifications made by others.
- </p>
- <p>This License is a kind of "copyleft", which means that derivative
- works of the document must themselves be free in the same sense. It
- complements the GNU General Public License, which is a copyleft
- license designed for free software.
- </p>
- <p>We have designed this License in order to use it for manuals for free
- software, because free software needs free documentation: a free
- program should come with manuals providing the same freedoms that the
- software does. But this License is not limited to software manuals;
- it can be used for any textual work, regardless of subject matter or
- whether it is published as a printed book. We recommend this License
- principally for works whose purpose is instruction or reference.
- </p>
- </li><li>
- APPLICABILITY AND DEFINITIONS
- <p>This License applies to any manual or other work, in any medium, that
- contains a notice placed by the copyright holder saying it can be
- distributed under the terms of this License. Such a notice grants a
- world-wide, royalty-free license, unlimited in duration, to use that
- work under the conditions stated herein. The "Document", below,
- refers to any such manual or work. Any member of the public is a
- licensee, and is addressed as "you". You accept the license if you
- copy, modify or distribute the work in a way requiring permission
- under copyright law.
- </p>
- <p>A "Modified Version" of the Document means any work containing the
- Document or a portion of it, either copied verbatim, or with
- modifications and/or translated into another language.
- </p>
- <p>A "Secondary Section" is a named appendix or a front-matter section
- of the Document that deals exclusively with the relationship of the
- publishers or authors of the Document to the Document's overall
- subject (or to related matters) and contains nothing that could fall
- directly within that overall subject. (Thus, if the Document is in
- part a textbook of mathematics, a Secondary Section may not explain
- any mathematics.) The relationship could be a matter of historical
- connection with the subject or with related matters, or of legal,
- commercial, philosophical, ethical or political position regarding
- them.
- </p>
- <p>The "Invariant Sections" are certain Secondary Sections whose titles
- are designated, as being those of Invariant Sections, in the notice
- that says that the Document is released under this License. If a
- section does not fit the above definition of Secondary then it is not
- allowed to be designated as Invariant. The Document may contain zero
- Invariant Sections. If the Document does not identify any Invariant
- Sections then there are none.
- </p>
- <p>The "Cover Texts" are certain short passages of text that are listed,
- as Front-Cover Texts or Back-Cover Texts, in the notice that says that
- the Document is released under this License. A Front-Cover Text may
- be at most 5 words, and a Back-Cover Text may be at most 25 words.
- </p>
- <p>A "Transparent" copy of the Document means a machine-readable copy,
- represented in a format whose specification is available to the
- general public, that is suitable for revising the document
- straightforwardly with generic text editors or (for images composed of
- pixels) generic paint programs or (for drawings) some widely available
- drawing editor, and that is suitable for input to text formatters or
- for automatic translation to a variety of formats suitable for input
- to text formatters. A copy made in an otherwise Transparent file
- format whose markup, or absence of markup, has been arranged to thwart
- or discourage subsequent modification by readers is not Transparent.
- An image format is not Transparent if used for any substantial amount
- of text. A copy that is not "Transparent" is called "Opaque".
- </p>
- <p>Examples of suitable formats for Transparent copies include plain
- <small>ASCII</small> without markup, Texinfo input format, LaTeX input
- format, <acronym>SGML</acronym> or <acronym>XML</acronym> using a publicly available
- <acronym>DTD</acronym>, and standard-conforming simple <acronym>HTML</acronym>,
- PostScript or <acronym>PDF</acronym> designed for human modification. Examples
- of transparent image formats include <acronym>PNG</acronym>, <acronym>XCF</acronym> and
- <acronym>JPG</acronym>. Opaque formats include proprietary formats that can be
- read and edited only by proprietary word processors, <acronym>SGML</acronym> or
- <acronym>XML</acronym> for which the <acronym>DTD</acronym> and/or processing tools are
- not generally available, and the machine-generated <acronym>HTML</acronym>,
- PostScript or <acronym>PDF</acronym> produced by some word processors for
- output purposes only.
- </p>
- <p>The "Title Page" means, for a printed book, the title page itself,
- plus such following pages as are needed to hold, legibly, the material
- this License requires to appear in the title page. For works in
- formats which do not have any title page as such, "Title Page" means
- the text near the most prominent appearance of the work's title,
- preceding the beginning of the body of the text.
- </p>
- <p>A section "Entitled XYZ" means a named subunit of the Document whose
- title either is precisely XYZ or contains XYZ in parentheses following
- text that translates XYZ in another language. (Here XYZ stands for a
- specific section name mentioned below, such as "Acknowledgements",
- "Dedications", "Endorsements", or "History".) To "Preserve the Title"
- of such a section when you modify the Document means that it remains a
- section "Entitled XYZ" according to this definition.
- </p>
- <p>The Document may include Warranty Disclaimers next to the notice which
- states that this License applies to the Document. These Warranty
- Disclaimers are considered to be included by reference in this
- License, but only as regards disclaiming warranties: any other
- implication that these Warranty Disclaimers may have is void and has
- no effect on the meaning of this License.
- </p>
- </li><li>
- VERBATIM COPYING
- <p>You may copy and distribute the Document in any medium, either
- commercially or noncommercially, provided that this License, the
- copyright notices, and the license notice saying this License applies
- to the Document are reproduced in all copies, and that you add no other
- conditions whatsoever to those of this License. You may not use
- technical measures to obstruct or control the reading or further
- copying of the copies you make or distribute. However, you may accept
- compensation in exchange for copies. If you distribute a large enough
- number of copies you must also follow the conditions in section 3.
- </p>
- <p>You may also lend copies, under the same conditions stated above, and
- you may publicly display copies.
- </p>
- </li><li>
- COPYING IN QUANTITY
- <p>If you publish printed copies (or copies in media that commonly have
- printed covers) of the Document, numbering more than 100, and the
- Document's license notice requires Cover Texts, you must enclose the
- copies in covers that carry, clearly and legibly, all these Cover
- Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
- the back cover. Both covers must also clearly and legibly identify
- you as the publisher of these copies. The front cover must present
- the full title with all words of the title equally prominent and
- visible. You may add other material on the covers in addition.
- Copying with changes limited to the covers, as long as they preserve
- the title of the Document and satisfy these conditions, can be treated
- as verbatim copying in other respects.
- </p>
- <p>If the required texts for either cover are too voluminous to fit
- legibly, you should put the first ones listed (as many as fit
- reasonably) on the actual cover, and continue the rest onto adjacent
- pages.
- </p>
- <p>If you publish or distribute Opaque copies of the Document numbering
- more than 100, you must either include a machine-readable Transparent
- copy along with each Opaque copy, or state in or with each Opaque copy
- a computer-network location from which the general network-using
- public has access to download using public-standard network protocols
- a complete Transparent copy of the Document, free of added material.
- If you use the latter option, you must take reasonably prudent steps,
- when you begin distribution of Opaque copies in quantity, to ensure
- that this Transparent copy will remain thus accessible at the stated
- location until at least one year after the last time you distribute an
- Opaque copy (directly or through your agents or retailers) of that
- edition to the public.
- </p>
- <p>It is requested, but not required, that you contact the authors of the
- Document well before redistributing any large number of copies, to give
- them a chance to provide you with an updated version of the Document.
- </p>
- </li><li>
- MODIFICATIONS
- <p>You may copy and distribute a Modified Version of the Document under
- the conditions of sections 2 and 3 above, provided that you release
- the Modified Version under precisely this License, with the Modified
- Version filling the role of the Document, thus licensing distribution
- and modification of the Modified Version to whoever possesses a copy
- of it. In addition, you must do these things in the Modified Version:
- </p>
- <ol>
- <li>
- Use in the Title Page (and on the covers, if any) a title distinct
- from that of the Document, and from those of previous versions
- (which should, if there were any, be listed in the History section
- of the Document). You may use the same title as a previous version
- if the original publisher of that version gives permission.
- </li><li>
- List on the Title Page, as authors, one or more persons or entities
- responsible for authorship of the modifications in the Modified
- Version, together with at least five of the principal authors of the
- Document (all of its principal authors, if it has fewer than five),
- unless they release you from this requirement.
- </li><li>
- State on the Title page the name of the publisher of the
- Modified Version, as the publisher.
- </li><li>
- Preserve all the copyright notices of the Document.
- </li><li>
- Add an appropriate copyright notice for your modifications
- adjacent to the other copyright notices.
- </li><li>
- Include, immediately after the copyright notices, a license notice
- giving the public permission to use the Modified Version under the
- terms of this License, in the form shown in the Addendum below.
- </li><li>
- Preserve in that license notice the full lists of Invariant Sections
- and required Cover Texts given in the Document's license notice.
- </li><li>
- Include an unaltered copy of this License.
- </li><li>
- Preserve the section Entitled "History", Preserve its Title, and add
- to it an item stating at least the title, year, new authors, and
- publisher of the Modified Version as given on the Title Page. If
- there is no section Entitled "History" in the Document, create one
- stating the title, year, authors, and publisher of the Document as
- given on its Title Page, then add an item describing the Modified
- Version as stated in the previous sentence.
- </li><li>
- Preserve the network location, if any, given in the Document for
- public access to a Transparent copy of the Document, and likewise
- the network locations given in the Document for previous versions
- it was based on. These may be placed in the "History" section.
- You may omit a network location for a work that was published at
- least four years before the Document itself, or if the original
- publisher of the version it refers to gives permission.
- </li><li>
- For any section Entitled "Acknowledgements" or "Dedications", Preserve
- the Title of the section, and preserve in the section all the
- substance and tone of each of the contributor acknowledgements and/or
- dedications given therein.
- </li><li>
- Preserve all the Invariant Sections of the Document,
- unaltered in their text and in their titles. Section numbers
- or the equivalent are not considered part of the section titles.
- </li><li>
- Delete any section Entitled "Endorsements". Such a section
- may not be included in the Modified Version.
- </li><li>
- Do not retitle any existing section to be Entitled "Endorsements" or
- to conflict in title with any Invariant Section.
- </li><li>
- Preserve any Warranty Disclaimers.
- </li></ol>
- <p>If the Modified Version includes new front-matter sections or
- appendices that qualify as Secondary Sections and contain no material
- copied from the Document, you may at your option designate some or all
- of these sections as invariant. To do this, add their titles to the
- list of Invariant Sections in the Modified Version's license notice.
- These titles must be distinct from any other section titles.
- </p>
- <p>You may add a section Entitled "Endorsements", provided it contains
- nothing but endorsements of your Modified Version by various
- parties--for example, statements of peer review or that the text has
- been approved by an organization as the authoritative definition of a
- standard.
- </p>
- <p>You may add a passage of up to five words as a Front-Cover Text, and a
- passage of up to 25 words as a Back-Cover Text, to the end of the list
- of Cover Texts in the Modified Version. Only one passage of
- Front-Cover Text and one of Back-Cover Text may be added by (or
- through arrangements made by) any one entity. If the Document already
- includes a cover text for the same cover, previously added by you or
- by arrangement made by the same entity you are acting on behalf of,
- you may not add another; but you may replace the old one, on explicit
- permission from the previous publisher that added the old one.
- </p>
- <p>The author(s) and publisher(s) of the Document do not by this License
- give permission to use their names for publicity for or to assert or
- imply endorsement of any Modified Version.
- </p>
- </li><li>
- COMBINING DOCUMENTS
- <p>You may combine the Document with other documents released under this
- License, under the terms defined in section 4 above for modified
- versions, provided that you include in the combination all of the
- Invariant Sections of all of the original documents, unmodified, and
- list them all as Invariant Sections of your combined work in its
- license notice, and that you preserve all their Warranty Disclaimers.
- </p>
- <p>The combined work need only contain one copy of this License, and
- multiple identical Invariant Sections may be replaced with a single
- copy. If there are multiple Invariant Sections with the same name but
- different contents, make the title of each such section unique by
- adding at the end of it, in parentheses, the name of the original
- author or publisher of that section if known, or else a unique number.
- Make the same adjustment to the section titles in the list of
- Invariant Sections in the license notice of the combined work.
- </p>
- <p>In the combination, you must combine any sections Entitled "History"
- in the various original documents, forming one section Entitled
- "History"; likewise combine any sections Entitled "Acknowledgements",
- and any sections Entitled "Dedications". You must delete all
- sections Entitled "Endorsements."
- </p>
- </li><li>
- COLLECTIONS OF DOCUMENTS
- <p>You may make a collection consisting of the Document and other documents
- released under this License, and replace the individual copies of this
- License in the various documents with a single copy that is included in
- the collection, provided that you follow the rules of this License for
- verbatim copying of each of the documents in all other respects.
- </p>
- <p>You may extract a single document from such a collection, and distribute
- it individually under this License, provided you insert a copy of this
- License into the extracted document, and follow this License in all
- other respects regarding verbatim copying of that document.
- </p>
- </li><li>
- AGGREGATION WITH INDEPENDENT WORKS
- <p>A compilation of the Document or its derivatives with other separate
- and independent documents or works, in or on a volume of a storage or
- distribution medium, is called an "aggregate" if the copyright
- resulting from the compilation is not used to limit the legal rights
- of the compilation's users beyond what the individual works permit.
- When the Document is included in an aggregate, this License does not
- apply to the other works in the aggregate which are not themselves
- derivative works of the Document.
- </p>
- <p>If the Cover Text requirement of section 3 is applicable to these
- copies of the Document, then if the Document is less than one half of
- the entire aggregate, the Document's Cover Texts may be placed on
- covers that bracket the Document within the aggregate, or the
- electronic equivalent of covers if the Document is in electronic form.
- Otherwise they must appear on printed covers that bracket the whole
- aggregate.
- </p>
- </li><li>
- TRANSLATION
- <p>Translation is considered a kind of modification, so you may
- distribute translations of the Document under the terms of section 4.
- Replacing Invariant Sections with translations requires special
- permission from their copyright holders, but you may include
- translations of some or all Invariant Sections in addition to the
- original versions of these Invariant Sections. You may include a
- translation of this License, and all the license notices in the
- Document, and any Warranty Disclaimers, provided that you also include
- the original English version of this License and the original versions
- of those notices and disclaimers. In case of a disagreement between
- the translation and the original version of this License or a notice
- or disclaimer, the original version will prevail.
- </p>
- <p>If a section in the Document is Entitled "Acknowledgements",
- "Dedications", or "History", the requirement (section 4) to Preserve
- its Title (section 1) will typically require changing the actual
- title.
- </p>
- </li><li>
- TERMINATION
- <p>You may not copy, modify, sublicense, or distribute the Document except
- as expressly provided for under this License. Any other attempt to
- copy, modify, sublicense or distribute the Document is void, and will
- automatically terminate your rights under this License. However,
- parties who have received copies, or rights, from you under this
- License will not have their licenses terminated so long as such
- parties remain in full compliance.
- </p>
- </li><li>
- FUTURE REVISIONS OF THIS LICENSE
- <p>The Free Software Foundation may publish new, revised versions
- of the GNU Free Documentation License from time to time. Such new
- versions will be similar in spirit to the present version, but may
- differ in detail to address new problems or concerns. See
- <a href="http://www.gnu.org/copyleft/">http://www.gnu.org/copyleft/</a>.
- </p>
- <p>Each version of the License is given a distinguishing version number.
- If the Document specifies that a particular numbered version of this
- License "or any later version" applies to it, you have the option of
- following the terms and conditions either of that specified version or
- of any later version that has been published (not as a draft) by the
- Free Software Foundation. If the Document does not specify a version
- number of this License, you may choose any version ever published (not
- as a draft) by the Free Software Foundation.
- </p></li></ol>
- <hr size="6">
- <a name="SEC118"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC117"> < </a>]</td>
- <td align="left" valign="middle">[<a title="阅读顺序的下一章" href="#SEC119"> > </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC116"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC117"> 上层 </a>]</td>
- <td align="left" valign="middle">[<a title="下一章" href="#SEC119"> >> </a>]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h3 class="appendixsubsec"><a name="t119"></a> C.1.1 ADDENDUM: How to use this License for your documents </h3>
- <p>To use this License in a document you have written, include a copy of
- the License in the document and put the following copyright and
- license notices just after the title page:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample"> Copyright (C) <var>year</var> <var>your name</var>.
- Permission is granted to copy, distribute and/or modify this document
- under the terms of the GNU Free Documentation License, Version 1.2
- or any later version published by the Free Software Foundation;
- with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
- A copy of the license is included in the section entitled ``GNU
- Free Documentation License''.
- </pre></td></tr></tbody></table>
- <p>If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
- replace the "with...Texts." line with this:
- </p>
- <table><tbody><tr><td> </td><td><pre name="code" class="smallexample"> with the Invariant Sections being <var>list their titles</var>, with
- the Front-Cover Texts being <var>list</var>, and with the Back-Cover Texts
- being <var>list</var>.
- </pre></td></tr></tbody></table>
- <p>If you have Invariant Sections without Cover Texts, or some other
- combination of the three, merge those two alternatives to suit the
- situation.
- </p>
- <p>If your document contains nontrivial examples of program code, we
- recommend releasing these examples in parallel under your choice of
- free software license, such as the GNU General Public License,
- to permit their use in free software.
- </p>
- <hr size="6">
- <a name="Index"></a>
- <a name="SEC119"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="阅读顺序的上一章" href="#SEC118"> < </a>]</td>
- <td align="left" valign="middle">[ > ]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="章节的开始或上一章" href="#SEC116"> << </a>]</td>
- <td align="left" valign="middle">[<a title="上层章节" href="#SEC_Top"> 上层 </a>]</td>
- <td align="left" valign="middle">[ >> ]</td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle"> </td>
- <td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1 class="unnumbered"><a name="t120"></a> 索引-Index </h1>
- <table><tbody><tr><th valign="top">跳转到: </th><td><a class="summary-letter" href="#SEC119_0"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_1"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_2"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_3"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_4"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_5"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_6"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_7"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_8"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_9"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_10"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_11"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_12"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_13"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_14"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_15"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_16"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_17"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_18"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_19"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_20"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_21"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_22"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_23"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_24"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_25"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_26"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_27"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_28"><b>�</b></a>
-
- <br>
- <a class="summary-letter" href="#SEC119_29"><b>A</b></a>
-
- <a class="summary-letter" href="#SEC119_30"><b>B</b></a>
-
- <a class="summary-letter" href="#SEC119_31"><b>C</b></a>
-
- <a class="summary-letter" href="#SEC119_32"><b>E</b></a>
-
- <a class="summary-letter" href="#SEC119_33"><b>F</b></a>
-
- <a class="summary-letter" href="#SEC119_34"><b>G</b></a>
-
- <a class="summary-letter" href="#SEC119_35"><b>I</b></a>
-
- <a class="summary-letter" href="#SEC119_36"><b>L</b></a>
-
- <a class="summary-letter" href="#SEC119_37"><b>M</b></a>
-
- <a class="summary-letter" href="#SEC119_38"><b>P</b></a>
-
- <a class="summary-letter" href="#SEC119_39"><b>R</b></a>
-
- </td></tr></tbody></table>
- </tr>
- <tr><td></tr><td><table class="index-cp" border="0">
- <tbody><tr><td></td><th align="left">索引项</th><th align="left"> 部分</th></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_0">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX29">被丢弃的符号(discarded symbols)</a></td><td valign="top"><a href="#SEC67">3.7.6 释放被丢弃的符号-Freeing Discarded Symbols</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC26">编写一个词法分析器(writing a lexical analyzer)</a></td><td valign="top"><a href="#SEC26">2.1.3 <code>rpcalc</code>的词法分析器-The <code>rpcalc</code> Lexical Analyzer</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC30">编译分析器(compiling the parser)</a></td><td valign="top"><a href="#SEC30">2.1.7 编译分析器文件-Compiling the Parser File</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_1">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC20">波兰记号计算器(polish notation calculator)</a></td><td valign="top"><a href="#SEC20">2.1 逆波兰记号计算器-Reverse Polish Notation Calculator</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC94">不确定性分析(non-deterministic parsing)</a></td><td valign="top"><a href="#SEC94">5.8 通用<acronym>LR</acronym> (<acronym>GLR</acronym>)分析-Generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) Parsing</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC85">操作符的优先级(precedence of operators)</a></td><td valign="top"><a href="#SEC85">5.3 操作符优先级-Operator Precedence</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC85">操作符优先级(operator precedence)</a></td><td valign="top"><a href="#SEC85">5.3 操作符优先级-Operator Precedence</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC63">操作符优先级(operator precedence), 声明(declaring)</a></td><td valign="top"><a href="#SEC63">3.7.2 操作符优先级-Operator Precedence</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_2">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC108">常见问题(frequently asked questions)</a></td><td valign="top"><a href="#SEC108%22%3E10.+%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98-Frequently+Asked+Questions%3C/a%3E%3C/td%3E%3C/tr%3E%0A%3Ctr%3E%3Ctd%3E%3C/td%3E%3Ctd%20valign=" top"=""></a><a href="#SEC83">超前扫描记号(look-ahead token)</a></td><td valign="top"><a href="#SEC83">5.1 超前扫描记号-Look-Ahead Tokens</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC11">冲突(conflicts)</a></td><td valign="top"><a href="#SEC11">1.5 编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC12">冲突(conflicts)</a></td><td valign="top"><a href="#SEC12">1.5.1 使用<acronym>GLR</acronym>分析器分析非歧义文法</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC84">冲突(conflicts)</a></td><td valign="top"><a href="#SEC84">5.2 移进/归约冲突-Shift/Reduce Conflicts</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC92">冲突(conflicts), 归约/归约(reduce/reduce)</a></td><td valign="top"><a href="#SEC92">5.6 归约/归约冲突-Reduce/Reduce Conflicts</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC68">冲突(conflicts), 消除警告(suppressing warnings of)</a></td><td valign="top"><a href="#SEC68">3.7.7 消除冲突警告-Suppressing Conflict Warnings</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX110">抽象语法树(abstract syntax tree)</a></td><td valign="top"><a href="#SEC113">10.5 实现跳转/循环-Implementing Gotos/Loops</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_3">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC70">纯分析器(pure parser)</a></td><td valign="top"><a href="#SEC70">3.7.9 纯(可重入)分析器-A Pure (Reentrant) Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC75">词法分析器(lexical analyzer)</a></td><td valign="top"><a href="#SEC75">4.2 词法分析器函数<code>yylex</code>-The Lexical Analyzer Function <code>yylex</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC26">词法分析器(lexical analyzer), 编写(writing)</a></td><td valign="top"><a href="#SEC26">2.1.3 <code>rpcalc</code>的词法分析器-The <code>rpcalc</code> Lexical Analyzer</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC16">词法分析器(lexical analyzer), 目的(purpose)</a></td><td valign="top"><a href="#SEC16">1.7 Bison的输出:分析器文件-Bison Output: the Parser File</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC99">词法关联(lexical tie-in)</a></td><td valign="top"><a href="#SEC99">7.2 词法关联-Lexical Tie-ins</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC115">词汇表(glossary)</a></td><td valign="top"><a href="#SEC115">B. 词汇表-Glossary</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC96">从错误中恢复(recovery from errors)</a></td><td valign="top"><a href="#SEC96">6. 错误恢复-Error Recovery</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC73">从语言接口(C-language interface)</a></td><td valign="top"><a href="#SEC73">4. 分析器C语言接口-Parser C-Language Interface</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC28">错误报告的规则(error reporting routine)</a></td><td valign="top"><a href="#SEC28">2.1.5 错误报告的规则-The Error Reporting Routine</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC80">错误报告函数(error reporting function)</a></td><td valign="top"><a href="#SEC80">4.3 错误报告函数<code>yyerror</code>-The Error Reporting Function <code>yyerror</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC96">错误恢复(error recovery)</a></td><td valign="top"><a href="#SEC96">6. 错误恢复-Error Recovery</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC32">错误恢复(error recovery), 简单(simple)</a></td><td valign="top"><a href="#SEC32">2.3 简单的错误恢复-Simple Error Recovery</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_4">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX16">单字符文字(single-character literal)</a></td><td valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC50">递归规则(recursive rule)</a></td><td valign="top"><a href="#SEC50">3.4 递归规则-Recursive Rules</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC103">调试(debugging)</a></td><td valign="top"><a href="#SEC103">8.2 跟踪你的分析器-Tracing Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC104">调用Bison(invoking Bison)</a></td><td valign="top"><a href="#SEC104">9. 调用Bison-Invoking Bison</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_5">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC51">定义语言的语义(defining language semantics)</a></td><td valign="top"><a href="#SEC51">3.5 定义语言的语义-Defining Language Semantics</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC54">动作(action)</a></td><td valign="top"><a href="#SEC54">3.5.3 动作-Actions</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC59">动作(actions), 位置(location)</a></td><td valign="top"><a href="#SEC59">3.6.2 动作和位置-Actions and Locations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC10">动作(actions), 语义(semantic)</a></td><td valign="top"><a href="#SEC10">1.4 语义动作</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC55">动作数据类型(action data types)</a></td><td valign="top"><a href="#SEC55">3.5.4 动作中值的数据类型-Data Types of Values in Actions</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC81">动作特征总结(action features summary)</a></td><td valign="top"><a href="#SEC81">4.4 在动作中使用的特殊特征-Special Features for Use in Actions</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC55">动作中的数据类型(data types in actions)</a></td><td valign="top"><a href="#SEC55">3.5.4 动作中值的数据类型-Data Types of Values in Actions</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC37">多功能计算器(multi-function calculator)</a></td><td valign="top"><a href="#SEC37">2.5 多功能计算器:<code>mfcalc</code>-Multi-Function Calculator: <code>mfcalc</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX19">多字符文字(multicharacter literal)</a></td><td valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC47">额外C代码部分(additional C code section)</a></td><td valign="top"><a href="#SEC47">3.1.4 <var>Epilogue</var>部分-The epilogue</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_6">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX8">非确定性分析(non-deterministic parsing)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC48">非终结符(nonterminal symbol)</a></td><td valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX96">非终结符(nonterminal), 没用处(useless)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC80">分析错误(parse error)</a></td><td valign="top"><a href="#SEC80">4.3 错误报告函数<code>yyerror</code>-The Error Reporting Function <code>yyerror</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC16">分析器(parser)</a></td><td valign="top"><a href="#SEC16">1.7 Bison的输出:分析器文件-Bison Output: the Parser File</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC82">分析器的算法(algorithm of parser)</a></td><td valign="top"><a href="#SEC82">5. Bison分析器算法-The Bison Parser Algorithm</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC82">分析器栈(parser stack)</a></td><td valign="top"><a href="#SEC82">5. Bison分析器算法-The Bison Parser Algorithm</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC95">分析器栈的溢出(overflow of parser stack)</a></td><td valign="top"><a href="#SEC95">5.9 栈溢出以及如何避免它-Stack Overflow, and How to Avoid It</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC95">分析器栈溢出(parser stack overflow)</a></td><td valign="top"><a href="#SEC95">5.9 栈溢出以及如何避免它-Stack Overflow, and How to Avoid It</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC91">分析器状态(parser state)</a></td><td valign="top"><a href="#SEC91">5.5 分析器状态-Parser States</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC48">符号(symbol)</a></td><td valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX9">符号(symbols (abstract))</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC40">符号表实例(symbol table example)</a></td><td valign="top"><a href="#SEC40">2.5.3 <code>mfcalc</code>的符号表-The <code>mfcalc</code> Symbol Table</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC48">符号类型(token type)</a></td><td valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC62">符号类型名称(token type names), 声明(declaring)</a></td><td valign="top"><a href="#SEC62">3.7.1 符号类型名称-Token Type Names</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_7">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX98">规则(rule), 没用处(useless)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX102">规则(rule), 指明的(pointed)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC49">规则语法(rule syntax)</a></td><td valign="top"><a href="#SEC49">3.3 描述语法规则的语法-Syntax of Grammar Rules</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC56">规则中动作(mid-rule actions)</a></td><td valign="top"><a href="#SEC56">3.5.5 规则中的动作-Actions in Mid-Rule</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC82">归约(reduction)</a></td><td valign="top"><a href="#SEC82">5. Bison分析器算法-The Bison Parser Algorithm</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC11">归约/归约 冲突(reduce/reduce conflicts)</a></td><td valign="top"><a href="#SEC11">1.5 编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC92">归约/归约冲突(reduce/reduce conflict)</a></td><td valign="top"><a href="#SEC92">5.6 归约/归约冲突-Reduce/Reduce Conflicts</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC12">归约/归约冲突(reduce/reduce conflicts)</a></td><td valign="top"><a href="#SEC12">1.5.1 使用<acronym>GLR</acronym>分析器分析非歧义文法</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_8">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX103">核心(core), 项目集(item set)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX105">核心(kernel), 项目集(item set)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_9">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC37">计算器(calculator), 多功能(multi-function)</a></td><td valign="top"><a href="#SEC37">2.5 多功能计算器:<code>mfcalc</code>-Multi-Function Calculator: <code>mfcalc</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC20">计算器(calculator), 简单(simple)</a></td><td valign="top"><a href="#SEC20">2.1 逆波兰记号计算器-Reverse Polish Notation Calculator</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC33">计算器(calculator), 位置追踪(location tracking)</a></td><td valign="top"><a href="#SEC33">2.4 带有位置追踪的计算器:<code>ltcalc</code>-Location Tracking Calculator: <code>ltcalc</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC31">计算器(calculator), 中缀符号(infix notation)</a></td><td valign="top"><a href="#SEC31">2.2 中缀符号计算器:<code>calc</code>-Infix Notation Calculator: <code>calc</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX10">记号(token)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX94">记号(token), 没用处(useless)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC27">简单例子的main函数(main function in simple example)</a></td><td valign="top"><a href="#SEC27">2.1.4 控制函数-The Controlling Function</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC19">简单实例(simple examples)</a></td><td valign="top"><a href="#SEC19">2. 实例-Examples</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC1">简介(introduction)</a></td><td valign="top"><a href="#SEC1">Bison简介-Introduction</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_10">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC73">接口(interface)</a></td><td valign="top"><a href="#SEC73">4. 分析器C语言接口-Parser C-Language Interface</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX84">结合性(associativity)</a></td><td valign="top"><a href="#SEC86">5.3.1 什么时候需要优先级-When Precedence is Needed</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_11">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC68">警告(warnings), 阻止(preventing)</a></td><td valign="top"><a href="#SEC68">3.7.7 消除冲突警告-Suppressing Conflict Warnings</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_12">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX13">开始符号(start symbol)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC69">开始符号(start symbol), (声明)declaring</a></td><td valign="top"><a href="#SEC69">3.7.8 开始符号-The Start-Symbol</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC70">可重入分析器(reentrant parser)</a></td><td valign="top"><a href="#SEC70">3.7.9 纯(可重入)分析器-A Pure (Reentrant) Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC27">控制函数(controlling function)</a></td><td valign="top"><a href="#SEC27">2.1.4 控制函数-The Controlling Function</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_13">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC41">练习(exercises)</a></td><td valign="top"><a href="#SEC41">2.6 练习-Exercises</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_14">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX97">没用处的非终结符(useless nonterminal)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX99">没用处的规则(useless rule)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX95">没用处的记号(useless token)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_15">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX24">默认动作(default action)</a></td><td valign="top"><a href="#SEC54">3.5.3 动作-Actions</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC69">默认开始符号(default start symbol)</a></td><td valign="top"><a href="#SEC69">3.7.8 开始符号-The Start-Symbol</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC52">默认数据类型(default data type)</a></td><td valign="top"><a href="#SEC52">3.5.1 语义值的数据类型-Data Types of Semantic Values</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC58">默认位置类型(default location type)</a></td><td valign="top"><a href="#SEC58">3.6.1 位置的数据类型-Data Type of Locations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX88">默认栈容量限制(default stack limit)</a></td><td valign="top"><a href="#SEC95">5.9 栈溢出以及如何避免它-Stack Overflow, and How to Avoid It</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC20">逆波兰记号(reverse polish notation)</a></td><td valign="top"><a href="#SEC20">2.1 逆波兰记号计算器-Reverse Polish Notation Calculator</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_16">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX7">歧义文法(ambiguous grammars)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC94">歧义文法(ambiguous grammars)</a></td><td valign="top"><a href="#SEC94">5.8 通用<acronym>LR</acronym> (<acronym>GLR</acronym>)分析-Generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) Parsing</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_17">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC7">上下文无关文法(context-free grammar)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC90">上下文依赖优先级(context-dependent precedence)</a></td><td valign="top"><a href="#SEC90">5.4 上下文依赖优先级-Context-Dependent Precedence</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC44">声明(declarations)</a></td><td valign="top"><a href="#SEC44">3.1.1 <var>Prologue</var>部分-The prologue</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC61">声明(declarations), Bison</a></td><td valign="top"><a href="#SEC61">3.7 Bison声明-Bison Declarations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC45">声明(declarations), Bison(简介)(Bison (introduction))</a></td><td valign="top"><a href="#SEC45">3.1.2 <var>Bison Declarations</var>部分-The Bison Declarations Section</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC44">声明部分(declarations section)</a></td><td valign="top"><a href="#SEC44">3.1.1 <var>Prologue</var>部分-The prologue</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC63">声明操作符优先级(declaring operator precedence)</a></td><td valign="top"><a href="#SEC63">3.7.2 操作符优先级-Operator Precedence</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC62">声明符号类型名称(declaring token type names)</a></td><td valign="top"><a href="#SEC62">3.7.1 符号类型名称-Token Type Names</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC69">声明开始符号(declaring the start symbol)</a></td><td valign="top"><a href="#SEC69">3.7.8 开始符号-The Start-Symbol</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC62">声明文字串记号(declaring literal string tokens)</a></td><td valign="top"><a href="#SEC62">3.7.1 符号类型名称-Token Type Names</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC64">声明值类型(declaring value types)</a></td><td valign="top"><a href="#SEC64">3.7.3 值类型集-The Collection of Value Types</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC65">声明值类型(declaring value types), 非终结符(nonterminals)</a></td><td valign="top"><a href="#SEC65">3.7.4 非终结符-Nonterminal Symbols</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC71">声明总结(declaration summary)</a></td><td valign="top"><a href="#SEC71">3.7.10 Bison声明总结-Bison Declaration Summary</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_18">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC19">实例(examples), 简单(simple)</a></td><td valign="top"><a href="#SEC19">2. 实例-Examples</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC17">使用Bison(using Bison)</a></td><td valign="top"><a href="#SEC17">1.8 使用Bison的流程-Stages in Using Bison</a></td><td valign="top"><a href="#SEC17">使用Bison的流程(stages in using Bison)</a></td><td valign="top"><a href="#SEC17">1.8 使用Bison的流程-Stages in Using Bison</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC67">释放被丢弃的符号(freeing discarded symbols)</a></td><td valign="top"><a href="#SEC67">3.7.6 释放被丢弃的符号-Freeing Discarded Symbols</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_19">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC94">通用<acronym>LR</acronym> (<acronym>GLR</acronym>)分析(generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) parsing)</a></td><td valign="top"><a href="#SEC94">5.8 通用<acronym>LR</acronym> (<acronym>GLR</acronym>)分析-Generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) Parsing</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX6">通用<acronym>LR</acronym>(<acronym>GLR</acronym>)分析(generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) parsing)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC12">通用<acronym>LR</acronym>(<acronym>GLR</acronym>)分析(generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) parsing), 非歧义文法(unambiguous grammars)</a></td><td valign="top"><a href="#SEC12">1.5.1 使用<acronym>GLR</acronym>分析器分析非歧义文法</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC11">通用<acronym>LR</acronym>分析(generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) parsing)</a></td><td valign="top"><a href="#SEC11">1.5 编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_20">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC15">位置(location)</a></td><td valign="top"><a href="#SEC15">1.6 位置-Locations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC57">位置(location)</a></td><td valign="top"><a href="#SEC57">3.6 追踪位置-Tracking Locations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC57">位置(location), 文字的(textual)</a></td><td valign="top"><a href="#SEC57">3.6 追踪位置-Tracking Locations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC15">位置(location), 原文的(textual)</a></td><td valign="top"><a href="#SEC15">1.6 位置-Locations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC58">位置的数据类型(data type of locations)</a></td><td valign="top"><a href="#SEC58">3.6.1 位置的数据类型-Data Type of Locations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC59">位置动作(location actions)</a></td><td valign="top"><a href="#SEC59">3.6.2 动作和位置-Actions and Locations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC33">位置追踪(location tracking calculator)</a></td><td valign="top"><a href="#SEC33">2.4 带有位置追踪的计算器:<code>ltcalc</code>-Location Tracking Calculator: <code>ltcalc</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC7">文法(grammar), 上下文无关(context-free)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC18">文件格式(file format)</a></td><td valign="top"><a href="#SEC18">1.9 Bison语法文件的整体布局-The Overall Layout of a Bison Grammar</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX18">文字串记号(literal string token)</a></td><td valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX15">文字记号(literal token)</a></td><td valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC57">文字位置(textual location)</a></td><td valign="top"><a href="#SEC57">3.6 追踪位置-Tracking Locations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC108">问题(questions)</a></td><td valign="top"><a href="#SEC108">10. 常见问题-Frequently Asked Questions</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_21">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX23">相互递归-mutual recursion</a></td><td valign="top"><a href="#SEC50">3.4 递归规则-Recursive Rules</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX100">项目(item)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX104">项目集核心(item set core)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX106">项目集核心(item set core)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC68">消除冲突警告(suppressing conflict warnings)</a></td><td valign="top"><a href="#SEC68">3.7.7 消除冲突警告-Suppressing Conflict Warnings</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_22">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC84">悬挂<code>else</code>问题(dangling <code>else</code>)</a></td><td valign="top"><a href="#SEC84">5.2 移进/归约冲突-Shift/Reduce Conflicts</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_23">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC90">一元操作符优先级(unary operator precedence)</a></td><td valign="top"><a href="#SEC90">5.4 上下文依赖优先级-Context-Dependent Precedence</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC82">移进(shifting)</a></td><td valign="top"><a href="#SEC82">5. Bison分析器算法-The Bison Parser Algorithm</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC11">移进/归约 冲突(shift/reduce conflicts)</a></td><td valign="top"><a href="#SEC11">1.5 编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC12">移进/归约冲突(shift/reduce conflicts)</a></td><td valign="top"><a href="#SEC12">1.5.1 使用<acronym>GLR</acronym>分析器分析非歧义文法</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC84">移进/归约冲突(shift/reduce conflicts)</a></td><td valign="top"><a href="#SEC84">5.2 移进/归约冲突-Shift/Reduce Conflicts</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_24">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC49">用于语法规则的语法(syntax of grammar rules)</a></td><td valign="top"><a href="#SEC49">3.3 描述语法规则的语法-Syntax of Grammar Rules</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC90">优先级(precedence), 上下文依赖(context-dependent)</a></td><td valign="top"><a href="#SEC90">5.4 上下文依赖优先级-Context-Dependent Precedence</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC90">优先级(precedence), 一元操作符(unary operator)</a></td><td valign="top"><a href="#SEC90">5.4 上下文依赖优先级-Context-Dependent Precedence</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC63">优先级声明(precedence declarations)</a></td><td valign="top"><a href="#SEC63">3.7.2 操作符优先级-Operator Precedence</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC91">有限状态机-finite-state machine</a></td><td valign="top"><a href="#SEC91">5.5 分析器状态-Parser States</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX22">右递归(right recursion)</a></td><td valign="top"><a href="#SEC50">3.4 递归规则-Recursive Rules</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC8">语法(grammar), Bison</a></td><td valign="top"><a href="#SEC8">1.2 从正规文法转换到Bison的输入-From Formal Rules to Bison Input</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC80">语法错误(syntax error)</a></td><td valign="top"><a href="#SEC80">4.3 错误报告函数<code>yyerror</code>-The Error Reporting Function <code>yyerror</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC46">语法的规则部分(rules section for grammar)</a></td><td valign="top"><a href="#SEC46">3.1.3 语法规则部分-The Grammar Rules Section</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC46">语法规则部分(grammar rules section)</a></td><td valign="top"><a href="#SEC46">3.1.3 语法规则部分-The Grammar Rules Section</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC49">语法规则的语法(grammar rule syntax)</a></td><td valign="top"><a href="#SEC49">3.3 描述语法规则的语法-Syntax of Grammar Rules</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC18">语法文件(grammar file)</a></td><td valign="top"><a href="#SEC18">1.9 Bison语法文件的整体布局-The Overall Layout of a Bison Grammar</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC18">语法文件的格式(format of grammar file)</a></td><td valign="top"><a href="#SEC18">1.9 Bison语法文件的整体布局-The Overall Layout of a Bison Grammar</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX11">语法组(syntactic grouping)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC51">语言的语义(language semantics), 定义(defining)</a></td><td valign="top"><a href="#SEC51">3.5 定义语言的语义-Defining Language Semantics</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC10">语义动作(semantic actions)</a></td><td valign="top"><a href="#SEC10">1.4 语义动作</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC9">语义值(semantic value)</a></td><td valign="top"><a href="#SEC9">1.3 语义值-Semantic Values</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC52">语义值的数据类型(data types of semantic values)</a></td><td valign="top"><a href="#SEC52">3.5.1 语义值的数据类型-Data Types of Semantic Values</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC52">语义值类型(semantic value type)</a></td><td valign="top"><a href="#SEC52">3.5.1 语义值的数据类型-Data Types of Semantic Values</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_25">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC15">原文位置(textual location)</a></td><td valign="top"><a href="#SEC15">1.6 位置-Locations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC29">运行Bison(简介)(running Bison (introduction))</a></td><td valign="top"><a href="#SEC29">2.1.6 运行Bison来产生分析器-Running Bison to Make the Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC56">在规则中的动作(actions in mid-rule)</a></td><td valign="top"><a href="#SEC56">3.5.5 规则中的动作-Actions in Mid-Rule</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_26">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC82">栈(stack), 分析器(parser)</a></td><td valign="top"><a href="#SEC82">5. Bison分析器算法-The Bison Parser Algorithm</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC95">栈溢出(stack overflow)</a></td><td valign="top"><a href="#SEC95">5.9 栈溢出以及如何避免它-Stack Overflow, and How to Avoid It</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC8">正规文法(formal grammar)</a></td><td valign="top"><a href="#SEC8">1.2 从正规文法转换到Bison的输入-From Formal Rules to Bison Input</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_27">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC9">值(value), 语义(semantic)</a></td><td valign="top"><a href="#SEC9">1.3 语义值-Semantic Values</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC52">值类型(value type), 语义(semantic)</a></td><td valign="top"><a href="#SEC52">3.5.1 语义值的数据类型-Data Types of Semantic Values</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC65">值类型(value types), 非终结符(nonterminals), 声明(declaring)</a></td><td valign="top"><a href="#SEC65">3.7.4 非终结符-Nonterminal Symbols</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC64">值类型(value types), 声明(declaring)</a></td><td valign="top"><a href="#SEC64">3.7.3 值类型集-The Collection of Value Types</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX101">指明规则(pointed rule)</a></td><td valign="top"><a href="#SEC102">8.1 理解你的分析器-Understanding Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC31">中缀符号计算器(infix notation calculator)</a></td><td valign="top"><a href="#SEC31">2.2 中缀符号计算器:<code>calc</code>-Infix Notation Calculator: <code>calc</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC48">终结符(terminal symbol)</a></td><td valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_28">�</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC91">状态(分析器的)(state (of parser))</a></td><td valign="top"><a href="#SEC91">5.5 分析器状态-Parser States</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC103">追踪分析器(tracing the parser)</a></td><td valign="top"><a href="#SEC103">8.2 跟踪你的分析器-Tracing Your Parser</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX17">字符串记号(string token)</a></td><td valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX14">字符记号(character token)</a></td><td valign="top"><a href="#SEC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC71">总结(summary), Bison声明(Bison declaration)</a></td><td valign="top"><a href="#SEC71">3.7.10 Bison声明总结-Bison Declaration Summary</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC81">总结(summary), 动作特征(action features)</a></td><td valign="top"><a href="#SEC81">4.4 在动作中使用的特殊特征-Special Features for Use in Actions</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC68">阻止有关冲突的警告(preventing warnings about conflicts)</a></td><td valign="top"><a href="#SEC68">3.7.7 消除冲突警告-Suppressing Conflict Warnings</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX12">组合(grouping),语法的(syntactic)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX21">左递归(left recursion)</a></td><td valign="top"><a href="#SEC50">3.4 递归规则-Recursive Rules</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_29">A</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX111"><acronym>AST</acronym></a></td><td valign="top"><a href="#SEC113">10.5 实现跳转/循环-Implementing Gotos/Loops</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_30">B</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX2">Backus-Naur 范式(Backus-Naur form)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC104">Bison的调用选项(options for invoking Bison)</a></td><td valign="top"><a href="#SEC104">9. 调用Bison-Invoking Bison</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC104">Bison调用(Bison invocation)</a></td><td valign="top"><a href="#SEC104">9. 调用Bison-Invoking Bison</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC16">Bison分析器(Bison parser)</a></td><td valign="top"><a href="#SEC16">1.7 Bison的输出:分析器文件-Bison Output: the Parser File</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC82">Bison分析器算法(Bison parser algorithm)</a></td><td valign="top"><a href="#SEC82">5. Bison分析器算法-The Bison Parser Algorithm</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC114">Bison符号(Bison symbols), 表格(table of)</a></td><td valign="top"><a href="#SEC114">A. Bison符号-Bison Symbols</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC16">Bison工具(Bison utility)</a></td><td valign="top"><a href="#SEC16">1.7 Bison的输出:分析器文件-Bison Output: the Parser File</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC61">Bison声明(Bison declarations)</a></td><td valign="top"><a href="#SEC61">3.7 Bison声明-Bison Declarations</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC45">Bison声明(简介)(Bison declarations (introduction))</a></td><td valign="top"><a href="#SEC45">3.1.2 <var>Bison Declarations</var>部分-The Bison Declarations Section</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC71">Bison声明总结(Bison declaration summary)</a></td><td valign="top"><a href="#SEC71">3.7.10 Bison声明总结-Bison Declaration Summary</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC8">Bison语法(Bison grammar)</a></td><td valign="top"><a href="#SEC8">1.2 从正规文法转换到Bison的输入-From Formal Rules to Bison Input</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC18">Bison语法文件的布局(layout of Bison grammar)</a></td><td valign="top"><a href="#SEC18">1.9 Bison语法文件的整体布局-The Overall Layout of a Bison Grammar</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC114">Bison中的符号(symbols in Bison), 表格(table of)</a></td><td valign="top"><a href="#SEC114">A. Bison符号-Bison Symbols</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX1"><acronym>BNF</acronym></a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_31">C</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC31"><code>calc</code></a></td><td valign="top"><a href="#SEC31">2.2 中缀符号计算器:<code>calc</code>-Infix Notation Calculator: <code>calc</code></a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC13">conflicts</a></td><td valign="top"><a href="#SEC13">1.5.2 使用<acronym>GLR</acronym>解决歧义-Using <acronym>GLR</acronym> to Resolve Ambiguities</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC47">C代码(C code), 额外部分(section for additional)</a></td><td valign="top"><a href="#SEC47">3.1.4 <var>Epilogue</var>部分-The epilogue</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_32">E</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC84"><code>else</code>, 悬挂(dangling)</a></td><td valign="top"><a href="#SEC84">5.2 移进/归约冲突-Shift/Reduce Conflicts</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC47">epilogue</a></td><td valign="top"><a href="#SEC47">3.1.4 <var>Epilogue</var>部分-The epilogue</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_33">F</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC117">FDL, GNU Free Documentation License</a></td><td valign="top"><a href="#SEC117">C.1 GNU Free Documentation License</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_34">G</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC13">generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) parsing, ambiguous grammars</a></td><td valign="top"><a href="#SEC13">1.5.2 使用<acronym>GLR</acronym>解决歧义-Using <acronym>GLR</acronym> to Resolve Ambiguities</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC13"><acronym>GLR</acronym> parsing, ambiguous grammars</a></td><td valign="top"><a href="#SEC13">1.5.2 使用<acronym>GLR</acronym>解决歧义-Using <acronym>GLR</acronym> to Resolve Ambiguities</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX5"><acronym>GLR</acronym> 分析(<acronym>GLR</acronym> parsing)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC11"><acronym>GLR</acronym>分析(<acronym>GLR</acronym> parsing)</a></td><td valign="top"><a href="#SEC11">1.5 编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC94"><acronym>GLR</acronym>分析(<acronym>GLR</acronym> parsing)</a></td><td valign="top"><a href="#SEC94">5.8 通用<acronym>LR</acronym> (<acronym>GLR</acronym>)分析-Generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) Parsing</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC12"><acronym>GLR</acronym>分析(<acronym>GLR</acronym> parsing), 非歧义文法(unambiguous grammars)</a></td><td valign="top"><a href="#SEC12">1.5.1 使用<acronym>GLR</acronym>分析器分析非歧义文法</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC14"><acronym>GLR</acronym>分析器和<code>inline</code>(<acronym>GLR</acronym> parsers and <code>inline</code>)</a></td><td valign="top"><a href="#SEC14">1.5.3 编译<acronym>GLR</acronym>分析器时需要考虑的问题-Considerations when Compiling <acronym>GLR</acronym> Parsers</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_35">I</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC14"><code>inline</code></a></td><td valign="top"><a href="#SEC14">1.5.3 编译<acronym>GLR</acronym>分析器时需要考虑的问题-Considerations when Compiling <acronym>GLR</acronym> Parsers</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_36">L</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX86"><acronym>LALR</acronym>(1)</a></td><td valign="top"><a href="#SEC93">5.7 神秘的归约/归约冲突-Mysterious Reduce/Reduce Conflicts</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX3"><acronym>LALR</acronym>(1) 文法(<acronym>LALR</acronym>(1) grammars)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX85"><acronym>LR</acronym>(1)</a></td><td valign="top"><a href="#SEC93">5.7 神秘的归约/归约冲突-Mysterious Reduce/Reduce Conflicts</a></td></tr>
- <tr><td></td><td valign="top"><a href="#IDX4"><acronym>LR</acronym>(1) 文法(<acronym>LR</acronym>(1) grammars)</a></td><td valign="top"><a href="#SEC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC33"><code>ltcalc</code></a></td><td valign="top"><a href="#SEC33">2.4 带有位置追踪的计算器:<code>ltcalc</code>-Location Tracking Calculator: <code>ltcalc</code></a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_37">M</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC37"><code>mfcalc</code></a></td><td valign="top"><a href="#SEC37">2.5 多功能计算器:<code>mfcalc</code>-Multi-Function Calculator: <code>mfcalc</code></a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_38">P</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC44">Prologue</a></td><td valign="top"><a href="#SEC44">3.1.1 <var>Prologue</var>部分-The prologue</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- <tr><th><a name="SEC119_39">R</a></th><td></td><td></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC13">reduce/reduce conflicts</a></td><td valign="top"><a href="#SEC13">1.5.2 使用<acronym>GLR</acronym>解决歧义-Using <acronym>GLR</acronym> to Resolve Ambiguities</a></td></tr>
- <tr><td></td><td valign="top"><a href="#SEC20"><code>rpcalc</code></a></td><td valign="top"><a href="#SEC20">2.1 逆波兰记号计算器-Reverse Polish Notation Calculator</a></td></tr>
- <tr><td colspan="3"> <hr></td></tr>
- </tbody></table>
- <table><tbody><tr><th valign="top">跳转到: </th><td><a class="summary-letter" href="#SEC119_0"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_1"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_2"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_3"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_4"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_5"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_6"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_7"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_8"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_9"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_10"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_11"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_12"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_13"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_14"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_15"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_16"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_17"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_18"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_19"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_20"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_21"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_22"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_23"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_24"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_25"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_26"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_27"><b>�</b></a>
-
- <a class="summary-letter" href="#SEC119_28"><b>�</b></a>
-
- <br>
- <a class="summary-letter" href="#SEC119_29"><b>A</b></a>
-
- <a class="summary-letter" href="#SEC119_30"><b>B</b></a>
-
- <a class="summary-letter" href="#SEC119_31"><b>C</b></a>
-
- <a class="summary-letter" href="#SEC119_32"><b>E</b></a>
-
- <a class="summary-letter" href="#SEC119_33"><b>F</b></a>
-
- <a class="summary-letter" href="#SEC119_34"><b>G</b></a>
-
- <a class="summary-letter" href="#SEC119_35"><b>I</b></a>
-
- <a class="summary-letter" href="#SEC119_36"><b>L</b></a>
-
- <a class="summary-letter" href="#SEC119_37"><b>M</b></a>
-
- <a class="summary-letter" href="#SEC119_38"><b>P</b></a>
-
- <a class="summary-letter" href="#SEC119_39"><b>R</b></a>
-
- </td></tr></tbody></table>
- <hr size="6">
- <a name="SEC_Contents"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1><a name="t121"></a>目录</h1>
- <div class="contents">
- <ul class="toc">
- <li><a href="#SEC1" name="TOC1">Bison简介-Introduction</a></li>
- <li><a href="#SEC2" name="TOC2">使用Bison的条件-Conditions for Using Bison</a></li>
- <li><a href="#SEC3" name="TOC3">GNU GENERAL PUBLIC LICENSE</a>
- <ul class="toc">
- <li><a href="#SEC4" name="TOC4">Preamble</a></li>
- <li><a href="#SEC5" name="TOC5">Appendix: How to Apply These Terms to Your New Programs</a></li>
- </ul></li>
- <li><a href="#SEC6" name="TOC6">1. 和Bison相关的一些基本概念-The Concepts of Bison</a>
- <ul class="toc">
- <li><a href="#SEC7" name="TOC7">1.1 语言与上下文无关文法-Languages and Context-Free Grammars</a></li>
- <li><a href="#SEC8" name="TOC8">1.2 从正规文法转换到Bison的输入-From Formal Rules to Bison Input</a></li>
- <li><a href="#SEC9" name="TOC9">1.3 语义值-Semantic Values</a></li>
- <li><a href="#SEC10" name="TOC10">1.4 语义动作</a></li>
- <li><a href="#SEC11" name="TOC11">1.5 编写<acronym>GLR</acronym>分析器-Writing <acronym>GLR</acronym> Parsers</a>
- <ul class="toc">
- <li><a href="#SEC12" name="TOC12">1.5.1 使用<acronym>GLR</acronym>分析器分析非歧义文法</a></li>
- <li><a href="#SEC13" name="TOC13">1.5.2 使用<acronym>GLR</acronym>解决歧义-Using <acronym>GLR</acronym> to Resolve Ambiguities</a></li>
- <li><a href="#SEC14" name="TOC14">1.5.3 编译<acronym>GLR</acronym>分析器时需要考虑的问题-Considerations when Compiling <acronym>GLR</acronym> Parsers</a></li>
- </ul></li>
- <li><a href="#SEC15" name="TOC15">1.6 位置-Locations</a></li>
- <li><a href="#SEC16" name="TOC16">1.7 Bison的输出:分析器文件-Bison Output: the Parser File</a></li>
- <li><a href="#SEC17" name="TOC17">1.8 使用Bison的流程-Stages in Using Bison</a></li>
- <li><a href="#SEC18" name="TOC18">1.9 Bison语法文件的整体布局-The Overall Layout of a Bison Grammar</a></li>
- </ul></li>
- <li><a href="#SEC19" name="TOC19">2. 实例-Examples</a>
- <ul class="toc">
- <li><a href="#SEC20" name="TOC20">2.1 逆波兰记号计算器-Reverse Polish Notation Calculator</a>
- <ul class="toc">
- <li><a href="#SEC21" name="TOC21">2.1.1 <code>rpclac</code>的声明部分-Declarations for <code>rpcalc</code></a></li>
- <li><a href="#SEC22" name="TOC22">2.1.2 <code>rpcalc</code>的语法规则-Grammar Rules for <code>rpcalc</code></a>
- <ul class="toc">
- <li><a href="#SEC23" name="TOC23">2.1.2.1 解释<code>input</code>-Explanation of <code>input</code></a></li>
- <li><a href="#SEC24" name="TOC24">2.1.2.2 解释<code>line</code>-Explanation of <code>line</code></a></li>
- <li><a href="#SEC25" name="TOC25">2.1.2.3 解释<code>expr</code>-Explanation of <code>expr</code></a></li>
- </ul></li>
- <li><a href="#SEC26" name="TOC26">2.1.3 <code>rpcalc</code>的词法分析器-The <code>rpcalc</code> Lexical Analyzer</a></li>
- <li><a href="#SEC27" name="TOC27">2.1.4 控制函数-The Controlling Function</a></li>
- <li><a href="#SEC28" name="TOC28">2.1.5 错误报告的规则-The Error Reporting Routine</a></li>
- <li><a href="#SEC29" name="TOC29">2.1.6 运行Bison来产生分析器-Running Bison to Make the Parser</a></li>
- <li><a href="#SEC30" name="TOC30">2.1.7 编译分析器文件-Compiling the Parser File</a></li>
- </ul></li>
- <li><a href="#SEC31" name="TOC31">2.2 中缀符号计算器:<code>calc</code>-Infix Notation Calculator: <code>calc</code></a></li>
- <li><a href="#SEC32" name="TOC32">2.3 简单的错误恢复-Simple Error Recovery</a></li>
- <li><a href="#SEC33" name="TOC33">2.4 带有位置追踪的计算器:<code>ltcalc</code>-Location Tracking Calculator: <code>ltcalc</code></a>
- <ul class="toc">
- <li><a href="#SEC34" name="TOC34">2.4.1 <code>ltcalc</code>的<var>Declarations</var>-Declarations for <code>ltcalc</code></a></li>
- <li><a href="#SEC35" name="TOC35">2.4.2 <code>ltcalc</code>的语法规则-Grammar Rules for <code>ltcalc</code></a></li>
- <li><a href="#SEC36" name="TOC36">2.4.3 <code>ltcalc</code>的词法分析器-The <code>ltcalc</code> Lexical Analyzer.</a></li>
- </ul></li>
- <li><a href="#SEC37" name="TOC37">2.5 多功能计算器:<code>mfcalc</code>-Multi-Function Calculator: <code>mfcalc</code></a>
- <ul class="toc">
- <li><a href="#SEC38" name="TOC38">2.5.1 <code>mfcalc</code>的声明-Declarations for <code>mfcalc</code></a></li>
- <li><a href="#SEC39" name="TOC39">2.5.2 <code>mfcalc</code>的语法规则-Grammar Rules for <code>mfcalc</code></a></li>
- <li><a href="#SEC40" name="TOC40">2.5.3 <code>mfcalc</code>的符号表-The <code>mfcalc</code> Symbol Table</a></li>
- </ul></li>
- <li><a href="#SEC41" name="TOC41">2.6 练习-Exercises</a></li>
- </ul></li>
- <li><a href="#SEC42" name="TOC42">3. Biosn的语法文件-Bison Grammar Files</a>
- <ul class="toc">
- <li><a href="#SEC43" name="TOC43">3.1 Bison语法的提纲-Outline of a Bison Grammar</a>
- <ul class="toc">
- <li><a href="#SEC44" name="TOC44">3.1.1 <var>Prologue</var>部分-The prologue</a></li>
- <li><a href="#SEC45" name="TOC45">3.1.2 <var>Bison Declarations</var>部分-The Bison Declarations Section</a></li>
- <li><a href="#SEC46" name="TOC46">3.1.3 语法规则部分-The Grammar Rules Section</a></li>
- <li><a href="#SEC47" name="TOC47">3.1.4 <var>Epilogue</var>部分-The epilogue</a></li>
- </ul></li>
- <li><a href="#SEC48" name="TOC48">3.2 符号,终结符和非终结符-Symbols, Terminal and Nonterminal</a></li>
- <li><a href="#SEC49" name="TOC49">3.3 描述语法规则的语法-Syntax of Grammar Rules</a></li>
- <li><a href="#SEC50" name="TOC50">3.4 递归规则-Recursive Rules</a></li>
- <li><a href="#SEC51" name="TOC51">3.5 定义语言的语义-Defining Language Semantics</a>
- <ul class="toc">
- <li><a href="#SEC52" name="TOC52">3.5.1 语义值的数据类型-Data Types of Semantic Values</a></li>
- <li><a href="#SEC53" name="TOC53">3.5.2 多种值类型-More Than One Value Type</a></li>
- <li><a href="#SEC54" name="TOC54">3.5.3 动作-Actions</a></li>
- <li><a href="#SEC55" name="TOC55">3.5.4 动作中值的数据类型-Data Types of Values in Actions</a></li>
- <li><a href="#SEC56" name="TOC56">3.5.5 规则中的动作-Actions in Mid-Rule</a></li>
- </ul></li>
- <li><a href="#SEC57" name="TOC57">3.6 追踪位置-Tracking Locations</a>
- <ul class="toc">
- <li><a href="#SEC58" name="TOC58">3.6.1 位置的数据类型-Data Type of Locations</a></li>
- <li><a href="#SEC59" name="TOC59">3.6.2 动作和位置-Actions and Locations</a></li>
- <li><a href="#SEC60" name="TOC60">3.6.3 位置的默认动作-Default Action for Locations</a></li>
- </ul></li>
- <li><a href="#SEC61" name="TOC61">3.7 Bison声明-Bison Declarations</a>
- <ul class="toc">
- <li><a href="#SEC62" name="TOC62">3.7.1 符号类型名称-Token Type Names</a></li>
- <li><a href="#SEC63" name="TOC63">3.7.2 操作符优先级-Operator Precedence</a></li>
- <li><a href="#SEC64" name="TOC64">3.7.3 值类型集-The Collection of Value Types</a></li>
- <li><a href="#SEC65" name="TOC65">3.7.4 非终结符-Nonterminal Symbols</a></li>
- <li><a href="#SEC66" name="TOC66">3.7.5 在分析执行前执行一些动作-Performing Actions before Parsing</a></li>
- <li><a href="#SEC67" name="TOC67">3.7.6 释放被丢弃的符号-Freeing Discarded Symbols</a></li>
- <li><a href="#SEC68" name="TOC68">3.7.7 消除冲突警告-Suppressing Conflict Warnings</a></li>
- <li><a href="#SEC69" name="TOC69">3.7.8 开始符号-The Start-Symbol</a></li>
- <li><a href="#SEC70" name="TOC70">3.7.9 纯(可重入)分析器-A Pure (Reentrant) Parser</a></li>
- <li><a href="#SEC71" name="TOC71">3.7.10 Bison声明总结-Bison Declaration Summary</a></li>
- </ul></li>
- <li><a href="#SEC72" name="TOC72">3.8 在同一个程序中使用多个分析器-Multiple Parsers in the Same Program</a></li>
- </ul></li>
- <li><a href="#SEC73" name="TOC73">4. 分析器C语言接口-Parser C-Language Interface</a>
- <ul class="toc">
- <li><a href="#SEC74" name="TOC74">4.1 分析器函数<code>yyparse</code>-The Parser Function <code>yyparse</code></a></li>
- <li><a href="#SEC75" name="TOC75">4.2 词法分析器函数<code>yylex</code>-The Lexical Analyzer Function <code>yylex</code></a>
- <ul class="toc">
- <li><a href="#SEC76" name="TOC76">4.2.1 <code>yylex</code>的调用惯例-Calling Convention for <code>yylex</code></a></li>
- <li><a href="#SEC77" name="TOC77">4.2.2 记号的语义值-Semantic Values of Tokens</a></li>
- <li><a href="#SEC78" name="TOC78">4.2.3 记号的文字位置-Textual Locations of Tokens</a></li>
- <li><a href="#SEC79" name="TOC79">4.2.4 纯分析器的调用惯例-Conventions for Pure Parsers</a></li>
- </ul></li>
- <li><a href="#SEC80" name="TOC80">4.3 错误报告函数<code>yyerror</code>-The Error Reporting Function <code>yyerror</code></a></li>
- <li><a href="#SEC81" name="TOC81">4.4 在动作中使用的特殊特征-Special Features for Use in Actions</a></li>
- </ul></li>
- <li><a href="#SEC82" name="TOC82">5. Bison分析器算法-The Bison Parser Algorithm</a>
- <ul class="toc">
- <li><a href="#SEC83" name="TOC83">5.1 超前扫描记号-Look-Ahead Tokens</a></li>
- <li><a href="#SEC84" name="TOC84">5.2 移进/归约冲突-Shift/Reduce Conflicts</a></li>
- <li><a href="#SEC85" name="TOC85">5.3 操作符优先级-Operator Precedence</a>
- <ul class="toc">
- <li><a href="#SEC86" name="TOC86">5.3.1 什么时候需要优先级-When Precedence is Needed</a></li>
- <li><a href="#SEC87" name="TOC87">5.3.2 指定操作符的优先级-Specifying Operator Precedence</a></li>
- <li><a href="#SEC88" name="TOC88">5.3.3 优先级使用的例子-Precedence Examples</a></li>
- <li><a href="#SEC89" name="TOC89">5.3.4 优先级如何工作-How Precedence Works</a></li>
- </ul></li>
- <li><a href="#SEC90" name="TOC90">5.4 上下文依赖优先级-Context-Dependent Precedence</a></li>
- <li><a href="#SEC91" name="TOC91">5.5 分析器状态-Parser States</a></li>
- <li><a href="#SEC92" name="TOC92">5.6 归约/归约冲突-Reduce/Reduce Conflicts</a></li>
- <li><a href="#SEC93" name="TOC93">5.7 神秘的归约/归约冲突-Mysterious Reduce/Reduce Conflicts</a></li>
- <li><a href="#SEC94" name="TOC94">5.8 通用<acronym>LR</acronym> (<acronym>GLR</acronym>)分析-Generalized <acronym>LR</acronym> (<acronym>GLR</acronym>) Parsing</a></li>
- <li><a href="#SEC95" name="TOC95">5.9 栈溢出以及如何避免它-Stack Overflow, and How to Avoid It</a></li>
- </ul></li>
- <li><a href="#SEC96" name="TOC96">6. 错误恢复-Error Recovery</a></li>
- <li><a href="#SEC97" name="TOC97">7. 处理上下文依赖-Handling Context Dependencies</a>
- <ul class="toc">
- <li><a href="#SEC98" name="TOC98">7.1 符号类型中的语义信息-Semantic Info in Token Types</a></li>
- <li><a href="#SEC99" name="TOC99">7.2 词法关联-Lexical Tie-ins</a></li>
- <li><a href="#SEC100" name="TOC100">7.3 词法关联和错误恢复-Lexical Tie-ins and Error Recovery</a></li>
- </ul></li>
- <li><a href="#SEC101" name="TOC101">8. 调式你的分析器-Debugging Your Parser</a>
- <ul class="toc">
- <li><a href="#SEC102" name="TOC102">8.1 理解你的分析器-Understanding Your Parser</a></li>
- <li><a href="#SEC103" name="TOC103">8.2 跟踪你的分析器-Tracing Your Parser</a></li>
- </ul></li>
- <li><a href="#SEC104" name="TOC104">9. 调用Bison-Invoking Bison</a>
- <ul class="toc">
- <li><a href="#SEC105" name="TOC105">9.1 Bison选项-Bison Options</a></li>
- <li><a href="#SEC106" name="TOC106">9.2 选项交叉键-Option Cross Key</a></li>
- <li><a href="#SEC107" name="TOC107">9.3 Yacc库-Yacc Library</a></li>
- </ul></li>
- <li><a href="#SEC108" name="TOC108">10. 常见问题-Frequently Asked Questions</a>
- <ul class="toc">
- <li><a href="#SEC109" name="TOC109">10.1 分析器栈溢出-Parser Stack Overflow</a></li>
- <li><a href="#SEC110" name="TOC110">10.2 我如何复位分析器-How Can I Reset the Parser</a></li>
- <li><a href="#SEC111" name="TOC111">10.3 被销毁的字符串-Strings are Destroyed</a></li>
- <li><a href="#SEC112" name="TOC112">10.4 C++分析器-C++ Parsers</a></li>
- <li><a href="#SEC113" name="TOC113">10.5 实现跳转/循环-Implementing Gotos/Loops</a></li>
- </ul></li>
- <li><a href="#SEC114" name="TOC114">A. Bison符号-Bison Symbols</a></li>
- <li><a href="#SEC115" name="TOC115">B. 词汇表-Glossary</a></li>
- <li><a href="#SEC116" name="TOC116">C. 复制这个手册-Copying This Manual</a>
- <ul class="toc">
- <li><a href="#SEC117" name="TOC117">C.1 GNU Free Documentation License</a>
- <ul class="toc">
- <li><a href="#SEC118" name="TOC118">C.1.1 ADDENDUM: How to use this License for your documents</a></li>
- </ul>
- </li>
- </ul></li>
- <li><a href="#SEC119" name="TOC119">索引-Index</a></li>
- </ul>
- </div>
- <hr size="1">
- <a name="SEC_About"></a>
- <table border="0" cellpadding="1" cellspacing="1">
- <tbody><tr><td align="left" valign="middle">[<a title="文档封面" href="#SEC_Top">顶层</a>]</td>
- <td align="left" valign="middle">[<a title="目录" href="#SEC_Contents">内容</a>]</td>
- <td align="left" valign="middle">[<a title="索引" href="#SEC119">索引</a>]</td>
- <td align="left" valign="middle">[<a title="关于 (帮助)" href="#SEC_About"> ? </a>]</td>
- </tr></tbody></table>
- <h1><a name="t122"></a>关于这个文档</h1>
- <p>
- 这个文档由<em>Charlie &</em>在<em>2005,六月,21</em>使用王箫改进的<a href="http://texi2html.cvshome.org/"><em>texi2html 1.76</em></a>生成.
- </p>
- <p>
- 导航面板的按钮有如下意义
- </p>
- <table border="1">
- <tbody><tr>
- <th> 按钮 </th>
- <th> 名称 </th>
- <th> 转到 </th>
- <th> From 1.2.3 go to</th>
- </tr>
- <tr>
- <td align="center"> [ < ] </td>
- <td align="center">Back</td>
- <td>阅读顺序的上一章</td>
- <td>1.2.2</td>
- </tr>
- <tr>
- <td align="center"> [ > ] </td>
- <td align="center">Forward</td>
- <td>阅读顺序的下一章</td>
- <td>1.2.4</td>
- </tr>
- <tr>
- <td align="center"> [ << ] </td>
- <td align="center">FastBack</td>
- <td>章节的开始或上一章</td>
- <td>1</td>
- </tr>
- <tr>
- <td align="center"> [ 上层 ] </td>
- <td align="center">Up</td>
- <td>上层章节</td>
- <td>1.2</td>
- </tr>
- <tr>
- <td align="center"> [ >> ] </td>
- <td align="center">FastForward</td>
- <td>下一章</td>
- <td>2</td>
- </tr>
- <tr>
- <td align="center"> [顶层] </td>
- <td align="center">Top</td>
- <td>文档封面</td>
- <td> </td>
- </tr>
- <tr>
- <td align="center"> [内容] </td>
- <td align="center">Contents</td>
- <td>目录</td>
- <td> </td>
- </tr>
- <tr>
- <td align="center"> [索引] </td>
- <td align="center">Index</td>
- <td>索引</td>
- <td> </td>
- </tr>
- <tr>
- <td align="center"> [ ? ] </td>
- <td align="center">About</td>
- <td>关于 (帮助)</td>
- <td> </td>
- </tr>
- </tbody></table>
- <p>
- 这个<strong> 例子 </strong>假定当前的位置是在如下结构文档的<strong> 章节 1-2-3</strong>
- </p>
- <ul>
- <li> 1. 第一部分
- <ul>
- <li>1.1 章节 1-1
- <ul>
- <li>...</li>
- </ul>
- </li>
- <li>1.2 章节 1-2
- <ul>
- <li>1.2.1 章节 1-2-1</li>
- <li>1.2.2 章节 1-2-2</li>
- <li>1.2.3 章节 1-2-3
- <strong><== 当前位置 </strong></li>
- <li>1.2.4 章节 1-2-4</li>
- </ul>
- </li>
- <li>1.3 章节 1-3
- <ul>
- <li>...</li>
- </ul>
- </li>
- <li>1.4 章节 1-4</li>
- </ul>
- </li>
- </ul>
- <hr size="1">
- <p>
- <font size="-1">
- 这个文档由<em>Charlie &</em>在<em>2005,六月,21</em>使用王箫改进的<a href="http://texi2html.cvshome.org/"><em>texi2html 1.76</em></a>生成.
- </font>
- <br>
- </p>
-
- <div style="padding-top:20px">
- <p style="font-size:12px;">版权声明:本文为博主原创文章,未经博主允许不得转载。</p>
- </div>
- </div>
- <!-- Baidu Button BEGIN -->
- <div class="bdsharebuttonbox" style="float: right;">
- <a href="#" class="bds_more" data-cmd="more" style="background-position:0 0 !important; background-image: url(http://bdimg.share.baidu.com/static/api/img/share/icons_0_16.png?v=d754dcc0.png) !important"></a>
- <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间" style="background-position:0 -52px !important"></a>
- <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博" style="background-position:0 -104px !important"></a>
- <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博" style="background-position:0 -260px !important"></a>
- <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网" style="background-position:0 -208px !important"></a>
- <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信" style="background-position:0 -1612px !important"></a>
- </div>
- <script>window._bd_share_config = { "common": { "bdSnsKey": {}, "bdText": "", "bdMini": "1", "bdMiniList": false, "bdPic": "", "bdStyle": "0", "bdSize": "16" }, "share": {} }; with (document) 0[(getElementsByTagName('head')[0] || body).appendChild(createElement('script')).src = 'http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion=' + ~(-new Date() / 36e5)];</script>
- <!-- Baidu Button END -->
- <link rel="stylesheet" href="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/blog_detail.css">
-
- <!--172.16.140.12-->
- <ul class="article_next_prev">
- <li class="prev_article"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian']);location.href='/sirouni2003/article/details/400507';">上一篇</span><a href="http://blog.csdn.net/sirouni2003/article/details/400507" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian'])">Texi2Html中文输出版</a></li>
- <li class="next_article"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian']);location.href='/sirouni2003/article/details/590661';">下一篇</span><a href="http://blog.csdn.net/sirouni2003/article/details/590661" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian'])">GNU Bison 2.1 中文手册</a></li>
- </ul>
- <!-- Baidu Button BEGIN -->
- <script type="text/javascript" id="bdshare_js" data="type=tools&uid=1536434"></script>
- <script src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/shell_v2.html" type="text/javascript" id="bdshell_js"></script>
- <script type="text/javascript">
- document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion=" + Math.ceil(new Date()/3600000)
- </script>
- <!-- Baidu Button END -->
-
-
- </div>
- <div id="suggest">
- <dl class="blog-associat-tag">
- <dt>主题推荐</dt>
- <dd>
- <a href="http://www.csdn.net/tag/html" target="_blank" class="blog-tage-red">html</a>
- <a href="http://www.csdn.net/tag/gnu" target="_blank" class="blog-tage-red">gnu</a>
- <a href="http://www.csdn.net/tag/%E7%BC%96%E8%AF%91%E5%99%A8" target="_blank" class="blog-tage-red">编译器</a>
- <a href="http://www.csdn.net/tag/%E5%8E%8B%E7%BC%A9" target="_blank" class="blog-tage-red">压缩</a>
- <a href="http://www.csdn.net/tag/%E9%82%AE%E4%BB%B6" target="_blank" class="blog-tage-red">邮件</a>
- <a href="http://www.csdn.net/tag/%E5%8F%91%E5%B8%83" target="_blank" class="blog-tage-red">发布</a>
- <a href="http://www.csdn.net/tag/gzip" target="_blank" class="blog-tage-red">gzip</a>
- </dd>
- </dl>
- <span style="display:none" id="tags">html,gnu,编译器,压缩,邮件,发布,gzip</span>
- </div>
- <script language="javascript" type="text/javascript">
- $(function(){
- $.get("/sirouni2003/svc/GetSuggestContent/400672",function(data){
- $("#suggest").html(data);
- });
- });
- </script>
- <style>
- .blog-ass-articl dd {
- color: #369;
- width: 99%; /*修改行*/
- float: left;
- overflow: hidden;
- font: normal normal 12px/23px "SimSun";
- height: 23px;
- margin: 0;
- padding: 0 0 0 10px;
- margin-right: 30px;
- background: url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px;
- }
- </style>
- <dl class="blog-ass-articl" id="res-relatived">
- <dt><span>猜你在找</span></dt>
-
- <div id="adCollege" style="width: 42%;float: left;">
- <script src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/job_reco.html" type="text/javascript"></script>
- <script type="text/javascript">
- csdn.position.showEdu({
- sourceType: "blog",
- searchType: "detail",
- searchKey: "400672",
- username: "lhh411291769",
- recordcount: "5",
- containerId: "adCollege" //容器DIV的id。
- });
- </script>
- </div>
-
- <div id="res" data-mod="popu_36" class="tracking-ad" style="width: 42%;float: left;margin-right: 30px;"></div>
-
- </dl>
- <div id="job_blog_reco">
- <script src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/job_reco_002.html" type="text/javascript"></script>
-
- <script type="text/javascript">
- csdn.position.show({
- sourceType: "blog",
- tplType: "blogDetail",
- searchType: "detail",
- searchKey: "400672",
- username: "lhh411291769",
- containerId: "job_blog_reco"
- });
- </script>
- </div>
- <script type="text/javascript">
- $(function () {
- setTimeout(function () {
- var searchtitletags = 'GNU Bison 中文手册' + ',' + $("#tags").html();
- searchService({
- index: 'blog',
- query: searchtitletags,
- from: 5,
- size: 5,
- appendTo: '#res',
- url: 'recommend',
- his: 2,
- client: "blog_cf_enhance",
- tmpl: '<dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px;"><a href="#{ url }" title="#{ title }" strategy="#{ strategy }">#{ title }</a></dd>'
- });
- }, 500);
- });
- </script>
- <div id="ad_cen">
-
- <script type="text/javascript">
- new Ad(4, 'ad_cen');
- </script>
- <iframe src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ad.html" style="border-width: 0px; overflow: hidden; width: 746px; height: 2px;" id="ad_frm_0" scrolling="no" frameborder="0"></iframe></div>
- <div class="comment_class">
- <div id="comment_title" class="panel_head">
- <span class="see_comment">查看评论</span><a name="comments"></a></div>
- <div id="comment_list"><dl class="comment_item comment_topic" id="comment_item_4861555"><dt class="comment_head" floor="14">14楼 <span class="user"><a class="username" href="http://blog.csdn.net/imcg_cg" target="_blank">imcg_cg</a> <span class="ptime">2015-03-19 14:15发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="4861555" username="imcg_cg"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/imcg_cg" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_imcg_cg.jpg" width="40" height="40"></a></dd><dd class="comment_body">帮助非常大,谢谢!</dd></dl><dl class="comment_item comment_topic" id="comment_item_991993"><dt class="comment_head" floor="13">13楼 <span class="user"><a class="username" href="http://blog.csdn.net/dychenyi" target="_blank">dychenyi</a> <span class="ptime">2008-12-26 17:34发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="991993" username="dychenyi"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/dychenyi" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_dychenyi.jpg" width="40" height="40"></a></dd><dd class="comment_body">要有出版社出版发行一下就好了</dd></dl><dl class="comment_item comment_topic" id="comment_item_554546"><dt class="comment_head" floor="12">12楼 <span class="user"><a class="username" href="http://blog.csdn.net/gengyong" target="_blank">gengyong</a> <span class="ptime">2007-04-19 21:06发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="554546" username="gengyong"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/gengyong" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_gengyong.gif" width="40" height="40"></a></dd><dd class="comment_body">太好了, 感激得一塌糊涂!</dd></dl><dl class="comment_item comment_topic" id="comment_item_500594"><dt class="comment_head" floor="11">11楼 <span class="user"><a class="username" href="http://blog.csdn.net/%E5%80%99%E9%B8%9F" target="_blank">候鸟</a> <span class="ptime">2006-10-07 23:24发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="500594" username="候鸟"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/%E5%80%99%E9%B8%9F" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_.gif" width="40" height="40"></a></dd><dd class="comment_body">牛!佩服</dd></dl><dl class="comment_item comment_topic" id="comment_item_455098"><dt class="comment_head" floor="10">10楼 <span class="user"><a class="username" href="http://blog.csdn.net/sirouni" target="_blank">sirouni</a> <span class="ptime">2006-06-19 16:24发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="455098" username="sirouni"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/sirouni" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_sirouni.gif" width="40" height="40"></a></dd><dd class="comment_body">bison2.1手册已经发布在http://blog.csdn.net/sirouni2003/archive/2006/02/01/590661.aspx</dd></dl><dl class="comment_item comment_topic" id="comment_item_428129"><dt class="comment_head" floor="9">9楼 <span class="user"><a class="username" href="http://blog.csdn.net/%E8%B7%AF%E4%BA%BA%E7%94%B2" target="_blank">路人甲</a> <span class="ptime">2006-03-30 10:57发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="428129" username="路人甲"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/%E8%B7%AF%E4%BA%BA%E7%94%B2" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3__002.gif" width="40" height="40"></a></dd><dd class="comment_body">谢谢!
- <br>如果把charset=us-ascii改成charset=gb2312就更好了</dd></dl><dl class="comment_item comment_topic" id="comment_item_420237"><dt class="comment_head" floor="8">8楼 <span class="user"><a class="username" href="http://blog.csdn.net/sirouni" target="_blank">sirouni</a> <span class="ptime">2006-02-24 17:37发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="420237" username="sirouni"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/sirouni" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_sirouni.gif" width="40" height="40"></a></dd><dd class="comment_body">谢谢havenot的鼓励,我会再接再厉的</dd></dl><dl class="comment_item comment_topic" id="comment_item_418886"><dt class="comment_head" floor="7">7楼 <span class="user"><a class="username" href="http://blog.csdn.net/havenot" target="_blank">havenot</a> <span class="ptime">2006-02-19 12:13发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="418886" username="havenot"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/havenot" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_havenot.gif" width="40" height="40"></a></dd><dd class="comment_body">很
- 早就来过你的网站,当时是为了寻找有关yacc的资料来完成我的一项兴趣所致的工作,在你这里收获了很多。今天依然是搜寻资料,偶然故地重游,发现你又增
- 加不少新的作品,而我的工作依然没有完成。非常欣赏你在技术上的执着追求和无私奉献精神,让我想到了台湾的侯捷。我们需要你这样的真正的技术拓荒者和奉献
- 者。
- <br>
- <br>*孤独的拓荒者把收获的最甜美的甘果送给后来人品尝!*</dd></dl><dl class="comment_item comment_topic" id="comment_item_396421"><dt class="comment_head" floor="6">6楼 <span class="user"><a class="username" href="http://blog.csdn.net/eric" target="_blank">eric</a> <span class="ptime">2005-10-21 18:36发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="396421" username="eric"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/eric" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_eric.gif" width="40" height="40"></a></dd><dd class="comment_body">牛</dd></dl><dl class="comment_item comment_topic" id="comment_item_393858"><dt class="comment_head" floor="5">5楼 <span class="user"><a class="username" href="http://blog.csdn.net/sirouni2003" target="_blank">sirouni2003</a> <span class="ptime">2005-09-27 19:11发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="393858" username="sirouni2003"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/sirouni2003" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_sirouni2003.gif" width="40" height="40"></a></dd><dd class="comment_body">我也很菜,有问题可以给我发邮件sirouni@yahoo.com.cn,一起研究。
- <br>我很少用qq的</dd></dl><dl class="comment_item comment_topic" id="comment_item_393312"><dt class="comment_head" floor="4">4楼 <span class="user"><a class="username" href="http://blog.csdn.net/marsaber" target="_blank">marsaber</a> <span class="ptime">2005-09-23 11:29发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="393312" username="marsaber"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/marsaber" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_marsaber.jpg" width="40" height="40"></a></dd><dd class="comment_body">俺没站,不过俺有QQ,能加你不?
- <br>俺是新手,很多都不会,想找个人跟着学习.
- <br>QQ:15055388</dd></dl><dl class="comment_item comment_topic" id="comment_item_385770"><dt class="comment_head" floor="3">3楼 <span class="user"><a class="username" href="http://blog.csdn.net/mhss" target="_blank">mhss</a> <span class="ptime">2005-07-19 09:24发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="385770" username="mhss"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/mhss" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_mhss.gif" width="40" height="40"></a></dd><dd class="comment_body">好的,我已经加入了你的地址,我的地址是 http://mhss.nease.net</dd></dl><dl class="comment_item comment_topic" id="comment_item_385415"><dt class="comment_head" floor="2">2楼 <span class="user"><a class="username" href="http://blog.csdn.net/sirouni" target="_blank">sirouni</a> <span class="ptime">2005-07-16 18:40发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="385415" username="sirouni"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/sirouni" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_sirouni.gif" width="40" height="40"></a></dd><dd class="comment_body">没有问题,告诉我地址吧</dd></dl><dl class="comment_item comment_topic" id="comment_item_382347"><dt class="comment_head" floor="1">1楼 <span class="user"><a class="username" href="http://blog.csdn.net/mhss" target="_blank">mhss</a> <span class="ptime">2005-06-27 09:43发表</span> <a href="#reply" class="cmt_btn reply" title="回复">[回复]</a> <span class="comment_manage" style="display:none;" commentid="382347" username="mhss"> <a href="#quote" class="cmt_btn quote" title="引用">[引用]</a> <a href="#report" class="cmt_btn report" title="举报">[举报]</a></span></span></dt><dd class="comment_userface"><a href="http://blog.csdn.net/mhss" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/3_mhss.gif" width="40" height="40"></a></dd><dd class="comment_body">了不起!想和你做个友情连接:)</dd></dl><div class="clear"></div></div>
- <div id="comment_bar">
- </div>
- <div id="comment_form"><a name="commentbox"></a><a name="reply"></a><a name="quote"></a><form action="/sirouni2003/comment/submit?id=400672" method="post" onsubmit="return subform(this);"><div class="commentform"><div class="panel_head">发表评论</div><ul><li class="left">用 户 名:</li><li class="right">lhh411291769</li></ul><ul><li class="left">评论内容:</li><li class="right" style="position:relative;"><div id="ubbtools"><a href="#insertcode" code="code"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/code.gif" alt="插入代码" title="插入代码" border="0"></a></div><div id="lang_list" style="position: absolute; top: 28px; left: 0px; display: none;"><a class="long_name" href="#html">HTML/XML</a><a class="long_name" href="#objc">objective-c</a><a class="zhong_name" href="#delphi">Delphi</a><a class="zhong_name" href="#ruby">Ruby</a><a href="#php">PHP</a><a class="duan_name" href="#csharp">C#</a><a style=" border-right: none;" class="duan_name" href="#cpp">C++</a><a style=" border-bottom:none;" class="long_name" href="#javascript">JavaScript</a><a style=" border-bottom:none;" class="long_name" href="#vb">Visual Basic</a><a style=" border-bottom:none;" class="zhong_name" href="#python">Python</a><a style=" border-bottom:none;" class="zhong_name" href="#java">Java</a><a style="border-bottom:none;" class="duan_name" href="#css">CSS</a><a style="border-bottom:none;" class="duan_name" href="#sql">SQL</a><a style="border:none;" class="duan_name" href="#plain">其它</a></div><textarea class="comment_content" name="comment_content" id="comment_content" style="width: 400px; height: 200px;"></textarea></li></ul><ul><input id="comment_replyId" name="comment_replyId" type="hidden"><input id="comment_userId" name="comment_userId" value="521203" type="hidden"><input id="commentId" name="commentId" value="" type="hidden"><input class="comment_btn" value="提交" type="submit"> <span id="tip_comment" style="color: Red; display: none;"></span></ul></div></form></div>
- <div class="announce">
- * 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场<a name="reply"></a><a name="quote"></a></div>
- </div>
- <script type="text/javascript">
- var fileName = '400672';
- var commentscount = 14;
- var islock = false
- </script>
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/comment.js"></script>
- <div id="ad_bot">
- </div>
- <script type="text/javascript">
- setTimeout(function(){
- new Ad(5, 'ad_bot');
- },500);
- </script>
- <div id="report_dialog">
- </div>
- <div id="d-top" style="bottom:60px;">
- <a id="quick-reply" class="btn btn-top q-reply" title="快速回复" style="display:none;">
- <img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/blog-icon-reply.png" alt="快速回复">
- </a>
- <a id="d-top-a" class="btn btn-top backtop" style="display: none;" title="返回顶部" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_huidaodingbu'])">
- <img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/top.png" alt="TOP">
- </a>
- </div>
- <script type="text/javascript">
- $(function ()
- {
- $("#ad_frm_0").height("90px");
-
- setTimeout(function(){
- $("#ad_frm_2").height("200px");
- },1000);
- });
-
- </script>
- <style type="text/css">
- .tag_list
- {
- background: none repeat scroll 0 0 #FFFFFF;
- border: 1px solid #D7CBC1;
- color: #000000;
- font-size: 12px;
- line-height: 20px;
- list-style: none outside none;
- margin: 10px 2% 0 1%;
- padding: 1px;
- }
- .tag_list h5
- {
- background: none repeat scroll 0 0 #E0DBD3;
- color: #47381C;
- font-size: 12px;
- height: 24px;
- line-height: 24px;
- padding: 0 5px;
- margin: 0;
- }
- .tag_list h5 a
- {
- color: #47381C;
- }
- .classify
- {
- margin: 10px 0;
- padding: 4px 12px 8px;
- }
- .classify a
- {
- margin-right: 20px;
- white-space: nowrap;
- }
- </style>
- <div class="tag_list" style="">
- <h5>
- <a href="http://www.csdn.net/tag/" target="_blank">核心技术类目</a></h5>
- <div class="classify">
- <a title="全部主题" href="http://www.csdn.net/tag" target="_blank" onclick="LogClickCount(this,336);">全部主题</a>
- <a title="Hadoop" href="http://g.csdn.net/5272865" target="_blank" onclick="LogClickCount(this,336);">Hadoop</a>
- <a title="AWS" href="http://g.csdn.net/5272866" target="_blank" onclick="LogClickCount(this,336);">AWS</a>
- <a title="移动游戏" href="http://g.csdn.net/5272870" target="_blank" onclick="LogClickCount(this,336);">移动游戏</a>
- <a title="Java" href="http://g.csdn.net/5272871" target="_blank" onclick="LogClickCount(this,336);">Java</a>
- <a title="Android" href="http://g.csdn.net/5272872" target="_blank" onclick="LogClickCount(this,336);">Android</a>
- <a title="iOS" href="http://g.csdn.net/5272873" target="_blank" onclick="LogClickCount(this,336);">iOS</a>
- <a title="Swift" href="http://g.csdn.net/5272868" target="_blank" onclick="LogClickCount(this,336);">Swift</a>
- <a title="智能硬件" href="http://g.csdn.net/5272869" target="_blank" onclick="LogClickCount(this,336);">智能硬件</a>
- <a title="Docker" href="http://g.csdn.net/5272867" target="_blank" onclick="LogClickCount(this,336);">Docker</a>
- <a title="OpenStack" href="http://g.csdn.net/5272925" target="_blank" onclick="LogClickCount(this,336);">OpenStack</a>
- <a title="VPN" href="http://www.csdn.net/tag/vpn" target="_blank" onclick="LogClickCount(this,336);">VPN</a>
- <a title="Spark" href="http://g.csdn.net/5272924" target="_blank" onclick="LogClickCount(this,336);">Spark</a>
- <a title="ERP" href="http://www.csdn.net/tag/erp" target="_blank" onclick="LogClickCount(this,336);">ERP</a>
- <a title="IE10" href="http://www.csdn.net/tag/ie10" target="_blank" onclick="LogClickCount(this,336);">IE10</a>
- <a title="Eclipse" href="http://www.csdn.net/tag/eclipse" target="_blank" onclick="LogClickCount(this,336);">Eclipse</a>
- <a title="CRM" href="http://www.csdn.net/tag/crm" target="_blank" onclick="LogClickCount(this,336);">CRM</a>
- <a title="JavaScript" href="http://www.csdn.net/tag/javascript" target="_blank" onclick="LogClickCount(this,336);">JavaScript</a>
- <a title="数据库" href="http://www.csdn.net/tag/%E6%95%B0%E6%8D%AE%E5%BA%93" target="_blank" onclick="LogClickCount(this,336);">数据库</a>
- <a title="Ubuntu" href="http://www.csdn.net/tag/ubuntu" target="_blank" onclick="LogClickCount(this,336);">Ubuntu</a>
- <a title="NFC" href="http://www.csdn.net/tag/nfc" target="_blank" onclick="LogClickCount(this,336);">NFC</a>
- <a title="WAP" href="http://www.csdn.net/tag/wap" target="_blank" onclick="LogClickCount(this,336);">WAP</a>
- <a title="jQuery" href="http://www.csdn.net/tag/jquery" target="_blank" onclick="LogClickCount(this,336);">jQuery</a>
- <a title="BI" href="http://www.csdn.net/tag/bi" target="_blank" onclick="LogClickCount(this,336);">BI</a>
- <a title="HTML5" href="http://www.csdn.net/tag/html5" target="_blank" onclick="LogClickCount(this,336);">HTML5</a>
- <a title="Spring" href="http://www.csdn.net/tag/spring" target="_blank" onclick="LogClickCount(this,336);">Spring</a>
- <a title="Apache" href="http://www.csdn.net/tag/apache" target="_blank" onclick="LogClickCount(this,336);">Apache</a>
- <a title=".NET" href="http://www.csdn.net/tag/.net" target="_blank" onclick="LogClickCount(this,336);">.NET</a>
- <a title="API" href="http://www.csdn.net/tag/api" target="_blank" onclick="LogClickCount(this,336);">API</a>
- <a title="HTML" href="http://www.csdn.net/tag/html" target="_blank" onclick="LogClickCount(this,336);">HTML</a>
- <a title="SDK" href="http://www.csdn.net/tag/sdk" target="_blank" onclick="LogClickCount(this,336);">SDK</a>
- <a title="IIS" href="http://www.csdn.net/tag/iis" target="_blank" onclick="LogClickCount(this,336);">IIS</a>
- <a title="Fedora" href="http://www.csdn.net/tag/fedora" target="_blank" onclick="LogClickCount(this,336);">Fedora</a>
- <a title="XML" href="http://www.csdn.net/tag/xml" target="_blank" onclick="LogClickCount(this,336);">XML</a>
- <a title="LBS" href="http://www.csdn.net/tag/lbs" target="_blank" onclick="LogClickCount(this,336);">LBS</a>
- <a title="Unity" href="http://www.csdn.net/tag/unity" target="_blank" onclick="LogClickCount(this,336);">Unity</a>
- <a title="Splashtop" href="http://www.csdn.net/tag/splashtop" target="_blank" onclick="LogClickCount(this,336);">Splashtop</a>
- <a title="UML" href="http://www.csdn.net/tag/uml" target="_blank" onclick="LogClickCount(this,336);">UML</a>
- <a title="components" href="http://www.csdn.net/tag/components" target="_blank" onclick="LogClickCount(this,336);">components</a>
- <a title="Windows Mobile" href="http://www.csdn.net/tag/windowsmobile" target="_blank" onclick="LogClickCount(this,336);">Windows Mobile</a>
- <a title="Rails" href="http://www.csdn.net/tag/rails" target="_blank" onclick="LogClickCount(this,336);">Rails</a>
- <a title="QEMU" href="http://www.csdn.net/tag/qemu" target="_blank" onclick="LogClickCount(this,336);">QEMU</a>
- <a title="KDE" href="http://www.csdn.net/tag/kde" target="_blank" onclick="LogClickCount(this,336);">KDE</a>
- <a title="Cassandra" href="http://www.csdn.net/tag/cassandra" target="_blank" onclick="LogClickCount(this,336);">Cassandra</a>
- <a title="CloudStack" href="http://www.csdn.net/tag/cloudstack" target="_blank" onclick="LogClickCount(this,336);">CloudStack</a>
- <a title="FTC" href="http://www.csdn.net/tag/ftc" target="_blank" onclick="LogClickCount(this,336);">FTC</a>
- <a title="coremail" href="http://www.csdn.net/tag/coremail" target="_blank" onclick="LogClickCount(this,336);">coremail</a>
- <a title="OPhone " href="http://www.csdn.net/tag/ophone" target="_blank" onclick="LogClickCount(this,336);">OPhone </a>
- <a title="CouchBase" href="http://www.csdn.net/tag/couchbase" target="_blank" onclick="LogClickCount(this,336);">CouchBase</a>
- <a title="云计算" href="http://www.csdn.net/tag/%E4%BA%91%E8%AE%A1%E7%AE%97" target="_blank" onclick="LogClickCount(this,336);">云计算</a>
- <a title="iOS6" href="http://www.csdn.net/tag/iOS6" target="_blank" onclick="LogClickCount(this,336);">iOS6</a>
- <a title="Rackspace " href="http://www.csdn.net/tag/rackspace" target="_blank" onclick="LogClickCount(this,336);">Rackspace </a>
- <a title="Web App" href="http://www.csdn.net/tag/webapp" target="_blank" onclick="LogClickCount(this,336);">Web App</a>
- <a title="SpringSide" href="http://www.csdn.net/tag/springside" target="_blank" onclick="LogClickCount(this,336);">SpringSide</a>
- <a title="Maemo" href="http://www.csdn.net/tag/maemo" target="_blank" onclick="LogClickCount(this,336);">Maemo</a>
- <a title="Compuware" href="http://www.csdn.net/tag/compuware" target="_blank" onclick="LogClickCount(this,336);">Compuware</a>
- <a title="大数据" href="http://www.csdn.net/tag/%E5%A4%A7%E6%95%B0%E6%8D%AE" target="_blank" onclick="LogClickCount(this,336);">大数据</a>
- <a title="aptech" href="http://www.csdn.net/tag/aptech" target="_blank" onclick="LogClickCount(this,336);">aptech</a>
- <a title="Perl" href="http://www.csdn.net/tag/perl" target="_blank" onclick="LogClickCount(this,336);">Perl</a>
- <a title="Tornado" href="http://www.csdn.net/tag/tornado" target="_blank" onclick="LogClickCount(this,336);">Tornado</a>
- <a title="Ruby" href="http://www.csdn.net/tag/ruby" target="_blank" onclick="LogClickCount(this,336);">Ruby</a>
- <a title="Hibernate" href="http://www.csdn.net/hibernate" target="_blank" onclick="LogClickCount(this,336);">Hibernate</a>
- <a title="ThinkPHP" href="http://www.csdn.net/tag/thinkphp" target="_blank" onclick="LogClickCount(this,336);">ThinkPHP</a>
- <a title="HBase" href="http://www.csdn.net/tag/hbase" target="_blank" onclick="LogClickCount(this,336);">HBase</a>
- <a title="Pure" href="http://www.csdn.net/tag/pure" target="_blank" onclick="LogClickCount(this,336);">Pure</a>
- <a title="Solr" href="http://www.csdn.net/tag/solr" target="_blank" onclick="LogClickCount(this,336);">Solr</a>
- <a title="Angular" href="http://www.csdn.net/tag/angular" target="_blank" onclick="LogClickCount(this,336);">Angular</a>
- <a title="Cloud Foundry" href="http://www.csdn.net/tag/cloudfoundry" target="_blank" onclick="LogClickCount(this,336);">Cloud Foundry</a>
- <a title="Redis" href="http://www.csdn.net/tag/redis" target="_blank" onclick="LogClickCount(this,336);">Redis</a>
- <a title="Scala" href="http://www.csdn.net/tag/scala" target="_blank" onclick="LogClickCount(this,336);">Scala</a>
- <a title="Django" href="http://www.csdn.net/tag/django" target="_blank" onclick="LogClickCount(this,336);">Django</a>
- <a title="Bootstrap" href="http://www.csdn.net/tag/bootstrap" target="_blank" onclick="LogClickCount(this,336);">Bootstrap</a>
- </div>
- </div>
- <script language="javascript" type="text/javascript">
- $(function(){
- setTimeout(function(){
- $.get("/sirouni2003/svc/GetTagContent",function(data){
- $(".tag_list").html(data).show();
- });
- });
- },500);
- </script>
- <div id="pop_win" style="display:none ;position: absolute; z-index: 10000; border: 1px solid rgb(220, 220, 220); top: 222.5px; left: 630px; opacity: 1; background: none 0px 0px repeat scroll rgb(255, 255, 255);">
-
- </div>
- <div id="popup_mask"></div>
- <style>
- #popup_mask
- {
- position: absolute;
- width: 100%;
- height: 100%;
- background: #000;
- z-index: 9999;
- left: 0px;
- top: 0px;
- opacity: 0.3;
- filter: alpha(opacity=30);
- display: none;
- }
- </style>
- <script type="text/javascript">
- $(function(){
- setTimeout(function(){
- $(".comment_body:contains('回复')").each(function(index,item){
- var u=$(this).text().split(':')[0].toString().replace("回复","")
- var thisComment=$(this);
- if(u)
- {
- $.getJSON("https://passport.csdn.net/get/nick?callback=?", {users: u}, function(a) {
- if(a!=null&&a.data!=null&&a.data.length>0)
- {
- nick=a.data[0].n;
- if(u!=nick)
- {
- thisComment.text(thisComment.text().replace(u,nick));
- }
- }
- });
- }
- });
- },200);
-
- setTimeout(function(){
- $("a img[src='http://js.tongji.linezing.com/stats.gif']").parent().css({"position":"absolute","left":"50%"});
- },300);
- });
- function loginbox(){
- var $logpop=$("#pop_win");
- $logpop.html('<iframe src="https://passport.csdn.net/account/loginbox?service=http://static.blog.csdn.net/callback.htm" frameborder="0" height="600" width="400" scrolling="no"></iframe>');
- $('#popup_mask').css({
- opacity: 0.5,
- width: $( document ).width() + 'px',
- height: $( document ).height() + 'px'
- });
- $('#popup_mask').css("display","block");
-
- $logpop.css( {
- top: ($( window ).height() - $logpop.height())/ 2 + $( window
- ).scrollTop() + 'px',
- left:($( window ).width() - $logpop.width())/ 2
- } );
-
- setTimeout( function () {
- $logpop.show();
- $logpop.css( {
- opacity: 1
- } );
- }, 200 );
-
- $('#popup_mask').unbind("click");
- $('#popup_mask').bind("click", function(){
- $('#popup_mask').hide();
- var $clopop = $("#pop_win");
- $("#common_ask_div_sc").css("display","none");
- $clopop.css( {
- opacity: 0
- } );
- setTimeout( function () {
- $clopop.hide();
- }, 350 );
- return false;
- });
- }
- </script>
- <div class="clear">
- </div>
- </div>
-
- </div>
-
- <div id="side">
- <div class="side">
- <div id="panel_Profile" class="panel">
- <ul class="panel_head"><span>个人资料</span></ul>
- <ul class="panel_body profile">
- <div id="blog_userface">
- <a href="http://my.csdn.net/sirouni2003" target="_blank">
- <img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/1_sirouni2003.gif" title="访问我的空间" style="max-width:90%">
- </a>
- <br>
- <span><a href="http://my.csdn.net/sirouni2003" class="user_name" target="_blank">sirouni2003</a></span>
- </div>
- <div class="interact">
- <a href="javascript:void(0);" class="attent" id="span_add_follow" title="[加关注]"></a>
- <a href="javascript:void(0);" class="letter" title="[发私信]" onclick="window.open('http://msg.csdn.net/letters/model?receiver=sirouni2003','_blank','height=350,width=700');_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_sixin'])"></a>
- </div>
- <div id="blog_medal">
- <div id="bms_box">
- </div>
- </div>
- <ul id="blog_rank">
- <li>访问:<span>65066次</span></li>
- <li>积分:<span>421</span> </li>
- <li>等级: <span style="position:relative;display:inline-block;z-index:1">
- <img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/blog2.html" alt="" style="vertical-align: middle;" id="leveImg">
- <div id="smallTittle" style=" position: absolute; left: -24px; top: 25px; text-align: center; width: 101px; height: 32px; background-color: #fff; line-height: 32px; border: 2px #DDDDDD solid; box-shadow: 0px 2px 2px rgba (0,0,0,0.1); display: none; z-index: 999;">
- <div style="left: 42%; top: -8px; position: absolute; width: 0; height: 0; border-left: 10px solid transparent; border-right: 10px solid transparent; border-bottom: 8px solid #EAEAEA;"></div>
- 积分:421 </div>
- </span> </li>
- <li>排名:<span>千里之外</span></li>
- </ul>
- <ul id="blog_statistics">
- <li>原创:<span>6篇</span></li>
- <li>转载:<span>0篇</span></li>
- <li>译文:<span>0篇</span></li>
- <li>评论:<span>26条</span></li>
- </ul>
- </ul>
- </div>
- <div class="panel" id="panel_Search">
- <ul class="panel_head"><span>文章搜索</span></ul>
- <ul class="panel_body">
- <form id="frmSearch" action="http://so.csdn.net/search" class="form_search" target="_blank">
- <span><input id="inputSearch" class="blogsearch" title="请输入关键字" type="text"></span>
- <input id="btnSubmit" value="搜索" title="search in blog" type="button">
- <input name="q" id="inputQ" type="hidden">
- <input name="t" value="blog" type="hidden">
- <a id="btnSearchBlog" target="_blank"></a>
- </form>
- </ul>
- </div>
- <script type="text/javascript">
- $(function () {
- $("#btnSubmit").click(function () {
- search();
- });
- $("#frmSearch").submit(function () {
- search();
- return false;
- });
- function search()
- {
- var url = "http://so.csdn.net/so/search/s.do?q=" + encodeURIComponent($("#inputSearch").val()) + "&u=" + username + "&t=blog";
- window.location.href = url;
- }
- });
- </script><div id="panel_Category" class="panel">
- <ul class="panel_head"><span>文章分类</span></ul>
- <ul class="panel_body">
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/category/130568" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_wenzhangfenlei']); ">blog小技巧</a><span>(1)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/category/129669" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_wenzhangfenlei']); ">Open Source</a><span>(5)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/category/258171" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_wenzhangfenlei']); ">高性能计算机</a><span>(0)</span>
- </li>
- </ul>
- </div><div id="panel_Archive" class="panel">
- <ul class="panel_head"><span>文章存档</span></ul>
- <ul class="panel_body">
- <div id="archive_list">
- <!--归档统计-->
- <li><a href="http://blog.csdn.net/sirouni2003/article/month/2006/02">2006年02月</a><span>(1)</span></li><li><a href="http://blog.csdn.net/sirouni2003/article/month/2005/06">2005年06月</a><span>(3)</span></li><li><a href="http://blog.csdn.net/sirouni2003/article/month/2004/07">2004年07月</a><span>(2)</span></li>
- </div>
- </ul>
- </div>
- <div id="hotarticls" class="panel">
- <ul class="panel_head">
- <span>
- 阅读排行 </span>
- </ul>
- <ul class="panel_body itemlist">
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/400672" title="GNU Bison 中文手册">GNU Bison 中文手册</a><span>(35149)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/590661" title="GNU Bison 2.1 中文手册">GNU Bison 2.1 中文手册</a><span>(21563)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/33523" title="我的emacs配置文件">我的emacs配置文件</a><span>(2573)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/400507" title="Texi2Html中文输出版">Texi2Html中文输出版</a><span>(2246)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/32388" title="FreeBSD 5.2/GNOME2 中文化">FreeBSD 5.2/GNOME2 中文化</a><span>(1399)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/398864" title="适用于你的blog的一些天气预报提供者">适用于你的blog的一些天气预报提供者</a><span>(1074)</span>
- </li>
- </ul>
- </div>
- <div id="hotarticls2" class="panel">
- <ul class="panel_head"><span>评论排行</span></ul>
- <ul class="panel_body itemlist">
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/400672" title="GNU Bison 中文手册">GNU Bison 中文手册</a><span>(14)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/590661" title="GNU Bison 2.1 中文手册">GNU Bison 2.1 中文手册</a><span>(6)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/33523" title="我的emacs配置文件">我的emacs配置文件</a><span>(4)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/400507" title="Texi2Html中文输出版">Texi2Html中文输出版</a><span>(2)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/32388" title="FreeBSD 5.2/GNOME2 中文化">FreeBSD 5.2/GNOME2 中文化</a><span>(0)</span>
- </li>
- <li>
- <a href="http://blog.csdn.net/sirouni2003/article/details/398864" title="适用于你的blog的一些天气预报提供者">适用于你的blog的一些天气预报提供者</a><span>(0)</span>
- </li>
- </ul>
- </div>
- <div id="homepageArticles" class="panel tracking-ad" data-mod="popu_4">
- <ul class="panel_head"><span>推荐文章</span></ul>
- <ul class="panel_body" id="ad_commend"><iframe src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ad_002.html" style="border-width: 0px; overflow: hidden; width: 182px; height: 269px;" id="ad_frm_1" scrolling="no" frameborder="0"></iframe></ul>
- </div>
- <script type="text/javascript">
- new Ad(12, 'ad_commend');
- </script><div id="newcomments" class="panel">
- <ul class="panel_head"><span>最新评论</span></ul>
- <ul class="panel_body itemlist">
- <li>
-
- <a href="http://blog.csdn.net/sirouni2003/article/details/400672#comments">GNU Bison 中文手册</a>
- <p style="margin:0px;"><a href="http://blog.csdn.net/imcg_cg" class="user_name">imcg_cg</a>:
- 帮助非常大,谢谢!
- </p>
- </li>
- <li>
-
- <a href="http://blog.csdn.net/sirouni2003/article/details/590661#comments">GNU Bison 2.1 中文手册</a>
- <p style="margin:0px;"><a href="http://blog.csdn.net/crazyman_hw" class="user_name">crazyman_hw</a>:
- 中文下载不了了,很可惜
- </p>
- </li>
- <li>
-
- <a href="http://blog.csdn.net/sirouni2003/article/details/590661#comments">GNU Bison 2.1 中文手册</a>
- <p style="margin:0px;"><a href="http://blog.csdn.net/caiya_" class="user_name">caiya_</a>:
- 很好的啊
- </p>
- </li>
- <li>
-
- <a href="http://blog.csdn.net/sirouni2003/article/details/33523#comments">我的emacs配置文件</a>
- <p style="margin:0px;"><a href="http://blog.csdn.net/%E5%8C%BF%E5%90%8D%E7%94%A8%E6%88%B7" class="user_name">匿名用户</a>:
- 回复 startcode:像你的情况你可以设置%HOME%环境变量为d:,然后把.emacs或者_e...
- </p>
- </li>
- <li>
-
- <a href="http://blog.csdn.net/sirouni2003/article/details/33523#comments">GNU Bison 2.1 中文手册</a>
- <p style="margin:0px;"><a href="http://blog.csdn.net/powerkoria" class="user_name">powerkoria</a>:
- 3.5.5
- stmt: LET '(' var ')'
- { $...
- </p>
- </li>
- <li>
-
- <a href="http://blog.csdn.net/sirouni2003/article/details/33523#comments">GNU Bison 2.1 中文手册</a>
- <p style="margin:0px;"><a href="http://blog.csdn.net/powerkoria" class="user_name">powerkoria</a>:
- 3.5.3节版书错误
- Here is a typical example:
- exp: ...
- </p>
- </li>
- <li>
-
- <a href="http://blog.csdn.net/sirouni2003/article/details/33523#comments">GNU Bison 中文手册</a>
- <p style="margin:0px;"><a href="http://blog.csdn.net/dychenyi" class="user_name">dychenyi</a>:
- 要有出版社出版发行一下就好了
- </p>
- </li>
- <li>
-
- <a href="http://blog.csdn.net/sirouni2003/article/details/33523#comments">GNU Bison 中文手册</a>
- <p style="margin:0px;"><a href="http://blog.csdn.net/gengyong" class="user_name">gengyong</a>:
- 太好了, 感激得一塌糊涂!
- </p>
- </li>
- <li>
-
- <a href="http://blog.csdn.net/sirouni2003/article/details/33523#comments">GNU Bison 2.1 中文手册</a>
- <p style="margin:0px;"><a href="http://blog.csdn.net/lilo_x" class="user_name">lilo_x</a>:
- 好!
- </p>
- </li>
- <li>
-
- <a href="http://blog.csdn.net/sirouni2003/article/details/400507#comments">Texi2Html中文输出版</a>
- <p style="margin:0px;"><a href="http://blog.csdn.net/sirouni2003" class="user_name">sirouni2003</a>:
- 谢谢eric发现的问题,已经解决,请重新尝试.
- </p>
- </li>
- </ul>
- </div>
- <div id="custom_column_940932" class="panel">
- <ul class="panel_head"><span>FreeBSD</span></ul>
- <ul class="panel_body">
- <ul><li><a href="http://www.freebsd.org/" target="_blank">FreeBSD 官方网站</a></li><li><a href="http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/index.html" target="_blank">FreeBSD HandBooK</a></li><li><a href="http://gerda.univie.ac.at/freebsd-laptops/index.pl" target="_blank">FreeBSD 笔记本电脑 Kernel Config</a></li></ul>
- </ul>
- </div>
- <div id="custom_column_940933" class="panel">
- <ul class="panel_head"><span>GNU</span></ul>
- <ul class="panel_body">
- <ul><li><a href="http://www.gnu.org/" target="_blank">GNU官方</a></li><li><a href="https://savannah.gnu.org/" target="_blank">savannah</a></li></ul>
- </ul>
- </div>
- <div id="custom_column_940934" class="panel">
- <ul class="panel_head"><span>友情链接</span></ul>
- <ul class="panel_body">
- <ul><li><a href="http://mhss.nease.net/" target="_blank">寒蝉退士</a></li><li><a href="http://sirouni.photo.163.com/" target="_blank">照片中杭州</a></li><li><a href="http://blog.sina.com.cn/u/1247187410" target="_blank">丰潭路口</a></li></ul>
- </ul>
- </div> </div>
- <div class="clear">
- </div>
- </div>
- <div class="clear">
- </div>
- </div>
-
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/cnick.html"></script>
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/newblog.js"></script>
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/showblogmedal.js"></script>
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/JavaScript1.js"></script><link rel="stylesheet" type="text/css" href="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/pub_footer_2014.html"><div class="pub_fo"><div id="pub_footerall" class="pub_footer_new"><dl><dt></dt> <dd class="foot_sub_menu"><a href="http://www.csdn.net/company/about.html" target="_blank">公司简介</a><span>|</span><a href="http://www.csdn.net/company/recruit.html" target="_blank">招贤纳士</a><span>|</span><a href="http://www.csdn.net/company/marketing.html" target="_blank">广告服务</a><span>|</span><a href="http://www.csdn.net/company/account.html" target="_blank">银行汇款帐号</a><span>|</span><a href="http://www.csdn.net/company/contact.html" target="_blank">联系方式</a><span>|</span><a href="http://www.csdn.net/company/statement.html" target="_blank">版权声明</a><span>|</span><a href="http://www.csdn.net/company/layer.html" target="_blank">法律顾问</a><span>|</span><a href="mailto:webmaster@csdn.net">问题报告</a><span>|</span><a target="_blank" href="http://www.csdn.net/friendlink.html">合作伙伴</a><span>|</span><a href="http://bbs.csdn.net/forums/Service" target="_blank">论坛反馈</a></dd><dd class="foot_contact"><a href="http://wpa.qq.com/msgrd?v=3&uin=2355263776&site=qq&menu=yes" target="_blank" class="qq">网站客服</a><a href="http://wpa.qq.com/msgrd?v=3&uin=2251809102&site=qq&menu=yes" target="_blank" class="qq">杂志客服</a><a href="http://e.weibo.com/csdnsupport/profile" target="_blank" class="weibo">微博客服</a><a href="mailto:webmaster@csdn.net" class="email" title="联系邮箱">webmaster@csdn.net</a><span class="phone" title="服务热线">400-600-2320</span><span class="interval">|</span><span>北京创新乐知信息技术有限公司 版权所有</span><span class="interval">|</span><span>江苏乐知网络技术有限公司 提供商务支持</span></dd><dd class="foot_copyright"><span>京 ICP 证 070598 号</span><span class="interval">|</span><span>Copyright © 1999-2014, CSDN.NET, All Rights Reserved </span><a href="http://www.hd315.gov.cn/beian/view.asp?bianhao=010202001032100010" target="_blank"><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/gongshang_logos.html" alt="GongshangLogo" title=""></a></dd></dl></div></div><script id="noticeScript" type="text/javascript" btnid="header_notice_num" wrapid="note1" count="5" subcount="5" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/notify.html"></script>
- <script type="text/javascript">document.write("<img src=http://counter.csdn.net/pv.aspx?id=24 border=0 width=0 height=0>");</script><img src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/pv.asc" border="0" width="0" height="0">
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/counter.js"></script><script type="text/javascript" charset="UTF-8" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/msg.js"></script>
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ad-blog.js"></script><script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ad-ms1459.js"></script>
- <script type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ad-ms1462_2.js"></script>
- <script type="text/javascript">
- $(function () {
- function __get_code_toolbar(snippet_id) {
- return $("<a href='https://code.csdn.net/snippets/"
- + snippet_id
- + "' target='_blank' title='在CODE上查看代码片' style='text-indent:0;'><img src='https://code.csdn.net/assets/CODE_ico.png' width=12 height=12 alt='在CODE上查看代码片' style='position:relative;top:1px;left:2px;'/></a>"
- + "<a href='https://code.csdn.net/snippets/"
- + snippet_id
- + "/fork' target='_blank' title='派生到我的代码片' style='text-indent:0;'><img src='https://code.csdn.net/assets/ico_fork.svg' width=12 height=12 alt='派生到我的代码片' style='position:relative;top:2px;left:2px;'/></a>");
- }
-
- $("[code_snippet_id]").each(function () {
- __s_id = $(this).attr("code_snippet_id");
- if (__s_id != null && __s_id != "" && __s_id != 0 && parseInt(__s_id) > 70020) {
- __code_tool = __get_code_toolbar(__s_id);
- $(this).prev().find(".tools").append(__code_tool);
- }
- });
- });
- </script>
- </div>
- <!--new top-->
-
- <script id="csdn-toolbar-id" btnid="header_notice_num" wrapid="note1" count="5" subcount="5" type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/toolbar.js"></script>
- <!--new top-->
-
- <link href="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ask_float_block.html" type="text/css" rel="stylesheet">
- <script language="JavaScript" type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/wmd.html"></script>
- <script language="JavaScript" type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/showdown.html"></script>
- <script language="JavaScript" type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/prettify.html"></script>
- <script language="JavaScript" type="text/javascript" src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/ask_float_block_002.html"></script>
-
-
- <iframe src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/log.swf" style="width: 1px; height: 1px; position: absolute; visibility: hidden;"></iframe><iframe src="GNU%20Bison%20%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C%20-%20Naga%20Bank%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET_files/log_002.swf" style="width: 1px; height: 1px; position: absolute; visibility: hidden;"></iframe></body></html>
|