1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429 |
- /*
- * Copyright 2005-2007 Adrian Thurston <thurston@complang.org>
- */
- /* This file is part of Ragel.
- *
- * Ragel 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.
- *
- * Ragel 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 Ragel; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include "ragel.h"
- #include "xmlcodegen.h"
- #include "parsedata.h"
- #include "fsmgraph.h"
- #include "gendata.h"
- #include "inputdata.h"
- #include <string.h>
- #include "rlparse.h"
- #include "version.h"
- using namespace std;
- GenBase::GenBase( char *fsmName, ParseData *pd, FsmAp *fsm )
- :
- fsmName(fsmName),
- pd(pd),
- fsm(fsm),
- nextActionTableId(0)
- {
- }
- void GenBase::appendTrans( TransListVect &outList, Key lowKey,
- Key highKey, TransAp *trans )
- {
- if ( trans->toState != 0 || trans->actionTable.length() > 0 )
- outList.append( TransEl( lowKey, highKey, trans ) );
- }
- void GenBase::reduceActionTables()
- {
- /* Reduce the actions tables to a set. */
- for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
- RedActionTable *actionTable = 0;
- /* Reduce To State Actions. */
- if ( st->toStateActionTable.length() > 0 ) {
- if ( actionTableMap.insert( st->toStateActionTable, &actionTable ) )
- actionTable->id = nextActionTableId++;
- }
- /* Reduce From State Actions. */
- if ( st->fromStateActionTable.length() > 0 ) {
- if ( actionTableMap.insert( st->fromStateActionTable, &actionTable ) )
- actionTable->id = nextActionTableId++;
- }
- /* Reduce EOF actions. */
- if ( st->eofActionTable.length() > 0 ) {
- if ( actionTableMap.insert( st->eofActionTable, &actionTable ) )
- actionTable->id = nextActionTableId++;
- }
- /* Loop the transitions and reduce their actions. */
- for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) {
- if ( trans->actionTable.length() > 0 ) {
- if ( actionTableMap.insert( trans->actionTable, &actionTable ) )
- actionTable->id = nextActionTableId++;
- }
- }
- }
- }
- XMLCodeGen::XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm, std::ostream &out )
- :
- GenBase(fsmName, pd, fsm),
- out(out)
- {
- }
- void XMLCodeGen::writeActionList()
- {
- /* Determine which actions to write. */
- int nextActionId = 0;
- for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
- if ( act->numRefs() > 0 || act->numCondRefs > 0 )
- act->actionId = nextActionId++;
- }
- /* Write the list. */
- out << " <action_list length=\"" << nextActionId << "\">\n";
- for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
- if ( act->actionId >= 0 )
- writeAction( act );
- }
- out << " </action_list>\n";
- }
- void XMLCodeGen::writeActionTableList()
- {
- /* Must first order the action tables based on their id. */
- int numTables = nextActionTableId;
- RedActionTable **tables = new RedActionTable*[numTables];
- for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
- tables[at->id] = at;
- out << " <action_table_list length=\"" << numTables << "\">\n";
- for ( int t = 0; t < numTables; t++ ) {
- out << " <action_table id=\"" << t << "\" length=\"" <<
- tables[t]->key.length() << "\">";
- for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
- out << atel->value->actionId;
- if ( ! atel.last() )
- out << " ";
- }
- out << "</action_table>\n";
- }
- out << " </action_table_list>\n";
- delete[] tables;
- }
- void XMLCodeGen::writeKey( Key key )
- {
- if ( keyOps->isSigned )
- out << key.getVal();
- else
- out << (unsigned long) key.getVal();
- }
- void XMLCodeGen::writeTrans( Key lowKey, Key highKey, TransAp *trans )
- {
- /* First reduce the action. */
- RedActionTable *actionTable = 0;
- if ( trans->actionTable.length() > 0 )
- actionTable = actionTableMap.find( trans->actionTable );
- /* Write the transition. */
- out << " <t>";
- writeKey( lowKey );
- out << " ";
- writeKey( highKey );
- if ( trans->toState != 0 )
- out << " " << trans->toState->alg.stateNum;
- else
- out << " x";
- if ( actionTable != 0 )
- out << " " << actionTable->id;
- else
- out << " x";
- out << "</t>\n";
- }
- void XMLCodeGen::writeTransList( StateAp *state )
- {
- TransListVect outList;
- /* If there is only are no ranges the task is simple. */
- if ( state->outList.length() > 0 ) {
- /* Loop each source range. */
- for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
- /* Reduce the transition. If it reduced to anything then add it. */
- appendTrans( outList, trans->lowKey, trans->highKey, trans );
- }
- }
- out << " <trans_list length=\"" << outList.length() << "\">\n";
- for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
- writeTrans( tvi->lowKey, tvi->highKey, tvi->value );
- out << " </trans_list>\n";
- }
- void XMLCodeGen::writeEofTrans( StateAp *state )
- {
- RedActionTable *eofActions = 0;
- if ( state->eofActionTable.length() > 0 )
- eofActions = actionTableMap.find( state->eofActionTable );
-
- /* The <eof_t> is used when there is an eof target, otherwise the eof
- * action goes into state actions. */
- if ( state->eofTarget != 0 ) {
- out << " <eof_t>" << state->eofTarget->alg.stateNum;
- if ( eofActions != 0 )
- out << " " << eofActions->id;
- else
- out << " x";
- out << "</eof_t>" << endl;
- }
- }
- void XMLCodeGen::writeText( InlineItem *item )
- {
- if ( item->prev == 0 || item->prev->type != InlineItem::Text )
- out << "<text>";
- xmlEscapeHost( out, item->data, strlen(item->data) );
- if ( item->next == 0 || item->next->type != InlineItem::Text )
- out << "</text>";
- }
- void XMLCodeGen::writeGoto( InlineItem *item )
- {
- if ( pd->generatingSectionSubset )
- out << "<goto>-1</goto>";
- else {
- EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
- out << "<goto>" << targ->value->alg.stateNum << "</goto>";
- }
- }
- void XMLCodeGen::writeCall( InlineItem *item )
- {
- if ( pd->generatingSectionSubset )
- out << "<call>-1</call>";
- else {
- EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
- out << "<call>" << targ->value->alg.stateNum << "</call>";
- }
- }
- void XMLCodeGen::writeNext( InlineItem *item )
- {
- if ( pd->generatingSectionSubset )
- out << "<next>-1</next>";
- else {
- EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
- out << "<next>" << targ->value->alg.stateNum << "</next>";
- }
- }
- void XMLCodeGen::writeGotoExpr( InlineItem *item )
- {
- out << "<goto_expr>";
- writeInlineList( item->children );
- out << "</goto_expr>";
- }
- void XMLCodeGen::writeCallExpr( InlineItem *item )
- {
- out << "<call_expr>";
- writeInlineList( item->children );
- out << "</call_expr>";
- }
- void XMLCodeGen::writeNextExpr( InlineItem *item )
- {
- out << "<next_expr>";
- writeInlineList( item->children );
- out << "</next_expr>";
- }
- void XMLCodeGen::writeEntry( InlineItem *item )
- {
- if ( pd->generatingSectionSubset )
- out << "<entry>-1</entry>";
- else {
- EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
- out << "<entry>" << targ->value->alg.stateNum << "</entry>";
- }
- }
- void XMLCodeGen::writeActionExec( InlineItem *item )
- {
- out << "<exec>";
- writeInlineList( item->children );
- out << "</exec>";
- }
- void XMLCodeGen::writeLmOnLast( InlineItem *item )
- {
- out << "<set_tokend>1</set_tokend>";
- if ( item->longestMatchPart->action != 0 ) {
- out << "<sub_action>";
- writeInlineList( item->longestMatchPart->action->inlineList );
- out << "</sub_action>";
- }
- }
- void XMLCodeGen::writeLmOnNext( InlineItem *item )
- {
- out << "<set_tokend>0</set_tokend>";
- out << "<hold></hold>";
- if ( item->longestMatchPart->action != 0 ) {
- out << "<sub_action>";
- writeInlineList( item->longestMatchPart->action->inlineList );
- out << "</sub_action>";
- }
- }
- void XMLCodeGen::writeLmOnLagBehind( InlineItem *item )
- {
- out << "<exec><get_tokend></get_tokend></exec>";
- if ( item->longestMatchPart->action != 0 ) {
- out << "<sub_action>";
- writeInlineList( item->longestMatchPart->action->inlineList );
- out << "</sub_action>";
- }
- }
- void XMLCodeGen::writeLmSwitch( InlineItem *item )
- {
- LongestMatch *longestMatch = item->longestMatch;
- out << "<lm_switch>\n";
- /* We can't put the <exec> here because we may need to handle the error
- * case and in that case p should not be changed. Instead use a default
- * label in the switch to adjust p when user actions are not set. An id of
- * -1 indicates the default. */
- if ( longestMatch->lmSwitchHandlesError ) {
- /* If the switch handles error then we should have also forced the
- * error state. */
- assert( fsm->errState != 0 );
- out << " <sub_action id=\"0\">";
- out << "<goto>" << fsm->errState->alg.stateNum << "</goto>";
- out << "</sub_action>\n";
- }
-
- bool needDefault = false;
- for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
- if ( lmi->inLmSelect ) {
- if ( lmi->action == 0 )
- needDefault = true;
- else {
- /* Open the action. Write it with the context that sets up _p
- * when doing control flow changes from inside the machine. */
- out << " <sub_action id=\"" << lmi->longestMatchId << "\">";
- out << "<exec><get_tokend></get_tokend></exec>";
- writeInlineList( lmi->action->inlineList );
- out << "</sub_action>\n";
- }
- }
- }
- if ( needDefault ) {
- out << " <sub_action id=\"-1\"><exec><get_tokend>"
- "</get_tokend></exec></sub_action>\n";
- }
- out << " </lm_switch>";
- }
- void XMLCodeGen::writeInlineList( InlineList *inlineList )
- {
- for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
- switch ( item->type ) {
- case InlineItem::Text:
- writeText( item );
- break;
- case InlineItem::Goto:
- writeGoto( item );
- break;
- case InlineItem::GotoExpr:
- writeGotoExpr( item );
- break;
- case InlineItem::Call:
- writeCall( item );
- break;
- case InlineItem::CallExpr:
- writeCallExpr( item );
- break;
- case InlineItem::Next:
- writeNext( item );
- break;
- case InlineItem::NextExpr:
- writeNextExpr( item );
- break;
- case InlineItem::Break:
- out << "<break></break>";
- break;
- case InlineItem::Ret:
- out << "<ret></ret>";
- break;
- case InlineItem::PChar:
- out << "<pchar></pchar>";
- break;
- case InlineItem::Char:
- out << "<char></char>";
- break;
- case InlineItem::Curs:
- out << "<curs></curs>";
- break;
- case InlineItem::Targs:
- out << "<targs></targs>";
- break;
- case InlineItem::Entry:
- writeEntry( item );
- break;
- case InlineItem::Hold:
- out << "<hold></hold>";
- break;
- case InlineItem::Exec:
- writeActionExec( item );
- break;
- case InlineItem::LmSetActId:
- out << "<set_act>" <<
- item->longestMatchPart->longestMatchId <<
- "</set_act>";
- break;
- case InlineItem::LmSetTokEnd:
- out << "<set_tokend>1</set_tokend>";
- break;
- case InlineItem::LmOnLast:
- writeLmOnLast( item );
- break;
- case InlineItem::LmOnNext:
- writeLmOnNext( item );
- break;
- case InlineItem::LmOnLagBehind:
- writeLmOnLagBehind( item );
- break;
- case InlineItem::LmSwitch:
- writeLmSwitch( item );
- break;
- case InlineItem::LmInitAct:
- out << "<init_act></init_act>";
- break;
- case InlineItem::LmInitTokStart:
- out << "<init_tokstart></init_tokstart>";
- break;
- case InlineItem::LmSetTokStart:
- out << "<set_tokstart></set_tokstart>";
- break;
- }
- }
- }
- BackendGen::BackendGen( char *fsmName, ParseData *pd, FsmAp *fsm, CodeGenData *cgd )
- :
- GenBase(fsmName, pd, fsm),
- cgd(cgd)
- {
- }
- void BackendGen::makeText( GenInlineList *outList, InlineItem *item )
- {
- GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Text );
- inlineItem->data = item->data;
- outList->append( inlineItem );
- }
- void BackendGen::makeTargetItem( GenInlineList *outList, NameInst *nameTarg,
- GenInlineItem::Type type )
- {
- long targetState;
- if ( pd->generatingSectionSubset )
- targetState = -1;
- else {
- EntryMapEl *targ = fsm->entryPoints.find( nameTarg->id );
- targetState = targ->value->alg.stateNum;
- }
- /* Make the item. */
- GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), type );
- inlineItem->targId = targetState;
- outList->append( inlineItem );
- }
- /* Make a sublist item with a given type. */
- void BackendGen::makeSubList( GenInlineList *outList,
- InlineList *inlineList, GenInlineItem::Type type )
- {
- /* Fill the sub list. */
- GenInlineList *subList = new GenInlineList;
- makeGenInlineList( subList, inlineList );
- /* Make the item. */
- GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), type );
- inlineItem->children = subList;
- outList->append( inlineItem );
- }
- void BackendGen::makeLmOnLast( GenInlineList *outList, InlineItem *item )
- {
- makeSetTokend( outList, 1 );
- if ( item->longestMatchPart->action != 0 ) {
- makeSubList( outList,
- item->longestMatchPart->action->inlineList,
- GenInlineItem::SubAction );
- }
- }
- void BackendGen::makeLmOnNext( GenInlineList *outList, InlineItem *item )
- {
- makeSetTokend( outList, 0 );
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold ) );
- if ( item->longestMatchPart->action != 0 ) {
- makeSubList( outList,
- item->longestMatchPart->action->inlineList,
- GenInlineItem::SubAction );
- }
- }
- void BackendGen::makeExecGetTokend( GenInlineList *outList )
- {
- /* Make the Exec item. */
- GenInlineItem *execItem = new GenInlineItem( InputLoc(), GenInlineItem::Exec );
- execItem->children = new GenInlineList;
- /* Make the GetTokEnd */
- GenInlineItem *getTokend = new GenInlineItem( InputLoc(), GenInlineItem::LmGetTokEnd );
- execItem->children->append( getTokend );
- outList->append( execItem );
- }
- void BackendGen::makeLmOnLagBehind( GenInlineList *outList, InlineItem *item )
- {
- /* Jump to the tokend. */
- makeExecGetTokend( outList );
- if ( item->longestMatchPart->action != 0 ) {
- makeSubList( outList,
- item->longestMatchPart->action->inlineList,
- GenInlineItem::SubAction );
- }
- }
- void BackendGen::makeLmSwitch( GenInlineList *outList, InlineItem *item )
- {
- GenInlineItem *lmSwitch = new GenInlineItem( InputLoc(), GenInlineItem::LmSwitch );
- GenInlineList *lmList = lmSwitch->children = new GenInlineList;
- LongestMatch *longestMatch = item->longestMatch;
- /* We can't put the <exec> here because we may need to handle the error
- * case and in that case p should not be changed. Instead use a default
- * label in the switch to adjust p when user actions are not set. An id of
- * -1 indicates the default. */
- if ( longestMatch->lmSwitchHandlesError ) {
- /* If the switch handles error then we should have also forced the
- * error state. */
- assert( fsm->errState != 0 );
- GenInlineItem *errCase = new GenInlineItem( InputLoc(), GenInlineItem::SubAction );
- errCase->lmId = 0;
- errCase->children = new GenInlineList;
- /* Make the item. */
- GenInlineItem *gotoItem = new GenInlineItem( InputLoc(), GenInlineItem::Goto );
- gotoItem->targId = fsm->errState->alg.stateNum;
- errCase->children->append( gotoItem );
- lmList->append( errCase );
- }
-
- bool needDefault = false;
- for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
- if ( lmi->inLmSelect ) {
- if ( lmi->action == 0 )
- needDefault = true;
- else {
- /* Open the action. Write it with the context that sets up _p
- * when doing control flow changes from inside the machine. */
- GenInlineItem *lmCase = new GenInlineItem( InputLoc(),
- GenInlineItem::SubAction );
- lmCase->lmId = lmi->longestMatchId;
- lmCase->children = new GenInlineList;
- makeExecGetTokend( lmCase->children );
- makeGenInlineList( lmCase->children, lmi->action->inlineList );
- lmList->append( lmCase );
- }
- }
- }
- if ( needDefault ) {
- GenInlineItem *defCase = new GenInlineItem( InputLoc(),
- GenInlineItem::SubAction );
- defCase->lmId = -1;
- defCase->children = new GenInlineList;
- makeExecGetTokend( defCase->children );
- lmList->append( defCase );
- }
- outList->append( lmSwitch );
- }
- void BackendGen::makeSetTokend( GenInlineList *outList, long offset )
- {
- GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokEnd );
- inlineItem->offset = offset;
- outList->append( inlineItem );
- }
- void BackendGen::makeSetAct( GenInlineList *outList, long lmId )
- {
- GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetActId );
- inlineItem->lmId = lmId;
- outList->append( inlineItem );
- }
- void BackendGen::makeGenInlineList( GenInlineList *outList, InlineList *inList )
- {
- for ( InlineList::Iter item = *inList; item.lte(); item++ ) {
- switch ( item->type ) {
- case InlineItem::Text:
- makeText( outList, item );
- break;
- case InlineItem::Goto:
- makeTargetItem( outList, item->nameTarg, GenInlineItem::Goto );
- break;
- case InlineItem::GotoExpr:
- makeSubList( outList, item->children, GenInlineItem::GotoExpr );
- break;
- case InlineItem::Call:
- makeTargetItem( outList, item->nameTarg, GenInlineItem::Call );
- break;
- case InlineItem::CallExpr:
- makeSubList( outList, item->children, GenInlineItem::CallExpr );
- break;
- case InlineItem::Next:
- makeTargetItem( outList, item->nameTarg, GenInlineItem::Next );
- break;
- case InlineItem::NextExpr:
- makeSubList( outList, item->children, GenInlineItem::NextExpr );
- break;
- case InlineItem::Break:
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Break ) );
- break;
- case InlineItem::Ret:
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Ret ) );
- break;
- case InlineItem::PChar:
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::PChar ) );
- break;
- case InlineItem::Char:
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Char ) );
- break;
- case InlineItem::Curs:
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Curs ) );
- break;
- case InlineItem::Targs:
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Targs ) );
- break;
- case InlineItem::Entry:
- makeTargetItem( outList, item->nameTarg, GenInlineItem::Entry );
- break;
- case InlineItem::Hold:
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold ) );
- break;
- case InlineItem::Exec:
- makeSubList( outList, item->children, GenInlineItem::Exec );
- break;
- case InlineItem::LmSetActId:
- makeSetAct( outList, item->longestMatchPart->longestMatchId );
- break;
- case InlineItem::LmSetTokEnd:
- makeSetTokend( outList, 1 );
- break;
- case InlineItem::LmOnLast:
- makeLmOnLast( outList, item );
- break;
- case InlineItem::LmOnNext:
- makeLmOnNext( outList, item );
- break;
- case InlineItem::LmOnLagBehind:
- makeLmOnLagBehind( outList, item );
- break;
- case InlineItem::LmSwitch:
- makeLmSwitch( outList, item );
- break;
- case InlineItem::LmInitAct:
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitAct ) );
- break;
- case InlineItem::LmInitTokStart:
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitTokStart ) );
- break;
- case InlineItem::LmSetTokStart:
- outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokStart ) );
- cgd->hasLongestMatch = true;
- break;
- }
- }
- }
- void XMLCodeGen::writeAction( Action *action )
- {
- out << " <action id=\"" << action->actionId << "\"";
- if ( action->name != 0 )
- out << " name=\"" << action->name << "\"";
- out << " line=\"" << action->loc.line << "\" col=\"" << action->loc.col << "\">";
- writeInlineList( action->inlineList );
- out << "</action>\n";
- }
- void xmlEscapeHost( std::ostream &out, char *data, long len )
- {
- char *end = data + len;
- while ( data != end ) {
- switch ( *data ) {
- case '<': out << "<"; break;
- case '>': out << ">"; break;
- case '&': out << "&"; break;
- default: out << *data; break;
- }
- data += 1;
- }
- }
- void XMLCodeGen::writeStateActions( StateAp *state )
- {
- RedActionTable *toStateActions = 0;
- if ( state->toStateActionTable.length() > 0 )
- toStateActions = actionTableMap.find( state->toStateActionTable );
- RedActionTable *fromStateActions = 0;
- if ( state->fromStateActionTable.length() > 0 )
- fromStateActions = actionTableMap.find( state->fromStateActionTable );
- /* EOF actions go out here only if the state has no eof target. If it has
- * an eof target then an eof transition will be used instead. */
- RedActionTable *eofActions = 0;
- if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
- eofActions = actionTableMap.find( state->eofActionTable );
-
- if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
- out << " <state_actions>";
- if ( toStateActions != 0 )
- out << toStateActions->id;
- else
- out << "x";
- if ( fromStateActions != 0 )
- out << " " << fromStateActions->id;
- else
- out << " x";
- if ( eofActions != 0 )
- out << " " << eofActions->id;
- else
- out << " x";
- out << "</state_actions>\n";
- }
- }
- void XMLCodeGen::writeStateConditions( StateAp *state )
- {
- if ( state->stateCondList.length() > 0 ) {
- out << " <cond_list length=\"" << state->stateCondList.length() << "\">\n";
- for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
- out << " <c>";
- writeKey( scdi->lowKey );
- out << " ";
- writeKey( scdi->highKey );
- out << " ";
- out << scdi->condSpace->condSpaceId;
- out << "</c>\n";
- }
- out << " </cond_list>\n";
- }
- }
- void XMLCodeGen::writeStateList()
- {
- /* Write the list of states. */
- out << " <state_list length=\"" << fsm->stateList.length() << "\">\n";
- for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
- out << " <state id=\"" << st->alg.stateNum << "\"";
- if ( st->isFinState() )
- out << " final=\"t\"";
- out << ">\n";
- writeStateActions( st );
- writeEofTrans( st );
- writeStateConditions( st );
- writeTransList( st );
- out << " </state>\n";
- if ( !st.last() )
- out << "\n";
- }
- out << " </state_list>\n";
- }
- bool XMLCodeGen::writeNameInst( NameInst *nameInst )
- {
- bool written = false;
- if ( nameInst->parent != 0 )
- written = writeNameInst( nameInst->parent );
-
- if ( nameInst->name != 0 ) {
- if ( written )
- out << '_';
- out << nameInst->name;
- written = true;
- }
- return written;
- }
- void XMLCodeGen::writeEntryPoints()
- {
- /* List of entry points other than start state. */
- if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
- out << " <entry_points";
- if ( pd->lmRequiresErrorState )
- out << " error=\"t\"";
- out << ">\n";
- for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
- /* Get the name instantiation from nameIndex. */
- NameInst *nameInst = pd->nameIndex[en->key];
- StateAp *state = en->value;
- out << " <entry name=\"";
- writeNameInst( nameInst );
- out << "\">" << state->alg.stateNum << "</entry>\n";
- }
- out << " </entry_points>\n";
- }
- }
- void XMLCodeGen::writeMachine()
- {
- /* Open the machine. */
- out << " <machine>\n";
-
- /* Action tables. */
- reduceActionTables();
- writeActionList();
- writeActionTableList();
- writeConditions();
- /* Start state. */
- out << " <start_state>" << fsm->startState->alg.stateNum <<
- "</start_state>\n";
-
- /* Error state. */
- if ( fsm->errState != 0 ) {
- out << " <error_state>" << fsm->errState->alg.stateNum <<
- "</error_state>\n";
- }
- writeEntryPoints();
- writeStateList();
- out << " </machine>\n";
- }
- void XMLCodeGen::writeConditions()
- {
- if ( condData->condSpaceMap.length() > 0 ) {
- long nextCondSpaceId = 0;
- for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
- cs->condSpaceId = nextCondSpaceId++;
- out << " <cond_space_list length=\"" << condData->condSpaceMap.length() << "\">\n";
- for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
- out << " <cond_space id=\"" << cs->condSpaceId <<
- "\" length=\"" << cs->condSet.length() << "\">";
- writeKey( cs->baseKey );
- for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
- out << " " << (*csi)->actionId;
- out << "</cond_space>\n";
- }
- out << " </cond_space_list>\n";
- }
- }
- void XMLCodeGen::writeExports()
- {
- if ( pd->exportList.length() > 0 ) {
- out << " <exports>\n";
- for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ ) {
- out << " <ex name=\"" << exp->name << "\">";
- writeKey( exp->key );
- out << "</ex>\n";
- }
- out << " </exports>\n";
- }
- }
- void XMLCodeGen::writeXML()
- {
- /* Open the definition. */
- out << "<ragel_def name=\"" << fsmName << "\">\n";
- /* Alphabet type. */
- out << " <alphtype>" << keyOps->alphType->internalName << "</alphtype>\n";
-
- /* Getkey expression. */
- if ( pd->getKeyExpr != 0 ) {
- out << " <getkey>";
- writeInlineList( pd->getKeyExpr );
- out << "</getkey>\n";
- }
- /* Access expression. */
- if ( pd->accessExpr != 0 ) {
- out << " <access>";
- writeInlineList( pd->accessExpr );
- out << "</access>\n";
- }
- /* PrePush expression. */
- if ( pd->prePushExpr != 0 ) {
- out << " <prepush>";
- writeInlineList( pd->prePushExpr );
- out << "</prepush>\n";
- }
- /* PostPop expression. */
- if ( pd->postPopExpr != 0 ) {
- out << " <postpop>";
- writeInlineList( pd->postPopExpr );
- out << "</postpop>\n";
- }
- /*
- * Variable expressions.
- */
- if ( pd->pExpr != 0 ) {
- out << " <p_expr>";
- writeInlineList( pd->pExpr );
- out << "</p_expr>\n";
- }
-
- if ( pd->peExpr != 0 ) {
- out << " <pe_expr>";
- writeInlineList( pd->peExpr );
- out << "</pe_expr>\n";
- }
- if ( pd->eofExpr != 0 ) {
- out << " <eof_expr>";
- writeInlineList( pd->eofExpr );
- out << "</eof_expr>\n";
- }
-
- if ( pd->csExpr != 0 ) {
- out << " <cs_expr>";
- writeInlineList( pd->csExpr );
- out << "</cs_expr>\n";
- }
-
- if ( pd->topExpr != 0 ) {
- out << " <top_expr>";
- writeInlineList( pd->topExpr );
- out << "</top_expr>\n";
- }
-
- if ( pd->stackExpr != 0 ) {
- out << " <stack_expr>";
- writeInlineList( pd->stackExpr );
- out << "</stack_expr>\n";
- }
-
- if ( pd->actExpr != 0 ) {
- out << " <act_expr>";
- writeInlineList( pd->actExpr );
- out << "</act_expr>\n";
- }
-
- if ( pd->tokstartExpr != 0 ) {
- out << " <tokstart_expr>";
- writeInlineList( pd->tokstartExpr );
- out << "</tokstart_expr>\n";
- }
-
- if ( pd->tokendExpr != 0 ) {
- out << " <tokend_expr>";
- writeInlineList( pd->tokendExpr );
- out << "</tokend_expr>\n";
- }
-
- if ( pd->dataExpr != 0 ) {
- out << " <data_expr>";
- writeInlineList( pd->dataExpr );
- out << "</data_expr>\n";
- }
-
- writeExports();
-
- writeMachine();
- out <<
- "</ragel_def>\n";
- }
- void BackendGen::makeExports()
- {
- for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ )
- cgd->exportList.append( new Export( exp->name, exp->key ) );
- }
- void BackendGen::makeAction( Action *action )
- {
- GenInlineList *genList = new GenInlineList;
- makeGenInlineList( genList, action->inlineList );
- cgd->newAction( curAction++, action->name, action->loc, genList );
- }
- void BackendGen::makeActionList()
- {
- /* Determine which actions to write. */
- int nextActionId = 0;
- for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
- if ( act->numRefs() > 0 || act->numCondRefs > 0 )
- act->actionId = nextActionId++;
- }
- /* Write the list. */
- cgd->initActionList( nextActionId );
- curAction = 0;
- for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
- if ( act->actionId >= 0 )
- makeAction( act );
- }
- }
- void BackendGen::makeActionTableList()
- {
- /* Must first order the action tables based on their id. */
- int numTables = nextActionTableId;
- RedActionTable **tables = new RedActionTable*[numTables];
- for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
- tables[at->id] = at;
- cgd->initActionTableList( numTables );
- curActionTable = 0;
- for ( int t = 0; t < numTables; t++ ) {
- long length = tables[t]->key.length();
- /* Collect the action table. */
- RedAction *redAct = cgd->allActionTables + curActionTable;
- redAct->actListId = curActionTable;
- redAct->key.setAsNew( length );
- for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
- redAct->key[atel.pos()].key = 0;
- redAct->key[atel.pos()].value = cgd->allActions +
- atel->value->actionId;
- }
- /* Insert into the action table map. */
- cgd->redFsm->actionMap.insert( redAct );
- curActionTable += 1;
- }
- delete[] tables;
- }
- void BackendGen::makeConditions()
- {
- if ( condData->condSpaceMap.length() > 0 ) {
- long nextCondSpaceId = 0;
- for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
- cs->condSpaceId = nextCondSpaceId++;
- long listLength = condData->condSpaceMap.length();
- cgd->initCondSpaceList( listLength );
- curCondSpace = 0;
- for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
- long id = cs->condSpaceId;
- cgd->newCondSpace( curCondSpace, id, cs->baseKey );
- for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
- cgd->condSpaceItem( curCondSpace, (*csi)->actionId );
- curCondSpace += 1;
- }
- }
- }
- bool BackendGen::makeNameInst( std::string &res, NameInst *nameInst )
- {
- bool written = false;
- if ( nameInst->parent != 0 )
- written = makeNameInst( res, nameInst->parent );
-
- if ( nameInst->name != 0 ) {
- if ( written )
- res += '_';
- res += nameInst->name;
- written = true;
- }
- return written;
- }
- void BackendGen::makeEntryPoints()
- {
- /* List of entry points other than start state. */
- if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
- if ( pd->lmRequiresErrorState )
- cgd->setForcedErrorState();
- for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
- /* Get the name instantiation from nameIndex. */
- NameInst *nameInst = pd->nameIndex[en->key];
- std::string name;
- makeNameInst( name, nameInst );
- StateAp *state = en->value;
- cgd->addEntryPoint( strdup(name.c_str()), state->alg.stateNum );
- }
- }
- }
- void BackendGen::makeStateActions( StateAp *state )
- {
- RedActionTable *toStateActions = 0;
- if ( state->toStateActionTable.length() > 0 )
- toStateActions = actionTableMap.find( state->toStateActionTable );
- RedActionTable *fromStateActions = 0;
- if ( state->fromStateActionTable.length() > 0 )
- fromStateActions = actionTableMap.find( state->fromStateActionTable );
- /* EOF actions go out here only if the state has no eof target. If it has
- * an eof target then an eof transition will be used instead. */
- RedActionTable *eofActions = 0;
- if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
- eofActions = actionTableMap.find( state->eofActionTable );
-
- if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
- long to = -1;
- if ( toStateActions != 0 )
- to = toStateActions->id;
- long from = -1;
- if ( fromStateActions != 0 )
- from = fromStateActions->id;
- long eof = -1;
- if ( eofActions != 0 )
- eof = eofActions->id;
- cgd->setStateActions( curState, to, from, eof );
- }
- }
- void BackendGen::makeEofTrans( StateAp *state )
- {
- RedActionTable *eofActions = 0;
- if ( state->eofActionTable.length() > 0 )
- eofActions = actionTableMap.find( state->eofActionTable );
-
- /* The EOF trans is used when there is an eof target, otherwise the eof
- * action goes into state actions. */
- if ( state->eofTarget != 0 ) {
- long targ = state->eofTarget->alg.stateNum;
- long action = -1;
- if ( eofActions != 0 )
- action = eofActions->id;
- cgd->setEofTrans( curState, targ, action );
- }
- }
- void BackendGen::makeStateConditions( StateAp *state )
- {
- if ( state->stateCondList.length() > 0 ) {
- long length = state->stateCondList.length();
- cgd->initStateCondList( curState, length );
- curStateCond = 0;
- for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
- cgd->addStateCond( curState, scdi->lowKey, scdi->highKey,
- scdi->condSpace->condSpaceId );
- }
- }
- }
- void BackendGen::makeTrans( Key lowKey, Key highKey, TransAp *trans )
- {
- /* First reduce the action. */
- RedActionTable *actionTable = 0;
- if ( trans->actionTable.length() > 0 )
- actionTable = actionTableMap.find( trans->actionTable );
- long targ = -1;
- if ( trans->toState != 0 )
- targ = trans->toState->alg.stateNum;
- long action = -1;
- if ( actionTable != 0 )
- action = actionTable->id;
- cgd->newTrans( curState, curTrans++, lowKey, highKey, targ, action );
- }
- void BackendGen::makeTransList( StateAp *state )
- {
- TransListVect outList;
- /* If there is only are no ranges the task is simple. */
- if ( state->outList.length() > 0 ) {
- /* Loop each source range. */
- for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
- /* Reduce the transition. If it reduced to anything then add it. */
- appendTrans( outList, trans->lowKey, trans->highKey, trans );
- }
- }
- cgd->initTransList( curState, outList.length() );
- curTrans = 0;
- for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
- makeTrans( tvi->lowKey, tvi->highKey, tvi->value );
- cgd->finishTransList( curState );
- }
- void BackendGen::makeStateList()
- {
- /* Write the list of states. */
- long length = fsm->stateList.length();
- cgd->initStateList( length );
- curState = 0;
- for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
- makeStateActions( st );
- makeEofTrans( st );
- makeStateConditions( st );
- makeTransList( st );
- long id = st->alg.stateNum;
- cgd->setId( curState, id );
- if ( st->isFinState() )
- cgd->setFinal( curState );
- curState += 1;
- }
- }
- void BackendGen::makeMachine()
- {
- cgd->createMachine();
- /* Action tables. */
- reduceActionTables();
- makeActionList();
- makeActionTableList();
- makeConditions();
- /* Start State. */
- cgd->setStartState( fsm->startState->alg.stateNum );
- /* Error state. */
- if ( fsm->errState != 0 )
- cgd->setErrorState( fsm->errState->alg.stateNum );
- makeEntryPoints();
- makeStateList();
- cgd->closeMachine();
- }
- void BackendGen::close_ragel_def()
- {
- /* Do this before distributing transitions out to singles and defaults
- * makes life easier. */
- cgd->redFsm->maxKey = cgd->findMaxKey();
- cgd->redFsm->assignActionLocs();
- /* Find the first final state (The final state with the lowest id). */
- cgd->redFsm->findFirstFinState();
- /* Call the user's callback. */
- cgd->finishRagelDef();
- }
- void BackendGen::makeBackend()
- {
- /* Alphabet type. */
- cgd->setAlphType( keyOps->alphType->internalName );
-
- /* Getkey expression. */
- if ( pd->getKeyExpr != 0 ) {
- cgd->getKeyExpr = new GenInlineList;
- makeGenInlineList( cgd->getKeyExpr, pd->getKeyExpr );
- }
- /* Access expression. */
- if ( pd->accessExpr != 0 ) {
- cgd->accessExpr = new GenInlineList;
- makeGenInlineList( cgd->accessExpr, pd->accessExpr );
- }
- /* PrePush expression. */
- if ( pd->prePushExpr != 0 ) {
- cgd->prePushExpr = new GenInlineList;
- makeGenInlineList( cgd->prePushExpr, pd->prePushExpr );
- }
- /* PostPop expression. */
- if ( pd->postPopExpr != 0 ) {
- cgd->postPopExpr = new GenInlineList;
- makeGenInlineList( cgd->postPopExpr, pd->postPopExpr );
- }
- /*
- * Variable expressions.
- */
- if ( pd->pExpr != 0 ) {
- cgd->pExpr = new GenInlineList;
- makeGenInlineList( cgd->pExpr, pd->pExpr );
- }
-
- if ( pd->peExpr != 0 ) {
- cgd->peExpr = new GenInlineList;
- makeGenInlineList( cgd->peExpr, pd->peExpr );
- }
- if ( pd->eofExpr != 0 ) {
- cgd->eofExpr = new GenInlineList;
- makeGenInlineList( cgd->eofExpr, pd->eofExpr );
- }
-
- if ( pd->csExpr != 0 ) {
- cgd->csExpr = new GenInlineList;
- makeGenInlineList( cgd->csExpr, pd->csExpr );
- }
-
- if ( pd->topExpr != 0 ) {
- cgd->topExpr = new GenInlineList;
- makeGenInlineList( cgd->topExpr, pd->topExpr );
- }
-
- if ( pd->stackExpr != 0 ) {
- cgd->stackExpr = new GenInlineList;
- makeGenInlineList( cgd->stackExpr, pd->stackExpr );
- }
-
- if ( pd->actExpr != 0 ) {
- cgd->actExpr = new GenInlineList;
- makeGenInlineList( cgd->actExpr, pd->actExpr );
- }
-
- if ( pd->tokstartExpr != 0 ) {
- cgd->tokstartExpr = new GenInlineList;
- makeGenInlineList( cgd->tokstartExpr, pd->tokstartExpr );
- }
-
- if ( pd->tokendExpr != 0 ) {
- cgd->tokendExpr = new GenInlineList;
- makeGenInlineList( cgd->tokendExpr, pd->tokendExpr );
- }
-
- if ( pd->dataExpr != 0 ) {
- cgd->dataExpr = new GenInlineList;
- makeGenInlineList( cgd->dataExpr, pd->dataExpr );
- }
-
- makeExports();
- makeMachine();
- close_ragel_def();
- }
- void InputData::writeLanguage( std::ostream &out )
- {
- out << " lang=\"";
- switch ( hostLang->lang ) {
- case HostLang::C: out << "C"; break;
- case HostLang::D: out << "D"; break;
- case HostLang::D2: out << "D2"; break;
- case HostLang::Go: out << "Go"; break;
- case HostLang::Java: out << "Java"; break;
- case HostLang::Ruby: out << "Ruby"; break;
- case HostLang::CSharp: out << "C#"; break;
- case HostLang::OCaml: out << "OCaml"; break;
- }
- out << "\"";
- }
- void InputData::writeXML( std::ostream &out )
- {
- out << "<ragel version=\"" VERSION "\" filename=\"" << inputFileName << "\"";
- writeLanguage( out );
- out << ">\n";
- for ( ParserDict::Iter parser = parserDict; parser.lte(); parser++ ) {
- ParseData *pd = parser->value->pd;
- if ( pd->instanceList.length() > 0 )
- pd->generateXML( *outStream );
- }
- out << "</ragel>\n";
- }
|