/*
- * Copyright 2005-2007 Adrian Thurston <thurston@cs.queensu.ca>
+ * Copyright 2005-2007 Adrian Thurston <thurston@complang.org>
*/
/* This file is part of Ragel.
#include "ragel.h"
#include "xmlcodegen.h"
+#include "xmlparse.h"
#include "parsedata.h"
#include "fsmgraph.h"
+#include "gendata.h"
+#include "inputdata.h"
#include <string.h>
using namespace std;
-XMLCodeGen::XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm,
- std::ostream &out )
+GenBase::GenBase( char *fsmName, ParseData *pd, FsmAp *fsm )
:
fsmName(fsmName),
pd(pd),
fsm(fsm),
- out(out),
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()
{
delete[] tables;
}
-void XMLCodeGen::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++;
- }
- }
- }
-}
-
-void XMLCodeGen::appendTrans( TransListVect &outList, Key lowKey,
- Key highKey, TransAp *trans )
-{
- if ( trans->toState != 0 || trans->actionTable.length() > 0 )
- outList.append( TransEl( lowKey, highKey, trans ) );
-}
-
void XMLCodeGen::writeKey( Key key )
{
if ( keyOps->isSigned )
out << " </trans_list>\n";
}
-void XMLCodeGen::writeText( InlineItem *item )
+void XMLCodeGen::writeEofTrans( StateAp *state )
{
- 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>";
-}
+ 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;
-bool isLmItem( InlineItem *context )
-{
- return context != 0 && (
- context->type == InlineItem::LmOnLast ||
- context->type == InlineItem::LmOnNext ||
- context->type == InlineItem::LmOnLagBehind ||
- context->type == InlineItem::LmSwitch );
-}
+ if ( eofActions != 0 )
+ out << " " << eofActions->id;
+ else
+ out << " x";
-void XMLCodeGen::writeCtrlFlow( InlineItem *item, InlineItem *context )
-{
- switch ( item->type ) {
- case InlineItem::Goto:
- writeGoto( item, context );
- break;
- case InlineItem::GotoExpr:
- writeGotoExpr( item, context );
- break;
- case InlineItem::Call:
- writeCall( item, context );
- break;
- case InlineItem::CallExpr:
- writeCallExpr( item, context );
- break;
- case InlineItem::Next:
- writeNext( item, context );
- break;
- case InlineItem::NextExpr:
- writeNextExpr( item, context );
- break;
- case InlineItem::Break:
- out << "<break></break>";
- break;
- case InlineItem::Ret:
- out << "<ret></ret>";
- break;
- default: break;
+ out << "</eof_t>" << endl;
}
}
-void XMLCodeGen::writePtrMod( InlineItem *item, InlineItem * )
+void XMLCodeGen::writeText( InlineItem *item )
{
- switch ( item->type ) {
- case InlineItem::Hold:
- out << "<hold></hold>";
- break;
- case InlineItem::Exec:
- writeActionExec( item );
- break;
- default: break;
- }
+ 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, InlineItem *context )
+void XMLCodeGen::writeGoto( InlineItem *item )
{
if ( pd->generatingSectionSubset )
out << "<goto>-1</goto>";
}
}
-void XMLCodeGen::writeCall( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeCall( InlineItem *item )
{
if ( pd->generatingSectionSubset )
out << "<call>-1</call>";
}
}
-void XMLCodeGen::writeNext( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeNext( InlineItem *item )
{
if ( pd->generatingSectionSubset )
out << "<next>-1</next>";
}
}
-void XMLCodeGen::writeGotoExpr( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeGotoExpr( InlineItem *item )
{
out << "<goto_expr>";
- writeInlineList( item->children, 0 );
+ writeInlineList( item->children );
out << "</goto_expr>";
}
-void XMLCodeGen::writeCallExpr( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeCallExpr( InlineItem *item )
{
out << "<call_expr>";
- writeInlineList( item->children, 0 );
+ writeInlineList( item->children );
out << "</call_expr>";
}
-void XMLCodeGen::writeNextExpr( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeNextExpr( InlineItem *item )
{
out << "<next_expr>";
- writeInlineList( item->children, 0 );
+ writeInlineList( item->children );
out << "</next_expr>";
}
-void XMLCodeGen::writeEntry( InlineItem * item )
+void XMLCodeGen::writeEntry( InlineItem *item )
{
if ( pd->generatingSectionSubset )
out << "<entry>-1</entry>";
void XMLCodeGen::writeActionExec( InlineItem *item )
{
out << "<exec>";
- writeInlineList( item->children, 0 );
+ writeInlineList( item->children );
out << "</exec>";
}
-void XMLCodeGen::writeActionExecTE( InlineItem *item )
-{
- out << "<execte>";
- writeInlineList( item->children, 0 );
- out << "</execte>";
-}
-
void XMLCodeGen::writeLmOnLast( InlineItem *item )
{
out << "<set_tokend>1</set_tokend>";
if ( item->longestMatchPart->action != 0 ) {
out << "<sub_action>";
- writeInlineList( item->longestMatchPart->action->inlineList, item );
+ writeInlineList( item->longestMatchPart->action->inlineList );
out << "</sub_action>";
}
}
if ( item->longestMatchPart->action != 0 ) {
out << "<sub_action>";
- writeInlineList( item->longestMatchPart->action->inlineList, item );
+ writeInlineList( item->longestMatchPart->action->inlineList );
out << "</sub_action>";
}
}
if ( item->longestMatchPart->action != 0 ) {
out << "<sub_action>";
- writeInlineList( item->longestMatchPart->action->inlineList, item );
+ 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 << " <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 && lmi->action != 0 ) {
- /* 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, item );
- out << "</sub_action>\n";
+ 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, InlineItem *context )
+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: case InlineItem::GotoExpr:
- case InlineItem::Call: case InlineItem::CallExpr:
- case InlineItem::Next: case InlineItem::NextExpr:
- case InlineItem::Break: case InlineItem::Ret:
- writeCtrlFlow( item, context );
+ 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::Hold:
+ out << "<hold></hold>";
+ break;
case InlineItem::Exec:
- writePtrMod( item, context );
+ writeActionExec( item );
break;
case InlineItem::LmSetActId:
}
}
+BackendGen::BackendGen( char *fsmName, ParseData *pd, FsmAp *fsm, InputData &inputData )
+:
+ GenBase(fsmName, pd, fsm),
+ inputData(inputData)
+{
+}
+
+
+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, long entryId, GenInlineItem::Type type )
+{
+ long targetState;
+ if ( pd->generatingSectionSubset )
+ targetState = -1;
+ else {
+ EntryMapEl *targ = fsm->entryPoints.find( entryId );
+ 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->id, GenInlineItem::Goto );
+ break;
+ case InlineItem::GotoExpr:
+ makeSubList( outList, item->children, GenInlineItem::GotoExpr );
+ break;
+ case InlineItem::Call:
+ makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Call );
+ break;
+ case InlineItem::CallExpr:
+ makeSubList( outList, item->children, GenInlineItem::CallExpr );
+ break;
+ case InlineItem::Next:
+ makeTargetItem( outList, item->nameTarg->id, 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->id, 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 ) );
+ inputData.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, 0 );
+ writeInlineList( action->inlineList );
out << "</action>\n";
}
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->eofActionTable.length() > 0 )
+ if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
eofActions = actionTableMap.find( state->eofActionTable );
if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
if ( eofActions != 0 )
out << " " << eofActions->id;
else
- out << " x"; out << "</state_actions>\n";
+ out << " x";
+
+ out << "</state_actions>\n";
}
}
out << ">\n";
writeStateActions( st );
+ writeEofTrans( st );
writeStateConditions( st );
writeTransList( st );
/* Getkey expression. */
if ( pd->getKeyExpr != 0 ) {
out << " <getkey>";
- writeInlineList( pd->getKeyExpr, 0 );
+ writeInlineList( pd->getKeyExpr );
out << "</getkey>\n";
}
/* Access expression. */
if ( pd->accessExpr != 0 ) {
out << " <access>";
- writeInlineList( pd->accessExpr, 0 );
+ 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, 0 );
+ writeInlineList( pd->pExpr );
out << "</p_expr>\n";
}
if ( pd->peExpr != 0 ) {
out << " <pe_expr>";
- writeInlineList( pd->peExpr, 0 );
+ 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, 0 );
+ writeInlineList( pd->csExpr );
out << "</cs_expr>\n";
}
if ( pd->topExpr != 0 ) {
out << " <top_expr>";
- writeInlineList( pd->topExpr, 0 );
+ writeInlineList( pd->topExpr );
out << "</top_expr>\n";
}
if ( pd->stackExpr != 0 ) {
out << " <stack_expr>";
- writeInlineList( pd->stackExpr, 0 );
+ writeInlineList( pd->stackExpr );
out << "</stack_expr>\n";
}
if ( pd->actExpr != 0 ) {
out << " <act_expr>";
- writeInlineList( pd->actExpr, 0 );
+ writeInlineList( pd->actExpr );
out << "</act_expr>\n";
}
if ( pd->tokstartExpr != 0 ) {
out << " <tokstart_expr>";
- writeInlineList( pd->tokstartExpr, 0 );
+ writeInlineList( pd->tokstartExpr );
out << "</tokstart_expr>\n";
}
if ( pd->tokendExpr != 0 ) {
out << " <tokend_expr>";
- writeInlineList( pd->tokendExpr, 0 );
+ writeInlineList( pd->tokendExpr );
out << "</tokend_expr>\n";
}
+ if ( pd->dataExpr != 0 ) {
+ out << " <data_expr>";
+ writeInlineList( pd->dataExpr );
+ out << "</data_expr>\n";
+ }
+
writeExports();
writeMachine();
"</ragel_def>\n";
}
+void BackendGen::makeExports()
+{
+ for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ )
+ inputData.cgd->exportList.append( new Export( exp->name, exp->key ) );
+}
+
+void BackendGen::makeAction( Action *action )
+{
+ GenInlineList *genList = new GenInlineList;
+ makeGenInlineList( genList, action->inlineList );
+
+ inputData.cgd->newAction( curAction++, action->name,
+ action->loc.line, action->loc.col, 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. */
+ inputData.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;
+
+ inputData.cgd->initActionTableList( numTables );
+ curActionTable = 0;
+
+ for ( int t = 0; t < numTables; t++ ) {
+ long length = tables[t]->key.length();
+
+ /* Collect the action table. */
+ RedAction *redAct = inputData.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 = inputData.cgd->allActions +
+ atel->value->actionId;
+ }
+
+ /* Insert into the action table map. */
+ inputData.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();
+ inputData.cgd->initCondSpaceList( listLength );
+ curCondSpace = 0;
+
+ for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
+ long id = cs->condSpaceId;
+ inputData.cgd->newCondSpace( curCondSpace, id, cs->baseKey );
+ for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
+ inputData.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 )
+ inputData.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;
+ inputData.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;
+
+ inputData.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;
+
+ inputData.cgd->setEofTrans( curState, targ, action );
+ }
+}
+
+void BackendGen::makeStateConditions( StateAp *state )
+{
+ if ( state->stateCondList.length() > 0 ) {
+ long length = state->stateCondList.length();
+ inputData.cgd->initStateCondList( curState, length );
+ curStateCond = 0;
+
+ for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
+ inputData.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;
+
+ inputData.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 );
+ }
+ }
+
+ inputData.cgd->initTransList( curState, outList.length() );
+ curTrans = 0;
+
+ for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
+ makeTrans( tvi->lowKey, tvi->highKey, tvi->value );
+
+ inputData.cgd->finishTransList( curState );
+}
+
+
+void BackendGen::makeStateList()
+{
+ /* Write the list of states. */
+ long length = fsm->stateList.length();
+ inputData.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;
+ inputData.cgd->setId( curState, id );
+
+ if ( st->isFinState() )
+ inputData.cgd->setFinal( curState );
+
+ curState += 1;
+ }
+}
+
+
+void BackendGen::makeMachine()
+{
+ inputData.cgd->createMachine();
+
+ /* Action tables. */
+ reduceActionTables();
+
+ makeActionList();
+ makeActionTableList();
+ makeConditions();
+
+ /* Start State. */
+ inputData.cgd->setStartState( fsm->startState->alg.stateNum );
+
+ /* Error state. */
+ if ( fsm->errState != 0 )
+ inputData.cgd->setErrorState( fsm->errState->alg.stateNum );
+
+ makeEntryPoints();
+ makeStateList();
+
+ inputData.cgd->closeMachine();
+}
+
+void BackendGen::open_ragel_def( char *fsmName )
+{
+ CodeGenMapEl *mapEl = inputData.codeGenMap.find( fsmName );
+ if ( mapEl != 0 )
+ inputData.cgd = mapEl->value;
+ else {
+ inputData.cgd = makeCodeGen( inputData.sourceFileName, fsmName,
+ *inputData.outStream, inputData.wantComplete );
+ inputData.codeGenMap.insert( fsmName, inputData.cgd );
+ }
+}
+
+void BackendGen::close_ragel_def()
+{
+ /* Do this before distributing transitions out to singles and defaults
+ * makes life easier. */
+ inputData.cgd->redFsm->maxKey = inputData.cgd->findMaxKey();
+
+ inputData.cgd->redFsm->assignActionLocs();
+
+ /* Find the first final state (The final state with the lowest id). */
+ inputData.cgd->redFsm->findFirstFinState();
+
+ /* Call the user's callback. */
+ inputData.cgd->finishRagelDef();
+}
+
+
+void BackendGen::makeBackend()
+{
+ /* Alphabet type. */
+ inputData.cgd->setAlphType( keyOps->alphType->internalName );
+
+ /* Getkey expression. */
+ if ( pd->getKeyExpr != 0 ) {
+ inputData.cgd->getKeyExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->getKeyExpr, pd->getKeyExpr );
+ }
+
+ /* Access expression. */
+ if ( pd->accessExpr != 0 ) {
+ inputData.cgd->accessExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->accessExpr, pd->accessExpr );
+ }
+
+ /* PrePush expression. */
+ if ( pd->prePushExpr != 0 ) {
+ inputData.cgd->prePushExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->prePushExpr, pd->prePushExpr );
+ }
+
+ /* PostPop expression. */
+ if ( pd->postPopExpr != 0 ) {
+ inputData.cgd->postPopExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->postPopExpr, pd->postPopExpr );
+ }
+
+ /*
+ * Variable expressions.
+ */
+
+ if ( pd->pExpr != 0 ) {
+ inputData.cgd->pExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->pExpr, pd->pExpr );
+ }
+
+ if ( pd->peExpr != 0 ) {
+ inputData.cgd->peExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->peExpr, pd->peExpr );
+ }
+
+ if ( pd->eofExpr != 0 ) {
+ inputData.cgd->eofExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->eofExpr, pd->eofExpr );
+ }
+
+ if ( pd->csExpr != 0 ) {
+ inputData.cgd->csExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->csExpr, pd->csExpr );
+ }
+
+ if ( pd->topExpr != 0 ) {
+ inputData.cgd->topExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->topExpr, pd->topExpr );
+ }
+
+ if ( pd->stackExpr != 0 ) {
+ inputData.cgd->stackExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->stackExpr, pd->stackExpr );
+ }
+
+ if ( pd->actExpr != 0 ) {
+ inputData.cgd->actExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->actExpr, pd->actExpr );
+ }
+
+ if ( pd->tokstartExpr != 0 ) {
+ inputData.cgd->tokstartExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->tokstartExpr, pd->tokstartExpr );
+ }
+
+ if ( pd->tokendExpr != 0 ) {
+ inputData.cgd->tokendExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->tokendExpr, pd->tokendExpr );
+ }
+
+ if ( pd->dataExpr != 0 ) {
+ inputData.cgd->dataExpr = new GenInlineList;
+ makeGenInlineList( inputData.cgd->dataExpr, pd->dataExpr );
+ }
+
+ makeExports();
+ makeMachine();
+
+ close_ragel_def();
+}
+
+