diff options
author | smalov <[email protected]> | 2022-02-10 16:47:36 +0300 |
---|---|---|
committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:47:36 +0300 |
commit | f70d9720e13aef3a935e3f405b0eac554529e76e (patch) | |
tree | 5519c392aebdb16153197de07e4774c0a2be261a /contrib/tools/ragel6/xmlcodegen.cpp | |
parent | 7b659037613268d5eac4a1b6a7c5eff3cd36d4bf (diff) |
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/ragel6/xmlcodegen.cpp')
-rw-r--r-- | contrib/tools/ragel6/xmlcodegen.cpp | 2848 |
1 files changed, 1424 insertions, 1424 deletions
diff --git a/contrib/tools/ragel6/xmlcodegen.cpp b/contrib/tools/ragel6/xmlcodegen.cpp index e4b14bc82b2..d8d9004697a 100644 --- a/contrib/tools/ragel6/xmlcodegen.cpp +++ b/contrib/tools/ragel6/xmlcodegen.cpp @@ -1,1429 +1,1429 @@ -/* - * Copyright 2005-2007 Adrian Thurston <[email protected]> - */ - -/* 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. +/* + * Copyright 2005-2007 Adrian Thurston <[email protected]> + */ + +/* This file is part of Ragel. * - * 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 ) { + * 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::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; + 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::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"; -} + } + 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"; +} |