diff options
author | qrort <qrort@yandex-team.com> | 2022-11-30 23:47:12 +0300 |
---|---|---|
committer | qrort <qrort@yandex-team.com> | 2022-11-30 23:47:12 +0300 |
commit | 22f8ae0e3f5d68b92aecccdf96c1d841a0334311 (patch) | |
tree | bffa27765faf54126ad44bcafa89fadecb7a73d7 /contrib/tools/ragel5/ragel | |
parent | 332b99e2173f0425444abb759eebcb2fafaa9209 (diff) | |
download | ydb-22f8ae0e3f5d68b92aecccdf96c1d841a0334311.tar.gz |
validate canons without yatest_common
Diffstat (limited to 'contrib/tools/ragel5/ragel')
-rw-r--r-- | contrib/tools/ragel5/ragel/fsmap.cpp | 840 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/fsmattach.cpp | 425 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/fsmbase.cpp | 598 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/fsmgraph.cpp | 1426 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/fsmgraph.h | 1482 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/fsmmin.cpp | 732 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/fsmstate.cpp | 463 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/main.cpp | 355 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/parsedata.cpp | 1505 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/parsedata.h | 401 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/parsetree.cpp | 2089 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/parsetree.h | 755 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/ragel.h | 74 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/rlparse.cpp | 6088 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/rlparse.h | 184 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/rlscan.cpp | 4876 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/rlscan.h | 161 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/xmlcodegen.cpp | 713 | ||||
-rw-r--r-- | contrib/tools/ragel5/ragel/xmlcodegen.h | 137 |
19 files changed, 23304 insertions, 0 deletions
diff --git a/contrib/tools/ragel5/ragel/fsmap.cpp b/contrib/tools/ragel5/ragel/fsmap.cpp new file mode 100644 index 00000000000..551aea03914 --- /dev/null +++ b/contrib/tools/ragel5/ragel/fsmap.cpp @@ -0,0 +1,840 @@ +/* + * Copyright 2002-2004 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "fsmgraph.h" +#include <iostream> +using std::cerr; +using std::endl; + +CondData *condData = 0; +KeyOps *keyOps = 0; + +/* Insert an action into an action table. */ +void ActionTable::setAction( int ordering, Action *action ) +{ + /* Multi-insert in case specific instances of an action appear in a + * transition more than once. */ + insertMulti( ordering, action ); +} + +/* Set all the action from another action table in this table. */ +void ActionTable::setActions( const ActionTable &other ) +{ + for ( ActionTable::Iter action = other; action.lte(); action++ ) + insertMulti( action->key, action->value ); +} + +void ActionTable::setActions( int *orderings, Action **actions, int nActs ) +{ + for ( int a = 0; a < nActs; a++ ) + insertMulti( orderings[a], actions[a] ); +} + +bool ActionTable::hasAction( Action *action ) +{ + for ( int a = 0; a < length(); a++ ) { + if ( data[a].value == action ) + return true; + } + return false; +} + +/* Insert an action into an action table. */ +void LmActionTable::setAction( int ordering, LongestMatchPart *action ) +{ + /* Multi-insert in case specific instances of an action appear in a + * transition more than once. */ + insertMulti( ordering, action ); +} + +/* Set all the action from another action table in this table. */ +void LmActionTable::setActions( const LmActionTable &other ) +{ + for ( LmActionTable::Iter action = other; action.lte(); action++ ) + insertMulti( action->key, action->value ); +} + +void ErrActionTable::setAction( int ordering, Action *action, int transferPoint ) +{ + insertMulti( ErrActionTableEl( action, ordering, transferPoint ) ); +} + +void ErrActionTable::setActions( const ErrActionTable &other ) +{ + for ( ErrActionTable::Iter act = other; act.lte(); act++ ) + insertMulti( ErrActionTableEl( act->action, act->ordering, act->transferPoint ) ); +} + +/* Insert a priority into this priority table. Looks out for priorities on + * duplicate keys. */ +void PriorTable::setPrior( int ordering, PriorDesc *desc ) +{ + PriorEl *lastHit = 0; + PriorEl *insed = insert( PriorEl(ordering, desc), &lastHit ); + if ( insed == 0 ) { + /* This already has a priority on the same key as desc. Overwrite the + * priority if the ordering is larger (later in time). */ + if ( ordering >= lastHit->ordering ) + *lastHit = PriorEl( ordering, desc ); + } +} + +/* Set all the priorities from a priorTable in this table. */ +void PriorTable::setPriors( const PriorTable &other ) +{ + /* Loop src priorities once to overwrite duplicates. */ + PriorTable::Iter priorIt = other; + for ( ; priorIt.lte(); priorIt++ ) + setPrior( priorIt->ordering, priorIt->desc ); +} + +/* Set the priority of starting transitions. Isolates the start state so it has + * no other entry points, then sets the priorities of all the transitions out + * of the start state. If the start state is final, then the outPrior of the + * start state is also set. The idea is that a machine that accepts the null + * string can still specify the starting trans prior for when it accepts the + * null word. */ +void FsmAp::startFsmPrior( int ordering, PriorDesc *prior ) +{ + /* Make sure the start state has no other entry points. */ + isolateStartState(); + + /* Walk all transitions out of the start state. */ + for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) { + if ( trans->toState != 0 ) + trans->priorTable.setPrior( ordering, prior ); + } +} + +/* Set the priority of all transitions in a graph. Walks all transition lists + * and all def transitions. */ +void FsmAp::allTransPrior( int ordering, PriorDesc *prior ) +{ + /* Walk the list of all states. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + /* Walk the out list of the state. */ + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { + if ( trans->toState != 0 ) + trans->priorTable.setPrior( ordering, prior ); + } + } +} + +/* Set the priority of all transitions that go into a final state. Note that if + * any entry states are final, we will not be setting the priority of any + * transitions that may go into those states in the future. The graph does not + * support pending in transitions in the same way pending out transitions are + * supported. */ +void FsmAp::finishFsmPrior( int ordering, PriorDesc *prior ) +{ + /* Walk all final states. */ + for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) { + /* Walk all in transitions of the final state. */ + for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ ) + trans->priorTable.setPrior( ordering, prior ); + } +} + +/* Set the priority of any future out transitions that may be made going out of + * this state machine. */ +void FsmAp::leaveFsmPrior( int ordering, PriorDesc *prior ) +{ + /* Set priority in all final states. */ + for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) + (*state)->outPriorTable.setPrior( ordering, prior ); +} + + +/* Set actions to execute on starting transitions. Isolates the start state + * so it has no other entry points, then adds to the transition functions + * of all the transitions out of the start state. If the start state is final, + * then the func is also added to the start state's out func list. The idea is + * that a machine that accepts the null string can execute a start func when it + * matches the null word, which can only be done when leaving the start/final + * state. */ +void FsmAp::startFsmAction( int ordering, Action *action ) +{ + /* Make sure the start state has no other entry points. */ + isolateStartState(); + + /* Walk the start state's transitions, setting functions. */ + for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) { + if ( trans->toState != 0 ) + trans->actionTable.setAction( ordering, action ); + } +} + +/* Set functions to execute on all transitions. Walks the out lists of all + * states. */ +void FsmAp::allTransAction( int ordering, Action *action ) +{ + /* Walk all states. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + /* Walk the out list of the state. */ + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { + if ( trans->toState != 0 ) + trans->actionTable.setAction( ordering, action ); + } + } +} + +/* Specify functions to execute upon entering final states. If the start state + * is final we can't really specify a function to execute upon entering that + * final state the first time. So function really means whenever entering a + * final state from within the same fsm. */ +void FsmAp::finishFsmAction( int ordering, Action *action ) +{ + /* Walk all final states. */ + for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) { + /* Walk the final state's in list. */ + for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ ) + trans->actionTable.setAction( ordering, action ); + } +} + +/* Add functions to any future out transitions that may be made going out of + * this state machine. */ +void FsmAp::leaveFsmAction( int ordering, Action *action ) +{ + /* Insert the action in the outActionTable of all final states. */ + for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) + (*state)->outActionTable.setAction( ordering, action ); +} + +/* Add functions to the longest match action table for constructing scanners. */ +void FsmAp::longMatchAction( int ordering, LongestMatchPart *lmPart ) +{ + /* Walk all final states. */ + for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) { + /* Walk the final state's in list. */ + for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ ) + trans->lmActionTable.setAction( ordering, lmPart ); + } +} + +void FsmAp::fillGaps( StateAp *state ) +{ + if ( state->outList.length() == 0 ) { + /* Add the range on the lower and upper bound. */ + attachNewTrans( state, 0, keyOps->minKey, keyOps->maxKey ); + } + else { + TransList srcList; + srcList.transfer( state->outList ); + + /* Check for a gap at the beginning. */ + TransList::Iter trans = srcList, next; + if ( keyOps->minKey < trans->lowKey ) { + /* Make the high key and append. */ + Key highKey = trans->lowKey; + highKey.decrement(); + + attachNewTrans( state, 0, keyOps->minKey, highKey ); + } + + /* Write the transition. */ + next = trans.next(); + state->outList.append( trans ); + + /* Keep the last high end. */ + Key lastHigh = trans->highKey; + + /* Loop each source range. */ + for ( trans = next; trans.lte(); trans = next ) { + /* Make the next key following the last range. */ + Key nextKey = lastHigh; + nextKey.increment(); + + /* Check for a gap from last up to here. */ + if ( nextKey < trans->lowKey ) { + /* Make the high end of the range that fills the gap. */ + Key highKey = trans->lowKey; + highKey.decrement(); + + attachNewTrans( state, 0, nextKey, highKey ); + } + + /* Reduce the transition. If it reduced to anything then add it. */ + next = trans.next(); + state->outList.append( trans ); + + /* Keep the last high end. */ + lastHigh = trans->highKey; + } + + /* Now check for a gap on the end to fill. */ + if ( lastHigh < keyOps->maxKey ) { + /* Get a copy of the default. */ + lastHigh.increment(); + + attachNewTrans( state, 0, lastHigh, keyOps->maxKey ); + } + } +} + +void FsmAp::setErrorAction( StateAp *state, int ordering, Action *action ) +{ + /* Fill any gaps in the out list with an error transition. */ + fillGaps( state ); + + /* Set error transitions in the transitions that go to error. */ + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { + if ( trans->toState == 0 ) + trans->actionTable.setAction( ordering, action ); + } +} + + +/* Give a target state for error transitions. */ +void FsmAp::setErrorTarget( StateAp *state, StateAp *target, int *orderings, + Action **actions, int nActs ) +{ + /* Fill any gaps in the out list with an error transition. */ + fillGaps( state ); + + /* Set error target in the transitions that go to error. */ + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { + if ( trans->toState == 0 ) { + /* The trans goes to error, redirect it. */ + redirectErrorTrans( trans->fromState, target, trans ); + trans->actionTable.setActions( orderings, actions, nActs ); + } + } +} + +void FsmAp::transferErrorActions( StateAp *state, int transferPoint ) +{ + for ( int i = 0; i < state->errActionTable.length(); ) { + ErrActionTableEl *act = state->errActionTable.data + i; + if ( act->transferPoint == transferPoint ) { + /* Transfer the error action and remove it. */ + setErrorAction( state, act->ordering, act->action ); + state->errActionTable.vremove( i ); + } + else { + /* Not transfering and deleting, skip over the item. */ + i += 1; + } + } +} + +/* Set error actions in the start state. */ +void FsmAp::startErrorAction( int ordering, Action *action, int transferPoint ) +{ + /* Make sure the start state has no other entry points. */ + isolateStartState(); + + /* Add the actions. */ + startState->errActionTable.setAction( ordering, action, transferPoint ); +} + +/* Set error actions in all states where there is a transition out. */ +void FsmAp::allErrorAction( int ordering, Action *action, int transferPoint ) +{ + /* Insert actions in the error action table of all states. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) + state->errActionTable.setAction( ordering, action, transferPoint ); +} + +/* Set error actions in final states. */ +void FsmAp::finalErrorAction( int ordering, Action *action, int transferPoint ) +{ + /* Add the action to the error table of final states. */ + for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) + (*state)->errActionTable.setAction( ordering, action, transferPoint ); +} + +void FsmAp::notStartErrorAction( int ordering, Action *action, int transferPoint ) +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( state != startState ) + state->errActionTable.setAction( ordering, action, transferPoint ); + } +} + +void FsmAp::notFinalErrorAction( int ordering, Action *action, int transferPoint ) +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( ! state->isFinState() ) + state->errActionTable.setAction( ordering, action, transferPoint ); + } +} + +/* Set error actions in the states that have transitions into a final state. */ +void FsmAp::middleErrorAction( int ordering, Action *action, int transferPoint ) +{ + /* Isolate the start state in case it is reachable from in inside the + * machine, in which case we don't want it set. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( state != startState && ! state->isFinState() ) + state->errActionTable.setAction( ordering, action, transferPoint ); + } +} + +/* Set EOF actions in the start state. */ +void FsmAp::startEOFAction( int ordering, Action *action ) +{ + /* Make sure the start state has no other entry points. */ + isolateStartState(); + + /* Add the actions. */ + startState->eofActionTable.setAction( ordering, action ); +} + +/* Set EOF actions in all states where there is a transition out. */ +void FsmAp::allEOFAction( int ordering, Action *action ) +{ + /* Insert actions in the EOF action table of all states. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) + state->eofActionTable.setAction( ordering, action ); +} + +/* Set EOF actions in final states. */ +void FsmAp::finalEOFAction( int ordering, Action *action ) +{ + /* Add the action to the error table of final states. */ + for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) + (*state)->eofActionTable.setAction( ordering, action ); +} + +void FsmAp::notStartEOFAction( int ordering, Action *action ) +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( state != startState ) + state->eofActionTable.setAction( ordering, action ); + } +} + +void FsmAp::notFinalEOFAction( int ordering, Action *action ) +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( ! state->isFinState() ) + state->eofActionTable.setAction( ordering, action ); + } +} + +/* Set EOF actions in the states that have transitions into a final state. */ +void FsmAp::middleEOFAction( int ordering, Action *action ) +{ + /* Set the actions in all states that are not the start state and not final. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( state != startState && ! state->isFinState() ) + state->eofActionTable.setAction( ordering, action ); + } +} + +/* + * Set To State Actions. + */ + +/* Set to state actions in the start state. */ +void FsmAp::startToStateAction( int ordering, Action *action ) +{ + /* Make sure the start state has no other entry points. */ + isolateStartState(); + startState->toStateActionTable.setAction( ordering, action ); +} + +/* Set to state actions in all states. */ +void FsmAp::allToStateAction( int ordering, Action *action ) +{ + /* Insert the action on all states. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) + state->toStateActionTable.setAction( ordering, action ); +} + +/* Set to state actions in final states. */ +void FsmAp::finalToStateAction( int ordering, Action *action ) +{ + /* Add the action to the error table of final states. */ + for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) + (*state)->toStateActionTable.setAction( ordering, action ); +} + +void FsmAp::notStartToStateAction( int ordering, Action *action ) +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( state != startState ) + state->toStateActionTable.setAction( ordering, action ); + } +} + +void FsmAp::notFinalToStateAction( int ordering, Action *action ) +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( ! state->isFinState() ) + state->toStateActionTable.setAction( ordering, action ); + } +} + +/* Set to state actions in states that are not final and not the start state. */ +void FsmAp::middleToStateAction( int ordering, Action *action ) +{ + /* Set the action in all states that are not the start state and not final. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( state != startState && ! state->isFinState() ) + state->toStateActionTable.setAction( ordering, action ); + } +} + +/* + * Set From State Actions. + */ + +void FsmAp::startFromStateAction( int ordering, Action *action ) +{ + /* Make sure the start state has no other entry points. */ + isolateStartState(); + startState->fromStateActionTable.setAction( ordering, action ); +} + +void FsmAp::allFromStateAction( int ordering, Action *action ) +{ + /* Insert the action on all states. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) + state->fromStateActionTable.setAction( ordering, action ); +} + +void FsmAp::finalFromStateAction( int ordering, Action *action ) +{ + /* Add the action to the error table of final states. */ + for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) + (*state)->fromStateActionTable.setAction( ordering, action ); +} + +void FsmAp::notStartFromStateAction( int ordering, Action *action ) +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( state != startState ) + state->fromStateActionTable.setAction( ordering, action ); + } +} + +void FsmAp::notFinalFromStateAction( int ordering, Action *action ) +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( ! state->isFinState() ) + state->fromStateActionTable.setAction( ordering, action ); + } +} + +void FsmAp::middleFromStateAction( int ordering, Action *action ) +{ + /* Set the action in all states that are not the start state and not final. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + if ( state != startState && ! state->isFinState() ) + state->fromStateActionTable.setAction( ordering, action ); + } +} + +/* Shift the function ordering of the start transitions to start + * at fromOrder and increase in units of 1. Useful before staring. + * Returns the maximum number of order numbers used. */ +int FsmAp::shiftStartActionOrder( int fromOrder ) +{ + int maxUsed = 0; + + /* Walk the start state's transitions, shifting function ordering. */ + for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) { + /* Walk the function data for the transition and set the keys to + * increasing values starting at fromOrder. */ + int curFromOrder = fromOrder; + ActionTable::Iter action = trans->actionTable; + for ( ; action.lte(); action++ ) + action->key = curFromOrder++; + + /* Keep track of the max number of orders used. */ + if ( curFromOrder - fromOrder > maxUsed ) + maxUsed = curFromOrder - fromOrder; + } + + return maxUsed; +} + +/* Remove all priorities. */ +void FsmAp::clearAllPriorities() +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + /* Clear out priority data. */ + state->outPriorTable.empty(); + + /* Clear transition data from the out transitions. */ + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) + trans->priorTable.empty(); + } +} + +/* Zeros out the function ordering keys. This may be called before minimization + * when it is known that no more fsm operations are going to be done. This + * will achieve greater reduction as states will not be separated on the basis + * of function ordering. */ +void FsmAp::nullActionKeys( ) +{ + /* For each state... */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + /* Walk the transitions for the state. */ + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { + /* Walk the action table for the transition. */ + for ( ActionTable::Iter action = trans->actionTable; + action.lte(); action++ ) + action->key = 0; + + /* Walk the action table for the transition. */ + for ( LmActionTable::Iter action = trans->lmActionTable; + action.lte(); action++ ) + action->key = 0; + } + + /* Null the action keys of the to state action table. */ + for ( ActionTable::Iter action = state->toStateActionTable; + action.lte(); action++ ) + action->key = 0; + + /* Null the action keys of the from state action table. */ + for ( ActionTable::Iter action = state->fromStateActionTable; + action.lte(); action++ ) + action->key = 0; + + /* Null the action keys of the out transtions. */ + for ( ActionTable::Iter action = state->outActionTable; + action.lte(); action++ ) + action->key = 0; + + /* Null the action keys of the error action table. */ + for ( ErrActionTable::Iter action = state->errActionTable; + action.lte(); action++ ) + action->ordering = 0; + + /* Null the action keys eof action table. */ + for ( ActionTable::Iter action = state->eofActionTable; + action.lte(); action++ ) + action->key = 0; + } +} + +/* Walk the list of states and verify that non final states do not have out + * data, that all stateBits are cleared, and that there are no states with + * zero foreign in transitions. */ +void FsmAp::verifyStates() +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + /* Non final states should not have leaving data. */ + if ( ! (state->stateBits & SB_ISFINAL) ) { + assert( state->outActionTable.length() == 0 ); + assert( state->outCondSet.length() == 0 ); + assert( state->outPriorTable.length() == 0 ); + } + + /* Data used in algorithms should be cleared. */ + assert( (state->stateBits & SB_BOTH) == 0 ); + assert( state->foreignInTrans > 0 ); + } +} + +/* Compare two transitions according to their relative priority. Since the + * base transition has no priority associated with it, the default is to + * return equal. */ +int FsmAp::comparePrior( const PriorTable &priorTable1, const PriorTable &priorTable2 ) +{ + /* Looking for differing priorities on same keys. Need to concurrently + * scan the priority lists. */ + PriorTable::Iter pd1 = priorTable1; + PriorTable::Iter pd2 = priorTable2; + while ( pd1.lte() && pd2.lte() ) { + /* Check keys. */ + if ( pd1->desc->key < pd2->desc->key ) + pd1.increment(); + else if ( pd1->desc->key > pd2->desc->key ) + pd2.increment(); + /* Keys are the same, check priorities. */ + else if ( pd1->desc->priority < pd2->desc->priority ) + return -1; + else if ( pd1->desc->priority > pd2->desc->priority ) + return 1; + else { + /* Keys and priorities are equal, advance both. */ + pd1.increment(); + pd2.increment(); + } + } + + /* No differing priorities on the same key. */ + return 0; +} + +/* Compares two transitions according to priority and functions. Pointers + * should not be null. Does not consider to state or from state. Compare two + * transitions according to the data contained in the transitions. Data means + * any properties added to user transitions that may differentiate them. Since + * the base transition has no data, the default is to return equal. */ +int FsmAp::compareTransData( TransAp *trans1, TransAp *trans2 ) +{ + /* Compare the prior table. */ + int cmpRes = CmpPriorTable::compare( trans1->priorTable, + trans2->priorTable ); + if ( cmpRes != 0 ) + return cmpRes; + + /* Compare longest match action tables. */ + cmpRes = CmpLmActionTable::compare(trans1->lmActionTable, + trans2->lmActionTable); + if ( cmpRes != 0 ) + return cmpRes; + + /* Compare action tables. */ + return CmpActionTable::compare(trans1->actionTable, + trans2->actionTable); +} + +/* Callback invoked when another trans (or possibly this) is added into this + * transition during the merging process. Draw in any properties of srcTrans + * into this transition. AddInTrans is called when a new transitions is made + * that will be a duplicate of another transition or a combination of several + * other transitions. AddInTrans will be called for each transition that the + * new transition is to represent. */ +void FsmAp::addInTrans( TransAp *destTrans, TransAp *srcTrans ) +{ + /* Protect against adding in from ourselves. */ + if ( srcTrans == destTrans ) { + /* Adding in ourselves, need to make a copy of the source transitions. + * The priorities are not copied in as that would have no effect. */ + destTrans->lmActionTable.setActions( LmActionTable(srcTrans->lmActionTable) ); + destTrans->actionTable.setActions( ActionTable(srcTrans->actionTable) ); + } + else { + /* Not a copy of ourself, get the functions and priorities. */ + destTrans->lmActionTable.setActions( srcTrans->lmActionTable ); + destTrans->actionTable.setActions( srcTrans->actionTable ); + destTrans->priorTable.setPriors( srcTrans->priorTable ); + } +} + +/* Compare the properties of states that are embedded by users. Compares out + * priorities, out transitions, to, from, out, error and eof action tables. */ +int FsmAp::compareStateData( const StateAp *state1, const StateAp *state2 ) +{ + /* Compare the out priority table. */ + int cmpRes = CmpPriorTable:: + compare( state1->outPriorTable, state2->outPriorTable ); + if ( cmpRes != 0 ) + return cmpRes; + + /* Test to state action tables. */ + cmpRes = CmpActionTable::compare( state1->toStateActionTable, + state2->toStateActionTable ); + if ( cmpRes != 0 ) + return cmpRes; + + /* Test from state action tables. */ + cmpRes = CmpActionTable::compare( state1->fromStateActionTable, + state2->fromStateActionTable ); + if ( cmpRes != 0 ) + return cmpRes; + + /* Test out action tables. */ + cmpRes = CmpActionTable::compare( state1->outActionTable, + state2->outActionTable ); + if ( cmpRes != 0 ) + return cmpRes; + + /* Test out condition sets. */ + cmpRes = CmpActionSet::compare( state1->outCondSet, + state2->outCondSet ); + if ( cmpRes != 0 ) + return cmpRes; + + /* Test out error action tables. */ + cmpRes = CmpErrActionTable::compare( state1->errActionTable, + state2->errActionTable ); + if ( cmpRes != 0 ) + return cmpRes; + + /* Test eof action tables. */ + return CmpActionTable::compare( state1->eofActionTable, + state2->eofActionTable ); +} + + +/* Invoked when a state looses its final state status and the leaving + * transition embedding data should be deleted. */ +void FsmAp::clearOutData( StateAp *state ) +{ + /* Kill the out actions and priorities. */ + state->outActionTable.empty(); + state->outCondSet.empty(); + state->outPriorTable.empty(); +} + +bool FsmAp::hasOutData( StateAp *state ) +{ + return ( state->outActionTable.length() > 0 || + state->outCondSet.length() > 0 || + state->outPriorTable.length() > 0 ); +} + +/* + * Setting Conditions. + */ + + +void logNewExpansion( Expansion *exp ); +void logCondSpace( CondSpace *condSpace ); + +CondSpace *FsmAp::addCondSpace( const CondSet &condSet ) +{ + CondSpace *condSpace = condData->condSpaceMap.find( condSet ); + if ( condSpace == 0 ) { + Key baseKey = condData->nextCondKey; + condData->nextCondKey += (1 << condSet.length() ) * keyOps->alphSize(); + + condSpace = new CondSpace( condSet ); + condSpace->baseKey = baseKey; + condData->condSpaceMap.insert( condSpace ); + + #ifdef LOG_CONDS + cerr << "adding new condition space" << endl; + cerr << " condition set: "; + logCondSpace( condSpace ); + cerr << endl; + cerr << " baseKey: " << baseKey.getVal() << endl; + #endif + } + return condSpace; +} + +void FsmAp::startFsmCondition( Action *condAction ) +{ + /* Make sure the start state has no other entry points. */ + isolateStartState(); + embedCondition( startState, condAction ); +} + +void FsmAp::allTransCondition( Action *condAction ) +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) + embedCondition( state, condAction ); +} + +void FsmAp::leaveFsmCondition( Action *condAction ) +{ + for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) + (*state)->outCondSet.insert( condAction ); +} diff --git a/contrib/tools/ragel5/ragel/fsmattach.cpp b/contrib/tools/ragel5/ragel/fsmattach.cpp new file mode 100644 index 00000000000..6a90df658a2 --- /dev/null +++ b/contrib/tools/ragel5/ragel/fsmattach.cpp @@ -0,0 +1,425 @@ +/* + * Copyright 2001 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <string.h> +#include <assert.h> +#include "fsmgraph.h" + +#include <iostream> +using namespace std; + +/* Insert a transition into an inlist. The head must be supplied. */ +void FsmAp::attachToInList( StateAp *from, StateAp *to, + TransAp *&head, TransAp *trans ) +{ + trans->ilnext = head; + trans->ilprev = 0; + + /* If in trans list is not empty, set the head->prev to trans. */ + if ( head != 0 ) + head->ilprev = trans; + + /* Now insert ourselves at the front of the list. */ + head = trans; + + /* Keep track of foreign transitions for from and to. */ + if ( from != to ) { + if ( misfitAccounting ) { + /* If the number of foreign in transitions is about to go up to 1 then + * move it from the misfit list to the main list. */ + if ( to->foreignInTrans == 0 ) + stateList.append( misfitList.detach( to ) ); + } + + to->foreignInTrans += 1; + } +}; + +/* Detach a transition from an inlist. The head of the inlist must be supplied. */ +void FsmAp::detachFromInList( StateAp *from, StateAp *to, + TransAp *&head, TransAp *trans ) +{ + /* Detach in the inTransList. */ + if ( trans->ilprev == 0 ) + head = trans->ilnext; + else + trans->ilprev->ilnext = trans->ilnext; + + if ( trans->ilnext != 0 ) + trans->ilnext->ilprev = trans->ilprev; + + /* Keep track of foreign transitions for from and to. */ + if ( from != to ) { + to->foreignInTrans -= 1; + + if ( misfitAccounting ) { + /* If the number of foreign in transitions goes down to 0 then move it + * from the main list to the misfit list. */ + if ( to->foreignInTrans == 0 ) + misfitList.append( stateList.detach( to ) ); + } + } +} + +/* Attach states on the default transition, range list or on out/in list key. + * First makes a new transition. If there is already a transition out from + * fromState on the default, then will assertion fail. */ +TransAp *FsmAp::attachNewTrans( StateAp *from, StateAp *to, Key lowKey, Key highKey ) +{ + /* Make the new transition. */ + TransAp *retVal = new TransAp(); + + /* The transition is now attached. Remember the parties involved. */ + retVal->fromState = from; + retVal->toState = to; + + /* Make the entry in the out list for the transitions. */ + from->outList.append( retVal ); + + /* Set the the keys of the new trans. */ + retVal->lowKey = lowKey; + retVal->highKey = highKey; + + /* Attach using inList as the head pointer. */ + if ( to != 0 ) + attachToInList( from, to, to->inList.head, retVal ); + + return retVal; +} + +/* Attach for range lists or for the default transition. This attach should + * be used when a transition already is allocated and must be attached to a + * target state. Does not handle adding the transition into the out list. */ +void FsmAp::attachTrans( StateAp *from, StateAp *to, TransAp *trans ) +{ + assert( trans->fromState == 0 && trans->toState == 0 ); + trans->fromState = from; + trans->toState = to; + + if ( to != 0 ) { + /* Attach using the inList pointer as the head pointer. */ + attachToInList( from, to, to->inList.head, trans ); + } +} + +/* Redirect a transition away from error and towards some state. This is just + * like attachTrans except it requires fromState to be set and does not touch + * it. */ +void FsmAp::redirectErrorTrans( StateAp *from, StateAp *to, TransAp *trans ) +{ + assert( trans->fromState != 0 && trans->toState == 0 ); + trans->toState = to; + + if ( to != 0 ) { + /* Attach using the inList pointer as the head pointer. */ + attachToInList( from, to, to->inList.head, trans ); + } +} + +/* Detach for out/in lists or for default transition. */ +void FsmAp::detachTrans( StateAp *from, StateAp *to, TransAp *trans ) +{ + assert( trans->fromState == from && trans->toState == to ); + trans->fromState = 0; + trans->toState = 0; + + if ( to != 0 ) { + /* Detach using to's inList pointer as the head. */ + detachFromInList( from, to, to->inList.head, trans ); + } +} + + +/* Detach a state from the graph. Detaches and deletes transitions in and out + * of the state. Empties inList and outList. Removes the state from the final + * state set. A detached state becomes useless and should be deleted. */ +void FsmAp::detachState( StateAp *state ) +{ + /* Detach the in transitions from the inList list of transitions. */ + while ( state->inList.head != 0 ) { + /* Get pointers to the trans and the state. */ + TransAp *trans = state->inList.head; + StateAp *fromState = trans->fromState; + + /* Detach the transitions from the source state. */ + detachTrans( fromState, state, trans ); + + /* Ok to delete the transition. */ + fromState->outList.detach( trans ); + delete trans; + } + + /* Remove the entry points in on the machine. */ + while ( state->entryIds.length() > 0 ) + unsetEntry( state->entryIds[0], state ); + + /* Detach out range transitions. */ + for ( TransList::Iter trans = state->outList; trans.lte(); ) { + TransList::Iter next = trans.next(); + detachTrans( state, trans->toState, trans ); + delete trans; + trans = next; + } + + /* Delete all of the out range pointers. */ + state->outList.abandon(); + + /* Unset final stateness before detaching from graph. */ + if ( state->stateBits & SB_ISFINAL ) + finStateSet.remove( state ); +} + + +/* Duplicate a transition. Makes a new transition that is attached to the same + * dest as srcTrans. The new transition has functions and priority taken from + * srcTrans. Used for merging a transition in to a free spot. The trans can + * just be dropped in. It does not conflict with an existing trans and need + * not be crossed. Returns the new transition. */ +TransAp *FsmAp::dupTrans( StateAp *from, TransAp *srcTrans ) +{ + /* Make a new transition. */ + TransAp *newTrans = new TransAp(); + + /* We can attach the transition, one does not exist. */ + attachTrans( from, srcTrans->toState, newTrans ); + + /* Call the user callback to add in the original source transition. */ + addInTrans( newTrans, srcTrans ); + + return newTrans; +} + +/* In crossing, src trans and dest trans both go to existing states. Make one + * state from the sets of states that src and dest trans go to. */ +TransAp *FsmAp::fsmAttachStates( MergeData &md, StateAp *from, + TransAp *destTrans, TransAp *srcTrans ) +{ + /* The priorities are equal. We must merge the transitions. Does the + * existing trans go to the state we are to attach to? ie, are we to + * simply double up the transition? */ + StateAp *toState = srcTrans->toState; + StateAp *existingState = destTrans->toState; + + if ( existingState == toState ) { + /* The transition is a double up to the same state. Copy the src + * trans into itself. We don't need to merge in the from out trans + * data, that was done already. */ + addInTrans( destTrans, srcTrans ); + } + else { + /* The trans is not a double up. Dest trans cannot be the same as src + * trans. Set up the state set. */ + StateSet stateSet; + + /* We go to all the states the existing trans goes to, plus... */ + if ( existingState->stateDictEl == 0 ) + stateSet.insert( existingState ); + else + stateSet.insert( existingState->stateDictEl->stateSet ); + + /* ... all the states that we have been told to go to. */ + if ( toState->stateDictEl == 0 ) + stateSet.insert( toState ); + else + stateSet.insert( toState->stateDictEl->stateSet ); + + /* Look for the state. If it is not there already, make it. */ + StateDictEl *lastFound; + if ( md.stateDict.insert( stateSet, &lastFound ) ) { + /* Make a new state representing the combination of states in + * stateSet. It gets added to the fill list. This means that we + * need to fill in it's transitions sometime in the future. We + * don't do that now (ie, do not recurse). */ + StateAp *combinState = addState(); + + /* Link up the dict element and the state. */ + lastFound->targState = combinState; + combinState->stateDictEl = lastFound; + + /* Add to the fill list. */ + md.fillListAppend( combinState ); + } + + /* Get the state insertted/deleted. */ + StateAp *targ = lastFound->targState; + + /* Detach the state from existing state. */ + detachTrans( from, existingState, destTrans ); + + /* Re-attach to the new target. */ + attachTrans( from, targ, destTrans ); + + /* Add in src trans to the existing transition that we redirected to + * the new state. We don't need to merge in the from out trans data, + * that was done already. */ + addInTrans( destTrans, srcTrans ); + } + + return destTrans; +} + +/* Two transitions are to be crossed, handle the possibility of either going + * to the error state. */ +TransAp *FsmAp::mergeTrans( MergeData &md, StateAp *from, + TransAp *destTrans, TransAp *srcTrans ) +{ + TransAp *retTrans = 0; + if ( destTrans->toState == 0 && srcTrans->toState == 0 ) { + /* Error added into error. */ + addInTrans( destTrans, srcTrans ); + retTrans = destTrans; + } + else if ( destTrans->toState == 0 && srcTrans->toState != 0 ) { + /* Non error added into error we need to detach and reattach, */ + detachTrans( from, destTrans->toState, destTrans ); + attachTrans( from, srcTrans->toState, destTrans ); + addInTrans( destTrans, srcTrans ); + retTrans = destTrans; + } + else if ( srcTrans->toState == 0 ) { + /* Dest goes somewhere but src doesn't, just add it it in. */ + addInTrans( destTrans, srcTrans ); + retTrans = destTrans; + } + else { + /* Both go somewhere, run the actual cross. */ + retTrans = fsmAttachStates( md, from, destTrans, srcTrans ); + } + + return retTrans; +} + +/* Find the trans with the higher priority. If src is lower priority then dest then + * src is ignored. If src is higher priority than dest, then src overwrites dest. If + * the priorities are equal, then they are merged. */ +TransAp *FsmAp::crossTransitions( MergeData &md, StateAp *from, + TransAp *destTrans, TransAp *srcTrans ) +{ + TransAp *retTrans; + + /* Compare the priority of the dest and src transitions. */ + int compareRes = comparePrior( destTrans->priorTable, srcTrans->priorTable ); + if ( compareRes < 0 ) { + /* Src trans has a higher priority than dest, src overwrites dest. + * Detach dest and return a copy of src. */ + detachTrans( from, destTrans->toState, destTrans ); + retTrans = dupTrans( from, srcTrans ); + } + else if ( compareRes > 0 ) { + /* The dest trans has a higher priority, use dest. */ + retTrans = destTrans; + } + else { + /* Src trans and dest trans have the same priority, they must be merged. */ + retTrans = mergeTrans( md, from, destTrans, srcTrans ); + } + + /* Return the transition that resulted from the cross. */ + return retTrans; +} + +/* Copy the transitions in srcList to the outlist of dest. The srcList should + * not be the outList of dest, otherwise you would be copying the contents of + * srcList into itself as it's iterated: bad news. */ +void FsmAp::outTransCopy( MergeData &md, StateAp *dest, TransAp *srcList ) +{ + /* The destination list. */ + TransList destList; + + /* Set up an iterator to stop at breaks. */ + PairIter<TransAp> outPair( dest->outList.head, srcList ); + for ( ; !outPair.end(); outPair++ ) { + switch ( outPair.userState ) { + case RangeInS1: { + /* The pair iter is the authority on the keys. It may have needed + * to break the dest range. */ + TransAp *destTrans = outPair.s1Tel.trans; + destTrans->lowKey = outPair.s1Tel.lowKey; + destTrans->highKey = outPair.s1Tel.highKey; + destList.append( destTrans ); + break; + } + case RangeInS2: { + /* Src range may get crossed with dest's default transition. */ + TransAp *newTrans = dupTrans( dest, outPair.s2Tel.trans ); + + /* Set up the transition's keys and append to the dest list. */ + newTrans->lowKey = outPair.s2Tel.lowKey; + newTrans->highKey = outPair.s2Tel.highKey; + destList.append( newTrans ); + break; + } + case RangeOverlap: { + /* Exact overlap, cross them. */ + TransAp *newTrans = crossTransitions( md, dest, + outPair.s1Tel.trans, outPair.s2Tel.trans ); + + /* Set up the transition's keys and append to the dest list. */ + newTrans->lowKey = outPair.s1Tel.lowKey; + newTrans->highKey = outPair.s1Tel.highKey; + destList.append( newTrans ); + break; + } + case BreakS1: { + /* Since we are always writing to the dest trans, the dest needs + * to be copied when it is broken. The copy goes into the first + * half of the break to "break it off". */ + outPair.s1Tel.trans = dupTrans( dest, outPair.s1Tel.trans ); + break; + } + case BreakS2: + break; + } + } + + /* Abandon the old outList and transfer destList into it. */ + dest->outList.transfer( destList ); +} + + +/* Move all the transitions that go into src so that they go into dest. */ +void FsmAp::inTransMove( StateAp *dest, StateAp *src ) +{ + /* Do not try to move in trans to and from the same state. */ + assert( dest != src ); + + /* If src is the start state, dest becomes the start state. */ + if ( src == startState ) { + unsetStartState(); + setStartState( dest ); + } + + /* For each entry point into, create an entry point into dest, when the + * state is detached, the entry points to src will be removed. */ + for ( EntryIdSet::Iter enId = src->entryIds; enId.lte(); enId++ ) + changeEntry( *enId, dest, src ); + + /* Move the transitions in inList. */ + while ( src->inList.head != 0 ) { + /* Get trans and from state. */ + TransAp *trans = src->inList.head; + StateAp *fromState = trans->fromState; + + /* Detach from src, reattach to dest. */ + detachTrans( fromState, src, trans ); + attachTrans( fromState, dest, trans ); + } +} diff --git a/contrib/tools/ragel5/ragel/fsmbase.cpp b/contrib/tools/ragel5/ragel/fsmbase.cpp new file mode 100644 index 00000000000..f1d7141c099 --- /dev/null +++ b/contrib/tools/ragel5/ragel/fsmbase.cpp @@ -0,0 +1,598 @@ +/* + * Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <string.h> +#include <assert.h> +#include "fsmgraph.h" + +/* Simple singly linked list append routine for the fill list. The new state + * goes to the end of the list. */ +void MergeData::fillListAppend( StateAp *state ) +{ + state->alg.next = 0; + + if ( stfillHead == 0 ) { + /* List is empty, state becomes head and tail. */ + stfillHead = state; + stfillTail = state; + } + else { + /* List is not empty, state goes after last element. */ + stfillTail->alg.next = state; + stfillTail = state; + } +} + +/* Graph constructor. */ +FsmAp::FsmAp() +: + /* No start state. */ + startState(0), + errState(0), + + /* Misfit accounting is a switch, turned on only at specific times. It + * controls what happens when states have no way in from the outside + * world.. */ + misfitAccounting(false) +{ +} + +/* Copy all graph data including transitions. */ +FsmAp::FsmAp( const FsmAp &graph ) +: + /* Lists start empty. Will be filled by copy. */ + stateList(), + misfitList(), + + /* Copy in the entry points, + * pointers will be resolved later. */ + entryPoints(graph.entryPoints), + startState(graph.startState), + errState(0), + + /* Will be filled by copy. */ + finStateSet(), + + /* Misfit accounting is only on during merging. */ + misfitAccounting(false) +{ + /* Create the states and record their map in the original state. */ + StateList::Iter origState = graph.stateList; + for ( ; origState.lte(); origState++ ) { + /* Make the new state. */ + StateAp *newState = new StateAp( *origState ); + + /* Add the state to the list. */ + stateList.append( newState ); + + /* Set the mapsTo item of the old state. */ + origState->alg.stateMap = newState; + } + + /* Derefernce all the state maps. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { + /* The points to the original in the src machine. The taget's duplicate + * is in the statemap. */ + StateAp *toState = trans->toState != 0 ? trans->toState->alg.stateMap : 0; + + /* Attach The transition to the duplicate. */ + trans->toState = 0; + attachTrans( state, toState, trans ); + } + } + + /* Fix the state pointers in the entry points array. */ + EntryMapEl *eel = entryPoints.data; + for ( int e = 0; e < entryPoints.length(); e++, eel++ ) { + /* Get the duplicate of the state. */ + eel->value = eel->value->alg.stateMap; + + /* Foreign in transitions must be built up when duping machines so + * increment it here. */ + eel->value->foreignInTrans += 1; + } + + /* Fix the start state pointer and the new start state's count of in + * transiions. */ + startState = startState->alg.stateMap; + startState->foreignInTrans += 1; + + /* Build the final state set. */ + StateSet::Iter st = graph.finStateSet; + for ( ; st.lte(); st++ ) + finStateSet.insert((*st)->alg.stateMap); +} + +/* Deletes all transition data then deletes each state. */ +FsmAp::~FsmAp() +{ + /* Delete all the transitions. */ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + /* Iterate the out transitions, deleting them. */ + state->outList.empty(); + } + + /* Delete all the states. */ + stateList.empty(); +} + +/* Set a state final. The state has its isFinState set to true and the state + * is added to the finStateSet. */ +void FsmAp::setFinState( StateAp *state ) +{ + /* Is it already a fin state. */ + if ( state->stateBits & SB_ISFINAL ) + return; + + state->stateBits |= SB_ISFINAL; + finStateSet.insert( state ); +} + +/* Set a state non-final. The has its isFinState flag set false and the state + * is removed from the final state set. */ +void FsmAp::unsetFinState( StateAp *state ) +{ + /* Is it already a non-final state? */ + if ( ! (state->stateBits & SB_ISFINAL) ) + return; + + /* When a state looses its final state status it must relinquish all the + * properties that are allowed only for final states. */ + clearOutData( state ); + + state->stateBits &= ~ SB_ISFINAL; + finStateSet.remove( state ); +} + +/* Set and unset a state as the start state. */ +void FsmAp::setStartState( StateAp *state ) +{ + /* Sould change from unset to set. */ + assert( startState == 0 ); + startState = state; + + if ( misfitAccounting ) { + /* If the number of foreign in transitions is about to go up to 1 then + * take it off the misfit list and put it on the head list. */ + if ( state->foreignInTrans == 0 ) + stateList.append( misfitList.detach( state ) ); + } + + /* Up the foreign in transitions to the state. */ + state->foreignInTrans += 1; +} + +void FsmAp::unsetStartState() +{ + /* Should change from set to unset. */ + assert( startState != 0 ); + + /* Decrement the entry's count of foreign entries. */ + startState->foreignInTrans -= 1; + + if ( misfitAccounting ) { + /* If the number of foreign in transitions just went down to 0 then take + * it off the main list and put it on the misfit list. */ + if ( startState->foreignInTrans == 0 ) + misfitList.append( stateList.detach( startState ) ); + } + + startState = 0; +} + +/* Associate an id with a state. Makes the state a named entry point. Has no + * effect if the entry point is already mapped to the state. */ +void FsmAp::setEntry( int id, StateAp *state ) +{ + /* Insert the id into the state. If the state is already labelled with id, + * nothing to do. */ + if ( state->entryIds.insert( id ) ) { + /* Insert the entry and assert that it succeeds. */ + entryPoints.insertMulti( id, state ); + + if ( misfitAccounting ) { + /* If the number of foreign in transitions is about to go up to 1 then + * take it off the misfit list and put it on the head list. */ + if ( state->foreignInTrans == 0 ) + stateList.append( misfitList.detach( state ) ); + } + + /* Up the foreign in transitions to the state. */ + state->foreignInTrans += 1; + } +} + +/* Remove the association of an id with a state. The state looses it's entry + * point status. Assumes that the id is indeed mapped to state. */ +void FsmAp::unsetEntry( int id, StateAp *state ) +{ + /* Find the entry point in on id. */ + EntryMapEl *enLow = 0, *enHigh = 0; + entryPoints.findMulti( id, enLow, enHigh ); + while ( enLow->value != state ) + enLow += 1; + + /* Remove the record from the map. */ + entryPoints.remove( enLow ); + + /* Remove the state's sense of the link. */ + state->entryIds.remove( id ); + state->foreignInTrans -= 1; + if ( misfitAccounting ) { + /* If the number of foreign in transitions just went down to 0 then take + * it off the main list and put it on the misfit list. */ + if ( state->foreignInTrans == 0 ) + misfitList.append( stateList.detach( state ) ); + } +} + +/* Remove all association of an id with states. Assumes that the id is indeed + * mapped to a state. */ +void FsmAp::unsetEntry( int id ) +{ + /* Find the entry point in on id. */ + EntryMapEl *enLow = 0, *enHigh = 0; + entryPoints.findMulti( id, enLow, enHigh ); + for ( EntryMapEl *mel = enLow; mel <= enHigh; mel++ ) { + /* Remove the state's sense of the link. */ + mel->value->entryIds.remove( id ); + mel->value->foreignInTrans -= 1; + if ( misfitAccounting ) { + /* If the number of foreign in transitions just went down to 0 + * then take it off the main list and put it on the misfit list. */ + if ( mel->value->foreignInTrans == 0 ) + misfitList.append( stateList.detach( mel->value ) ); + } + } + + /* Remove the records from the entry points map. */ + entryPoints.removeMulti( enLow, enHigh ); +} + + +void FsmAp::changeEntry( int id, StateAp *to, StateAp *from ) +{ + /* Find the entry in the entry map. */ + EntryMapEl *enLow = 0, *enHigh = 0; + entryPoints.findMulti( id, enLow, enHigh ); + while ( enLow->value != from ) + enLow += 1; + + /* Change it to the new target. */ + enLow->value = to; + + /* Remove from's sense of the link. */ + from->entryIds.remove( id ); + from->foreignInTrans -= 1; + if ( misfitAccounting ) { + /* If the number of foreign in transitions just went down to 0 then take + * it off the main list and put it on the misfit list. */ + if ( from->foreignInTrans == 0 ) + misfitList.append( stateList.detach( from ) ); + } + + /* Add to's sense of the link. */ + if ( to->entryIds.insert( id ) != 0 ) { + if ( misfitAccounting ) { + /* If the number of foreign in transitions is about to go up to 1 then + * take it off the misfit list and put it on the head list. */ + if ( to->foreignInTrans == 0 ) + stateList.append( misfitList.detach( to ) ); + } + + /* Up the foreign in transitions to the state. */ + to->foreignInTrans += 1; + } +} + + +/* Clear all entry points from a machine. */ +void FsmAp::unsetAllEntryPoints() +{ + for ( EntryMap::Iter en = entryPoints; en.lte(); en++ ) { + /* Kill all the state's entry points at once. */ + if ( en->value->entryIds.length() > 0 ) { + en->value->foreignInTrans -= en->value->entryIds.length(); + + if ( misfitAccounting ) { + /* If the number of foreign in transitions just went down to 0 + * then take it off the main list and put it on the misfit + * list. */ + if ( en->value->foreignInTrans == 0 ) + misfitList.append( stateList.detach( en->value ) ); + } + + /* Clear the set of ids out all at once. */ + en->value->entryIds.empty(); + } + } + + /* Now clear out the entry map all at once. */ + entryPoints.empty(); +} + +/* Assigning an epsilon transition into final states. */ +void FsmAp::epsilonTrans( int id ) +{ + for ( StateSet::Iter fs = finStateSet; fs.lte(); fs++ ) + (*fs)->epsilonTrans.append( id ); +} + +/* Mark all states reachable from state. Traverses transitions forward. Used + * for removing states that have no path into them. */ +void FsmAp::markReachableFromHere( StateAp *state ) +{ + /* Base case: return; */ + if ( state->stateBits & SB_ISMARKED ) + return; + + /* Set this state as processed. We are going to visit all states that this + * state has a transition to. */ + state->stateBits |= SB_ISMARKED; + + /* Recurse on all out transitions. */ + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { + if ( trans->toState != 0 ) + markReachableFromHere( trans->toState ); + } +} + +void FsmAp::markReachableFromHereStopFinal( StateAp *state ) +{ + /* Base case: return; */ + if ( state->stateBits & SB_ISMARKED ) + return; + + /* Set this state as processed. We are going to visit all states that this + * state has a transition to. */ + state->stateBits |= SB_ISMARKED; + + /* Recurse on all out transitions. */ + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { + StateAp *toState = trans->toState; + if ( toState != 0 && !toState->isFinState() ) + markReachableFromHereStopFinal( toState ); + } +} + +/* Mark all states reachable from state. Traverse transitions backwards. Used + * for removing dead end paths in graphs. */ +void FsmAp::markReachableFromHereReverse( StateAp *state ) +{ + /* Base case: return; */ + if ( state->stateBits & SB_ISMARKED ) + return; + + /* Set this state as processed. We are going to visit all states with + * transitions into this state. */ + state->stateBits |= SB_ISMARKED; + + /* Recurse on all items in transitions. */ + for ( TransInList::Iter trans = state->inList; trans.lte(); trans++ ) + markReachableFromHereReverse( trans->fromState ); +} + +/* Determine if there are any entry points into a start state other than the + * start state. Setting starting transitions requires that the start state be + * isolated. In most cases a start state will already be isolated. */ +bool FsmAp::isStartStateIsolated() +{ + /* If there are any in transitions then the state is not isolated. */ + if ( startState->inList.head != 0 ) + return false; + + /* If there are any entry points then isolated. */ + if ( startState->entryIds.length() > 0 ) + return false; + + return true; +} + +/* Bring in other's entry points. Assumes others states are going to be + * copied into this machine. */ +void FsmAp::copyInEntryPoints( FsmAp *other ) +{ + /* Use insert multi because names are not unique. */ + for ( EntryMap::Iter en = other->entryPoints; en.lte(); en++ ) + entryPoints.insertMulti( en->key, en->value ); +} + + +void FsmAp::unsetAllFinStates() +{ + for ( StateSet::Iter st = finStateSet; st.lte(); st++ ) + (*st)->stateBits &= ~ SB_ISFINAL; + finStateSet.empty(); +} + +void FsmAp::setFinBits( int finStateBits ) +{ + for ( int s = 0; s < finStateSet.length(); s++ ) + finStateSet.data[s]->stateBits |= finStateBits; +} + + +/* Tests the integrity of the transition lists and the fromStates. */ +void FsmAp::verifyIntegrity() +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) { + /* Walk the out transitions and assert fromState is correct. */ + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) + assert( trans->fromState == state ); + + /* Walk the inlist and assert toState is correct. */ + for ( TransInList::Iter trans = state->inList; trans.lte(); trans++ ) + assert( trans->toState == state ); + } +} + +void FsmAp::verifyReachability() +{ + /* Mark all the states that can be reached + * through the set of entry points. */ + markReachableFromHere( startState ); + for ( EntryMap::Iter en = entryPoints; en.lte(); en++ ) + markReachableFromHere( en->value ); + + /* Check that everything got marked. */ + for ( StateList::Iter st = stateList; st.lte(); st++ ) { + /* Assert it got marked and then clear the mark. */ + assert( st->stateBits & SB_ISMARKED ); + st->stateBits &= ~ SB_ISMARKED; + } +} + +void FsmAp::verifyNoDeadEndStates() +{ + /* Mark all states that have paths to the final states. */ + for ( StateSet::Iter pst = finStateSet; pst.lte(); pst++ ) + markReachableFromHereReverse( *pst ); + + /* Start state gets honorary marking. Must be done AFTER recursive call. */ + startState->stateBits |= SB_ISMARKED; + + /* Make sure everything got marked. */ + for ( StateList::Iter st = stateList; st.lte(); st++ ) { + /* Assert the state got marked and unmark it. */ + assert( st->stateBits & SB_ISMARKED ); + st->stateBits &= ~ SB_ISMARKED; + } +} + +void FsmAp::depthFirstOrdering( StateAp *state ) +{ + /* Nothing to do if the state is already on the list. */ + if ( state->stateBits & SB_ONLIST ) + return; + + /* Doing depth first, put state on the list. */ + state->stateBits |= SB_ONLIST; + stateList.append( state ); + + /* Recurse on everything ranges. */ + for ( TransList::Iter tel = state->outList; tel.lte(); tel++ ) { + if ( tel->toState != 0 ) + depthFirstOrdering( tel->toState ); + } +} + +/* Ordering states by transition connections. */ +void FsmAp::depthFirstOrdering() +{ + /* Init on state list flags. */ + for ( StateList::Iter st = stateList; st.lte(); st++ ) + st->stateBits &= ~SB_ONLIST; + + /* Clear out the state list, we will rebuild it. */ + int stateListLen = stateList.length(); + stateList.abandon(); + + /* Add back to the state list from the start state and all other entry + * points. */ + if ( errState != 0 ) + depthFirstOrdering( errState ); + depthFirstOrdering( startState ); + for ( EntryMap::Iter en = entryPoints; en.lte(); en++ ) + depthFirstOrdering( en->value ); + + /* Make sure we put everything back on. */ + assert( stateListLen == stateList.length() ); +} + +/* Stable sort the states by final state status. */ +void FsmAp::sortStatesByFinal() +{ + /* Move forward through the list and throw final states onto the end. */ + StateAp *state = 0; + StateAp *next = stateList.head; + StateAp *last = stateList.tail; + while ( state != last ) { + /* Move forward and load up the next. */ + state = next; + next = state->next; + + /* Throw to the end? */ + if ( state->isFinState() ) { + stateList.detach( state ); + stateList.append( state ); + } + } +} + +void FsmAp::setStateNumbers( int base ) +{ + for ( StateList::Iter state = stateList; state.lte(); state++ ) + state->alg.stateNum = base++; +} + + +bool FsmAp::checkErrTrans( StateAp *state, TransAp *trans ) +{ + /* Might go directly to error state. */ + if ( trans->toState == 0 ) + return true; + + if ( trans->prev == 0 ) { + /* If this is the first transition. */ + if ( keyOps->minKey < trans->lowKey ) + return true; + } + else { + /* Not the first transition. Compare against the prev. */ + TransAp *prev = trans->prev; + Key nextKey = prev->highKey; + nextKey.increment(); + if ( nextKey < trans->lowKey ) + return true; + } + return false; +} + +bool FsmAp::checkErrTransFinish( StateAp *state ) +{ + /* Check if there are any ranges already. */ + if ( state->outList.length() == 0 ) + return true; + else { + /* Get the last and check for a gap on the end. */ + TransAp *last = state->outList.tail; + if ( last->highKey < keyOps->maxKey ) + return true; + } + return 0; +} + +bool FsmAp::hasErrorTrans() +{ + bool result; + for ( StateList::Iter st = stateList; st.lte(); st++ ) { + for ( TransList::Iter tr = st->outList; tr.lte(); tr++ ) { + result = checkErrTrans( st, tr ); + if ( result ) + return true; + } + result = checkErrTransFinish( st ); + if ( result ) + return true; + } + return false; +} diff --git a/contrib/tools/ragel5/ragel/fsmgraph.cpp b/contrib/tools/ragel5/ragel/fsmgraph.cpp new file mode 100644 index 00000000000..d7d0ba4fe22 --- /dev/null +++ b/contrib/tools/ragel5/ragel/fsmgraph.cpp @@ -0,0 +1,1426 @@ +/* + * Copyright 2001, 2002, 2006 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <assert.h> +#include <iostream> + +#include "fsmgraph.h" +#include "mergesort.h" +#include "parsedata.h" + +using std::cerr; +using std::endl; + +/* Make a new state. The new state will be put on the graph's + * list of state. The new state can be created final or non final. */ +StateAp *FsmAp::addState() +{ + /* Make the new state to return. */ + StateAp *state = new StateAp(); + + if ( misfitAccounting ) { + /* Create the new state on the misfit list. All states are created + * with no foreign in transitions. */ + misfitList.append( state ); + } + else { + /* Create the new state. */ + stateList.append( state ); + } + + return state; +} + +/* Construct an FSM that is the concatenation of an array of characters. A new + * machine will be made that has len+1 states with one transition between each + * state for each integer in str. IsSigned determines if the integers are to + * be considered as signed or unsigned ints. */ +void FsmAp::concatFsm( Key *str, int len ) +{ + /* Make the first state and set it as the start state. */ + StateAp *last = addState(); + setStartState( last ); + + /* Attach subsequent states. */ + for ( int i = 0; i < len; i++ ) { + StateAp *newState = addState(); + attachNewTrans( last, newState, str[i], str[i] ); + last = newState; + } + + /* Make the last state the final state. */ + setFinState( last ); +} + +/* Case insensitive version of concatFsm. */ +void FsmAp::concatFsmCI( Key *str, int len ) +{ + /* Make the first state and set it as the start state. */ + StateAp *last = addState(); + setStartState( last ); + + /* Attach subsequent states. */ + for ( int i = 0; i < len; i++ ) { + StateAp *newState = addState(); + + KeySet keySet; + if ( str[i].isLower() ) + keySet.insert( str[i].toUpper() ); + if ( str[i].isUpper() ) + keySet.insert( str[i].toLower() ); + keySet.insert( str[i] ); + + for ( int i = 0; i < keySet.length(); i++ ) + attachNewTrans( last, newState, keySet[i], keySet[i] ); + + last = newState; + } + + /* Make the last state the final state. */ + setFinState( last ); +} + +/* Construct a machine that matches one character. A new machine will be made + * that has two states with a single transition between the states. IsSigned + * determines if the integers are to be considered as signed or unsigned ints. */ +void FsmAp::concatFsm( Key chr ) +{ + /* Two states first start, second final. */ + setStartState( addState() ); + + StateAp *end = addState(); + setFinState( end ); + + /* Attach on the character. */ + attachNewTrans( startState, end, chr, chr ); +} + +/* Construct a machine that matches any character in set. A new machine will + * be made that has two states and len transitions between the them. The set + * should be ordered correctly accroding to KeyOps and should not contain + * any duplicates. */ +void FsmAp::orFsm( Key *set, int len ) +{ + /* Two states first start, second final. */ + setStartState( addState() ); + + StateAp *end = addState(); + setFinState( end ); + + for ( int i = 1; i < len; i++ ) + assert( set[i-1] < set[i] ); + + /* Attach on all the integers in the given string of ints. */ + for ( int i = 0; i < len; i++ ) + attachNewTrans( startState, end, set[i], set[i] ); +} + +/* Construct a machine that matches a range of characters. A new machine will + * be made with two states and a range transition between them. The range will + * match any characters from low to high inclusive. Low should be less than or + * equal to high otherwise undefined behaviour results. IsSigned determines + * if the integers are to be considered as signed or unsigned ints. */ +void FsmAp::rangeFsm( Key low, Key high ) +{ + /* Two states first start, second final. */ + setStartState( addState() ); + + StateAp *end = addState(); + setFinState( end ); + + /* Attach using the range of characters. */ + attachNewTrans( startState, end, low, high ); +} + +/* Construct a machine that a repeated range of characters. */ +void FsmAp::rangeStarFsm( Key low, Key high) +{ + /* One state which is final and is the start state. */ + setStartState( addState() ); + setFinState( startState ); + + /* Attach start to start using range of characters. */ + attachNewTrans( startState, startState, low, high ); +} + +/* Construct a machine that matches the empty string. A new machine will be + * made with only one state. The new state will be both a start and final + * state. IsSigned determines if the machine has a signed or unsigned + * alphabet. Fsm operations must be done on machines with the same alphabet + * signedness. */ +void FsmAp::lambdaFsm( ) +{ + /* Give it one state with no transitions making it + * the start state and final state. */ + setStartState( addState() ); + setFinState( startState ); +} + +/* Construct a machine that matches nothing at all. A new machine will be + * made with only one state. It will not be final. */ +void FsmAp::emptyFsm( ) +{ + /* Give it one state with no transitions making it + * the start state and final state. */ + setStartState( addState() ); +} + +void FsmAp::transferOutData( StateAp *destState, StateAp *srcState ) +{ + for ( TransList::Iter trans = destState->outList; trans.lte(); trans++ ) { + if ( trans->toState != 0 ) { + /* Get the actions data from the outActionTable. */ + trans->actionTable.setActions( srcState->outActionTable ); + + /* Get the priorities from the outPriorTable. */ + trans->priorTable.setPriors( srcState->outPriorTable ); + } + } +} + +/* Kleene star operator. Makes this machine the kleene star of itself. Any + * transitions made going out of the machine and back into itself will be + * notified that they are leaving transitions by having the leavingFromState + * callback invoked. */ +void FsmAp::starOp( ) +{ + /* For the merging process. */ + MergeData md; + + /* Turn on misfit accounting to possibly catch the old start state. */ + setMisfitAccounting( true ); + + /* Create the new new start state. It will be set final after the merging + * of the final states with the start state is complete. */ + StateAp *prevStartState = startState; + unsetStartState(); + setStartState( addState() ); + + /* Merge the new start state with the old one to isolate it. */ + mergeStates( md, startState, prevStartState ); + + /* Merge the start state into all final states. Except the start state on + * the first pass. If the start state is set final we will be doubling up + * its transitions, which will get transfered to any final states that + * follow it in the final state set. This will be determined by the order + * of items in the final state set. To prevent this we just merge with the + * start on a second pass. */ + for ( StateSet::Iter st = finStateSet; st.lte(); st++ ) { + if ( *st != startState ) + mergeStatesLeaving( md, *st, startState ); + } + + /* Now it is safe to merge the start state with itself (provided it + * is set final). */ + if ( startState->isFinState() ) + mergeStatesLeaving( md, startState, startState ); + + /* Now ensure the new start state is a final state. */ + setFinState( startState ); + + /* Fill in any states that were newed up as combinations of others. */ + fillInStates( md ); + + /* Remove the misfits and turn off misfit accounting. */ + removeMisfits(); + setMisfitAccounting( false ); +} + +void FsmAp::repeatOp( int times ) +{ + /* Must be 1 and up. 0 produces null machine and requires deleting this. */ + assert( times > 0 ); + + /* A repeat of one does absolutely nothing. */ + if ( times == 1 ) + return; + + /* Make a machine to make copies from. */ + FsmAp *copyFrom = new FsmAp( *this ); + + /* Concatentate duplicates onto the end up until before the last. */ + for ( int i = 1; i < times-1; i++ ) { + FsmAp *dup = new FsmAp( *copyFrom ); + doConcat( dup, 0, false ); + } + + /* Now use the copyFrom on the end. */ + doConcat( copyFrom, 0, false ); +} + +void FsmAp::optionalRepeatOp( int times ) +{ + /* Must be 1 and up. 0 produces null machine and requires deleting this. */ + assert( times > 0 ); + + /* A repeat of one optional merely allows zero string. */ + if ( times == 1 ) { + setFinState( startState ); + return; + } + + /* Make a machine to make copies from. */ + FsmAp *copyFrom = new FsmAp( *this ); + + /* The state set used in the from end of the concatentation. Starts with + * the initial final state set, then after each concatenation, gets set to + * the the final states that come from the the duplicate. */ + StateSet lastFinSet( finStateSet ); + + /* Set the initial state to zero to allow zero copies. */ + setFinState( startState ); + + /* Concatentate duplicates onto the end up until before the last. */ + for ( int i = 1; i < times-1; i++ ) { + /* Make a duplicate for concating and set the fin bits to graph 2 so we + * can pick out it's final states after the optional style concat. */ + FsmAp *dup = new FsmAp( *copyFrom ); + dup->setFinBits( SB_GRAPH2 ); + doConcat( dup, &lastFinSet, true ); + + /* Clear the last final state set and make the new one by taking only + * the final states that come from graph 2.*/ + lastFinSet.empty(); + for ( int i = 0; i < finStateSet.length(); i++ ) { + /* If the state came from graph 2, add it to the last set and clear + * the bits. */ + StateAp *fs = finStateSet[i]; + if ( fs->stateBits & SB_GRAPH2 ) { + lastFinSet.insert( fs ); + fs->stateBits &= ~SB_GRAPH2; + } + } + } + + /* Now use the copyFrom on the end, no bits set, no bits to clear. */ + doConcat( copyFrom, &lastFinSet, true ); +} + + +/* Fsm concatentation worker. Supports treating the concatentation as optional, + * which essentially leaves the final states of machine one as final. */ +void FsmAp::doConcat( FsmAp *other, StateSet *fromStates, bool optional ) +{ + /* For the merging process. */ + StateSet finStateSetCopy, startStateSet; + MergeData md; + + /* Turn on misfit accounting for both graphs. */ + setMisfitAccounting( true ); + other->setMisfitAccounting( true ); + + /* Get the other's start state. */ + StateAp *otherStartState = other->startState; + + /* Unset other's start state before bringing in the entry points. */ + other->unsetStartState(); + + /* Bring in the rest of other's entry points. */ + copyInEntryPoints( other ); + other->entryPoints.empty(); + + /* Bring in other's states into our state lists. */ + stateList.append( other->stateList ); + misfitList.append( other->misfitList ); + + /* If from states is not set, then get a copy of our final state set before + * we clobber it and use it instead. */ + if ( fromStates == 0 ) { + finStateSetCopy = finStateSet; + fromStates = &finStateSetCopy; + } + + /* Unset all of our final states and get the final states from other. */ + if ( !optional ) + unsetAllFinStates(); + finStateSet.insert( other->finStateSet ); + + /* Since other's lists are empty, we can delete the fsm without + * affecting any states. */ + delete other; + + /* Merge our former final states with the start state of other. */ + for ( int i = 0; i < fromStates->length(); i++ ) { + StateAp *state = fromStates->data[i]; + + /* Merge the former final state with other's start state. */ + mergeStatesLeaving( md, state, otherStartState ); + + /* If the former final state was not reset final then we must clear + * the state's out trans data. If it got reset final then it gets to + * keep its out trans data. This must be done before fillInStates gets + * called to prevent the data from being sourced. */ + if ( ! state->isFinState() ) + clearOutData( state ); + } + + /* Fill in any new states made from merging. */ + fillInStates( md ); + + /* Remove the misfits and turn off misfit accounting. */ + removeMisfits(); + setMisfitAccounting( false ); +} + +/* Concatenates other to the end of this machine. Other is deleted. Any + * transitions made leaving this machine and entering into other are notified + * that they are leaving transitions by having the leavingFromState callback + * invoked. */ +void FsmAp::concatOp( FsmAp *other ) +{ + /* Assert same signedness and return graph concatenation op. */ + doConcat( other, 0, false ); +} + + +void FsmAp::doOr( FsmAp *other ) +{ + /* For the merging process. */ + MergeData md; + + /* Build a state set consisting of both start states */ + StateSet startStateSet; + startStateSet.insert( startState ); + startStateSet.insert( other->startState ); + + /* Both of the original start states loose their start state status. */ + unsetStartState(); + other->unsetStartState(); + + /* Bring in the rest of other's entry points. */ + copyInEntryPoints( other ); + other->entryPoints.empty(); + + /* Merge the lists. This will move all the states from other + * into this. No states will be deleted. */ + stateList.append( other->stateList ); + misfitList.append( other->misfitList ); + + /* Move the final set data from other into this. */ + finStateSet.insert(other->finStateSet); + other->finStateSet.empty(); + + /* Since other's list is empty, we can delete the fsm without + * affecting any states. */ + delete other; + + /* Create a new start state. */ + setStartState( addState() ); + + /* Merge the start states. */ + mergeStates( md, startState, startStateSet.data, startStateSet.length() ); + + /* Fill in any new states made from merging. */ + fillInStates( md ); +} + +/* Unions other with this machine. Other is deleted. */ +void FsmAp::unionOp( FsmAp *other ) +{ + /* Turn on misfit accounting for both graphs. */ + setMisfitAccounting( true ); + other->setMisfitAccounting( true ); + + /* Call Worker routine. */ + doOr( other ); + + /* Remove the misfits and turn off misfit accounting. */ + removeMisfits(); + setMisfitAccounting( false ); +} + +/* Intersects other with this machine. Other is deleted. */ +void FsmAp::intersectOp( FsmAp *other ) +{ + /* Turn on misfit accounting for both graphs. */ + setMisfitAccounting( true ); + other->setMisfitAccounting( true ); + + /* Set the fin bits on this and other to want each other. */ + setFinBits( SB_GRAPH1 ); + other->setFinBits( SB_GRAPH2 ); + + /* Call worker Or routine. */ + doOr( other ); + + /* Unset any final states that are no longer to + * be final due to final bits. */ + unsetIncompleteFinals(); + + /* Remove the misfits and turn off misfit accounting. */ + removeMisfits(); + setMisfitAccounting( false ); + + /* Remove states that have no path to a final state. */ + removeDeadEndStates(); +} + +/* Set subtracts other machine from this machine. Other is deleted. */ +void FsmAp::subtractOp( FsmAp *other ) +{ + /* Turn on misfit accounting for both graphs. */ + setMisfitAccounting( true ); + other->setMisfitAccounting( true ); + + /* Set the fin bits of other to be killers. */ + other->setFinBits( SB_GRAPH1 ); + + /* Call worker Or routine. */ + doOr( other ); + + /* Unset any final states that are no longer to + * be final due to final bits. */ + unsetKilledFinals(); + + /* Remove the misfits and turn off misfit accounting. */ + removeMisfits(); + setMisfitAccounting( false ); + + /* Remove states that have no path to a final state. */ + removeDeadEndStates(); +} + +bool FsmAp::inEptVect( EptVect *eptVect, StateAp *state ) +{ + if ( eptVect != 0 ) { + /* Vect is there, walk it looking for state. */ + for ( int i = 0; i < eptVect->length(); i++ ) { + if ( eptVect->data[i].targ == state ) + return true; + } + } + return false; +} + +/* Fill epsilon vectors in a root state from a given starting point. Epmploys + * a depth first search through the graph of epsilon transitions. */ +void FsmAp::epsilonFillEptVectFrom( StateAp *root, StateAp *from, bool parentLeaving ) +{ + /* Walk the epsilon transitions out of the state. */ + for ( EpsilonTrans::Iter ep = from->epsilonTrans; ep.lte(); ep++ ) { + /* Find the entry point, if the it does not resove, ignore it. */ + EntryMapEl *enLow, *enHigh; + if ( entryPoints.findMulti( *ep, enLow, enHigh ) ) { + /* Loop the targets. */ + for ( EntryMapEl *en = enLow; en <= enHigh; en++ ) { + /* Do not add the root or states already in eptVect. */ + StateAp *targ = en->value; + if ( targ != from && !inEptVect(root->eptVect, targ) ) { + /* Maybe need to create the eptVect. */ + if ( root->eptVect == 0 ) + root->eptVect = new EptVect(); + + /* If moving to a different graph or if any parent is + * leaving then we are leaving. */ + bool leaving = parentLeaving || + root->owningGraph != targ->owningGraph; + + /* All ok, add the target epsilon and recurse. */ + root->eptVect->append( EptVectEl(targ, leaving) ); + epsilonFillEptVectFrom( root, targ, leaving ); + } + } + } + } +} + +void FsmAp::shadowReadWriteStates( MergeData &md ) +{ + /* Init isolatedShadow algorithm data. */ + for ( StateList::Iter st = stateList; st.lte(); st++ ) + st->isolatedShadow = 0; + + /* Any states that may be both read from and written to must + * be shadowed. */ + for ( StateList::Iter st = stateList; st.lte(); st++ ) { + /* Find such states by looping through stateVect lists, which give us + * the states that will be read from. May cause us to visit the states + * that we are interested in more than once. */ + if ( st->eptVect != 0 ) { + /* For all states that will be read from. */ + for ( EptVect::Iter ept = *st->eptVect; ept.lte(); ept++ ) { + /* Check for read and write to the same state. */ + StateAp *targ = ept->targ; + if ( targ->eptVect != 0 ) { + /* State is to be written to, if the shadow is not already + * there, create it. */ + if ( targ->isolatedShadow == 0 ) { + StateAp *shadow = addState(); + mergeStates( md, shadow, targ ); + targ->isolatedShadow = shadow; + } + + /* Write shadow into the state vector so that it is the + * state that the epsilon transition will read from. */ + ept->targ = targ->isolatedShadow; + } + } + } + } +} + +void FsmAp::resolveEpsilonTrans( MergeData &md ) +{ + /* Walk the state list and invoke recursive worker on each state. */ + for ( StateList::Iter st = stateList; st.lte(); st++ ) + epsilonFillEptVectFrom( st, st, false ); + + /* Prevent reading from and writing to of the same state. */ + shadowReadWriteStates( md ); + + /* For all states that have epsilon transitions out, draw the transitions, + * clear the epsilon transitions. */ + for ( StateList::Iter st = stateList; st.lte(); st++ ) { + /* If there is a state vector, then create the pre-merge state. */ + if ( st->eptVect != 0 ) { + /* Merge all the epsilon targets into the state. */ + for ( EptVect::Iter ept = *st->eptVect; ept.lte(); ept++ ) { + if ( ept->leaving ) + mergeStatesLeaving( md, st, ept->targ ); + else + mergeStates( md, st, ept->targ ); + } + + /* Clean up the target list. */ + delete st->eptVect; + st->eptVect = 0; + } + + /* Clear the epsilon transitions vector. */ + st->epsilonTrans.empty(); + } +} + +void FsmAp::epsilonOp() +{ + /* For merging process. */ + MergeData md; + + setMisfitAccounting( true ); + + for ( StateList::Iter st = stateList; st.lte(); st++ ) + st->owningGraph = 0; + + /* Perform merges. */ + resolveEpsilonTrans( md ); + + /* Epsilons can caused merges which leave behind unreachable states. */ + fillInStates( md ); + + /* Remove the misfits and turn off misfit accounting. */ + removeMisfits(); + setMisfitAccounting( false ); +} + +/* Make a new maching by joining together a bunch of machines without making + * any transitions between them. A negative finalId results in there being no + * final id. */ +void FsmAp::joinOp( int startId, int finalId, FsmAp **others, int numOthers ) +{ + /* For the merging process. */ + MergeData md; + + /* Set the owning machines. Start at one. Zero is reserved for the start + * and final states. */ + for ( StateList::Iter st = stateList; st.lte(); st++ ) + st->owningGraph = 1; + for ( int m = 0; m < numOthers; m++ ) { + for ( StateList::Iter st = others[m]->stateList; st.lte(); st++ ) + st->owningGraph = 2+m; + } + + /* All machines loose start state status. */ + unsetStartState(); + for ( int m = 0; m < numOthers; m++ ) + others[m]->unsetStartState(); + + /* Bring the other machines into this. */ + for ( int m = 0; m < numOthers; m++ ) { + /* Bring in the rest of other's entry points. */ + copyInEntryPoints( others[m] ); + others[m]->entryPoints.empty(); + + /* Merge the lists. This will move all the states from other into + * this. No states will be deleted. */ + stateList.append( others[m]->stateList ); + assert( others[m]->misfitList.length() == 0 ); + + /* Move the final set data from other into this. */ + finStateSet.insert( others[m]->finStateSet ); + others[m]->finStateSet.empty(); + + /* Since other's list is empty, we can delete the fsm without + * affecting any states. */ + delete others[m]; + } + + /* Look up the start entry point. */ + EntryMapEl *enLow = 0, *enHigh = 0; + bool findRes = entryPoints.findMulti( startId, enLow, enHigh ); + if ( ! findRes ) { + /* No start state. Set a default one and proceed with the join. Note + * that the result of the join will be a very uninteresting machine. */ + setStartState( addState() ); + } + else { + /* There is at least one start state, create a state that will become + * the new start state. */ + StateAp *newStart = addState(); + setStartState( newStart ); + + /* The start state is in an owning machine class all it's own. */ + newStart->owningGraph = 0; + + /* Create the set of states to merge from. */ + StateSet stateSet; + for ( EntryMapEl *en = enLow; en <= enHigh; en++ ) + stateSet.insert( en->value ); + + /* Merge in the set of start states into the new start state. */ + mergeStates( md, newStart, stateSet.data, stateSet.length() ); + } + + /* Take a copy of the final state set, before unsetting them all. This + * will allow us to call clearOutData on the states that don't get + * final state status back back. */ + StateSet finStateSetCopy = finStateSet; + + /* Now all final states are unset. */ + unsetAllFinStates(); + + if ( finalId >= 0 ) { + /* Create the implicit final state. */ + StateAp *finState = addState(); + setFinState( finState ); + + /* Assign an entry into the final state on the final state entry id. Note + * that there may already be an entry on this id. That's ok. Also set the + * final state owning machine id. It's in a class all it's own. */ + setEntry( finalId, finState ); + finState->owningGraph = 0; + } + + /* Hand over to workers for resolving epsilon trans. This will merge states + * with the targets of their epsilon transitions. */ + resolveEpsilonTrans( md ); + + /* Invoke the relinquish final callback on any states that did not get + * final state status back. */ + for ( StateSet::Iter st = finStateSetCopy; st.lte(); st++ ) { + if ( !((*st)->stateBits & SB_ISFINAL) ) + clearOutData( *st ); + } + + /* Fill in any new states made from merging. */ + fillInStates( md ); + + /* Joining can be messy. Instead of having misfit accounting on (which is + * tricky here) do a full cleaning. */ + removeUnreachableStates(); +} + +void FsmAp::globOp( FsmAp **others, int numOthers ) +{ + /* All other machines loose start states status. */ + for ( int m = 0; m < numOthers; m++ ) + others[m]->unsetStartState(); + + /* Bring the other machines into this. */ + for ( int m = 0; m < numOthers; m++ ) { + /* Bring in the rest of other's entry points. */ + copyInEntryPoints( others[m] ); + others[m]->entryPoints.empty(); + + /* Merge the lists. This will move all the states from other into + * this. No states will be deleted. */ + stateList.append( others[m]->stateList ); + assert( others[m]->misfitList.length() == 0 ); + + /* Move the final set data from other into this. */ + finStateSet.insert( others[m]->finStateSet ); + others[m]->finStateSet.empty(); + + /* Since other's list is empty, we can delete the fsm without + * affecting any states. */ + delete others[m]; + } +} + +void FsmAp::deterministicEntry() +{ + /* For the merging process. */ + MergeData md; + + /* States may loose their entry points, turn on misfit accounting. */ + setMisfitAccounting( true ); + + /* Get a copy of the entry map then clear all the entry points. As we + * iterate the old entry map finding duplicates we will add the entry + * points for the new states that we create. */ + EntryMap prevEntry = entryPoints; + unsetAllEntryPoints(); + + for ( int enId = 0; enId < prevEntry.length(); ) { + /* Count the number of states on this entry key. */ + int highId = enId; + while ( highId < prevEntry.length() && prevEntry[enId].key == prevEntry[highId].key ) + highId += 1; + + int numIds = highId - enId; + if ( numIds == 1 ) { + /* Only a single entry point, just set the entry. */ + setEntry( prevEntry[enId].key, prevEntry[enId].value ); + } + else { + /* Multiple entry points, need to create a new state and merge in + * all the targets of entry points. */ + StateAp *newEntry = addState(); + for ( int en = enId; en < highId; en++ ) + mergeStates( md, newEntry, prevEntry[en].value ); + + /* Add the new state as the single entry point. */ + setEntry( prevEntry[enId].key, newEntry ); + } + + enId += numIds; + } + + /* The old start state may be unreachable. Remove the misfits and turn off + * misfit accounting. */ + removeMisfits(); + setMisfitAccounting( false ); +} + +/* Unset any final states that are no longer to be final due to final bits. */ +void FsmAp::unsetKilledFinals() +{ + /* Duplicate the final state set before we begin modifying it. */ + StateSet fin( finStateSet ); + + for ( int s = 0; s < fin.length(); s++ ) { + /* Check for killing bit. */ + StateAp *state = fin.data[s]; + if ( state->stateBits & SB_GRAPH1 ) { + /* One final state is a killer, set to non-final. */ + unsetFinState( state ); + } + + /* Clear all killing bits. Non final states should never have had those + * state bits set in the first place. */ + state->stateBits &= ~SB_GRAPH1; + } +} + +/* Unset any final states that are no longer to be final due to final bits. */ +void FsmAp::unsetIncompleteFinals() +{ + /* Duplicate the final state set before we begin modifying it. */ + StateSet fin( finStateSet ); + + for ( int s = 0; s < fin.length(); s++ ) { + /* Check for one set but not the other. */ + StateAp *state = fin.data[s]; + if ( state->stateBits & SB_BOTH && + (state->stateBits & SB_BOTH) != SB_BOTH ) + { + /* One state wants the other but it is not there. */ + unsetFinState( state ); + } + + /* Clear wanting bits. Non final states should never have had those + * state bits set in the first place. */ + state->stateBits &= ~SB_BOTH; + } +} + +/* Ensure that the start state is free of entry points (aside from the fact + * that it is the start state). If the start state has entry points then Make a + * new start state by merging with the old one. Useful before modifying start + * transitions. If the existing start state has any entry points other than the + * start state entry then modifying its transitions changes more than the start + * transitions. So isolate the start state by separating it out such that it + * only has start stateness as it's entry point. */ +void FsmAp::isolateStartState( ) +{ + /* For the merging process. */ + MergeData md; + + /* Bail out if the start state is already isolated. */ + if ( isStartStateIsolated() ) + return; + + /* Turn on misfit accounting to possibly catch the old start state. */ + setMisfitAccounting( true ); + + /* This will be the new start state. The existing start + * state is merged with it. */ + StateAp *prevStartState = startState; + unsetStartState(); + setStartState( addState() ); + + /* Merge the new start state with the old one to isolate it. */ + mergeStates( md, startState, prevStartState ); + + /* Stfil and stateDict will be empty because the merging of the old start + * state into the new one will not have any conflicting transitions. */ + assert( md.stateDict.treeSize == 0 ); + assert( md.stfillHead == 0 ); + + /* The old start state may be unreachable. Remove the misfits and turn off + * misfit accounting. */ + removeMisfits(); + setMisfitAccounting( false ); +} + +#ifdef LOG_CONDS +void logCondSpace( CondSpace *condSpace ) +{ + if ( condSpace == 0 ) + cerr << "<empty>"; + else { + for ( CondSet::Iter csi = condSpace->condSet.last(); csi.gtb(); csi-- ) { + if ( ! csi.last() ) + cerr << ','; + (*csi)->actionName( cerr ); + } + } +} + +void logNewExpansion( Expansion *exp ) +{ + cerr << "created expansion:" << endl; + cerr << " range: " << exp->lowKey.getVal() << " .. " << + exp->highKey.getVal() << endl; + + cerr << " fromCondSpace: "; + logCondSpace( exp->fromCondSpace ); + cerr << endl; + cerr << " fromVals: " << exp->fromVals << endl; + + cerr << " toCondSpace: "; + logCondSpace( exp->toCondSpace ); + cerr << endl; + cerr << " toValsList: "; + for ( LongVect::Iter to = exp->toValsList; to.lte(); to++ ) + cerr << " " << *to; + cerr << endl; +} +#endif + + +void FsmAp::findTransExpansions( ExpansionList &expansionList, + StateAp *destState, StateAp *srcState ) +{ + PairIter<TransAp, StateCond> transCond( destState->outList.head, + srcState->stateCondList.head ); + for ( ; !transCond.end(); transCond++ ) { + if ( transCond.userState == RangeOverlap ) { + Expansion *expansion = new Expansion( transCond.s1Tel.lowKey, + transCond.s1Tel.highKey ); + expansion->fromTrans = new TransAp(*transCond.s1Tel.trans); + expansion->fromTrans->fromState = 0; + expansion->fromTrans->toState = transCond.s1Tel.trans->toState; + expansion->fromCondSpace = 0; + expansion->fromVals = 0; + CondSpace *srcCS = transCond.s2Tel.trans->condSpace; + expansion->toCondSpace = srcCS; + + long numTargVals = (1 << srcCS->condSet.length()); + for ( long targVals = 0; targVals < numTargVals; targVals++ ) + expansion->toValsList.append( targVals ); + + #ifdef LOG_CONDS + logNewExpansion( expansion ); + #endif + expansionList.append( expansion ); + } + } +} + +void FsmAp::findCondExpInTrans( ExpansionList &expansionList, StateAp *state, + Key lowKey, Key highKey, CondSpace *fromCondSpace, CondSpace *toCondSpace, + long fromVals, LongVect &toValsList ) +{ + TransAp searchTrans; + searchTrans.lowKey = fromCondSpace->baseKey + fromVals * keyOps->alphSize() + + (lowKey - keyOps->minKey); + searchTrans.highKey = fromCondSpace->baseKey + fromVals * keyOps->alphSize() + + (highKey - keyOps->minKey); + searchTrans.prev = searchTrans.next = 0; + + PairIter<TransAp> pairIter( state->outList.head, &searchTrans ); + for ( ; !pairIter.end(); pairIter++ ) { + if ( pairIter.userState == RangeOverlap ) { + Expansion *expansion = new Expansion( lowKey, highKey ); + expansion->fromTrans = new TransAp(*pairIter.s1Tel.trans); + expansion->fromTrans->fromState = 0; + expansion->fromTrans->toState = pairIter.s1Tel.trans->toState; + expansion->fromCondSpace = fromCondSpace; + expansion->fromVals = fromVals; + expansion->toCondSpace = toCondSpace; + expansion->toValsList = toValsList; + + expansionList.append( expansion ); + #ifdef LOG_CONDS + logNewExpansion( expansion ); + #endif + } + } +} + +void FsmAp::findCondExpansions( ExpansionList &expansionList, + StateAp *destState, StateAp *srcState ) +{ + PairIter<StateCond, StateCond> condCond( destState->stateCondList.head, + srcState->stateCondList.head ); + for ( ; !condCond.end(); condCond++ ) { + if ( condCond.userState == RangeOverlap ) { + /* Loop over all existing condVals . */ + CondSet &destCS = condCond.s1Tel.trans->condSpace->condSet; + long destLen = destCS.length(); + + /* Find the items in src cond set that are not in dest + * cond set. These are the items that we must expand. */ + CondSet srcOnlyCS = condCond.s2Tel.trans->condSpace->condSet; + for ( CondSet::Iter dcsi = destCS; dcsi.lte(); dcsi++ ) + srcOnlyCS.remove( *dcsi ); + long srcOnlyLen = srcOnlyCS.length(); + + if ( srcOnlyCS.length() > 0 ) { + #ifdef LOG_CONDS + cerr << "there are " << srcOnlyCS.length() << " item(s) that are " + "only in the srcCS" << endl; + #endif + + CondSet mergedCS = destCS; + mergedCS.insert( condCond.s2Tel.trans->condSpace->condSet ); + + CondSpace *fromCondSpace = addCondSpace( destCS ); + CondSpace *toCondSpace = addCondSpace( mergedCS ); + + /* Loop all values in the dest space. */ + for ( long destVals = 0; destVals < (1 << destLen); destVals++ ) { + long basicVals = 0; + for ( CondSet::Iter csi = destCS; csi.lte(); csi++ ) { + if ( destVals & (1 << csi.pos()) ) { + Action **cim = mergedCS.find( *csi ); + long bitPos = (cim - mergedCS.data); + basicVals |= 1 << bitPos; + } + } + + /* Loop all new values. */ + LongVect expandToVals; + for ( long soVals = 0; soVals < (1 << srcOnlyLen); soVals++ ) { + long targVals = basicVals; + for ( CondSet::Iter csi = srcOnlyCS; csi.lte(); csi++ ) { + if ( soVals & (1 << csi.pos()) ) { + Action **cim = mergedCS.find( *csi ); + long bitPos = (cim - mergedCS.data); + targVals |= 1 << bitPos; + } + } + expandToVals.append( targVals ); + } + + findCondExpInTrans( expansionList, destState, + condCond.s1Tel.lowKey, condCond.s1Tel.highKey, + fromCondSpace, toCondSpace, destVals, expandToVals ); + } + } + } + } +} + +void FsmAp::doExpand( MergeData &md, StateAp *destState, ExpansionList &expList1 ) +{ + for ( ExpansionList::Iter exp = expList1; exp.lte(); exp++ ) { + for ( LongVect::Iter to = exp->toValsList; to.lte(); to++ ) { + long targVals = *to; + + /* We will use the copy of the transition that was made when the + * expansion was created. It will get used multiple times. Each + * time we must set up the keys, everything else is constant and + * and already prepared. */ + TransAp *srcTrans = exp->fromTrans; + + srcTrans->lowKey = exp->toCondSpace->baseKey + + targVals * keyOps->alphSize() + (exp->lowKey - keyOps->minKey); + srcTrans->highKey = exp->toCondSpace->baseKey + + targVals * keyOps->alphSize() + (exp->highKey - keyOps->minKey); + + TransList srcList; + srcList.append( srcTrans ); + outTransCopy( md, destState, srcList.head ); + srcList.abandon(); + } + } +} + + +void FsmAp::doRemove( MergeData &md, StateAp *destState, ExpansionList &expList1 ) +{ + for ( ExpansionList::Iter exp = expList1; exp.lte(); exp++ ) { + Removal removal; + if ( exp->fromCondSpace == 0 ) { + removal.lowKey = exp->lowKey; + removal.highKey = exp->highKey; + } + else { + removal.lowKey = exp->fromCondSpace->baseKey + + exp->fromVals * keyOps->alphSize() + (exp->lowKey - keyOps->minKey); + removal.highKey = exp->fromCondSpace->baseKey + + exp->fromVals * keyOps->alphSize() + (exp->highKey - keyOps->minKey); + } + removal.next = 0; + + TransList destList; + PairIter<TransAp, Removal> pairIter( destState->outList.head, &removal ); + for ( ; !pairIter.end(); pairIter++ ) { + switch ( pairIter.userState ) { + case RangeInS1: { + TransAp *destTrans = pairIter.s1Tel.trans; + destTrans->lowKey = pairIter.s1Tel.lowKey; + destTrans->highKey = pairIter.s1Tel.highKey; + destList.append( destTrans ); + break; + } + case RangeInS2: + break; + case RangeOverlap: { + TransAp *trans = pairIter.s1Tel.trans; + detachTrans( trans->fromState, trans->toState, trans ); + delete trans; + break; + } + case BreakS1: { + pairIter.s1Tel.trans = dupTrans( destState, + pairIter.s1Tel.trans ); + break; + } + case BreakS2: + break; + } + } + destState->outList.transfer( destList ); + } +} + +void FsmAp::mergeStateConds( StateAp *destState, StateAp *srcState ) +{ + StateCondList destList; + PairIter<StateCond> pairIter( destState->stateCondList.head, + srcState->stateCondList.head ); + for ( ; !pairIter.end(); pairIter++ ) { + switch ( pairIter.userState ) { + case RangeInS1: { + StateCond *destCond = pairIter.s1Tel.trans; + destCond->lowKey = pairIter.s1Tel.lowKey; + destCond->highKey = pairIter.s1Tel.highKey; + destList.append( destCond ); + break; + } + case RangeInS2: { + StateCond *newCond = new StateCond( *pairIter.s2Tel.trans ); + newCond->lowKey = pairIter.s2Tel.lowKey; + newCond->highKey = pairIter.s2Tel.highKey; + destList.append( newCond ); + break; + } + case RangeOverlap: { + StateCond *destCond = pairIter.s1Tel.trans; + StateCond *srcCond = pairIter.s2Tel.trans; + CondSet mergedCondSet; + mergedCondSet.insert( destCond->condSpace->condSet ); + mergedCondSet.insert( srcCond->condSpace->condSet ); + destCond->condSpace = addCondSpace( mergedCondSet ); + + destCond->lowKey = pairIter.s1Tel.lowKey; + destCond->highKey = pairIter.s1Tel.highKey; + destList.append( destCond ); + break; + } + case BreakS1: + pairIter.s1Tel.trans = new StateCond( *pairIter.s1Tel.trans ); + break; + + case BreakS2: + break; + } + } + destState->stateCondList.transfer( destList ); +} + +/* A state merge which represents the drawing in of leaving transitions. If + * there is any out data then we duplicate the souce state, transfer the out + * data, then merge in the state. The new state will be reaped because it will + * not be given any in transitions. */ +void FsmAp::mergeStatesLeaving( MergeData &md, StateAp *destState, StateAp *srcState ) +{ + if ( !hasOutData( destState ) ) + mergeStates( md, destState, srcState ); + else { + StateAp *ssMutable = addState(); + mergeStates( md, ssMutable, srcState ); + transferOutData( ssMutable, destState ); + + for ( ActionSet::Iter cond = destState->outCondSet; cond.lte(); cond++ ) + embedCondition( md, ssMutable, *cond ); + + mergeStates( md, destState, ssMutable ); + } +} + +void FsmAp::mergeStates( MergeData &md, StateAp *destState, + StateAp **srcStates, int numSrc ) +{ + for ( int s = 0; s < numSrc; s++ ) + mergeStates( md, destState, srcStates[s] ); +} + +void FsmAp::mergeStates( MergeData &md, StateAp *destState, StateAp *srcState ) +{ + ExpansionList expList1; + ExpansionList expList2; + + findTransExpansions( expList1, destState, srcState ); + findCondExpansions( expList1, destState, srcState ); + findTransExpansions( expList2, srcState, destState ); + findCondExpansions( expList2, srcState, destState ); + + mergeStateConds( destState, srcState ); + + outTransCopy( md, destState, srcState->outList.head ); + + doExpand( md, destState, expList1 ); + doExpand( md, destState, expList2 ); + + doRemove( md, destState, expList1 ); + doRemove( md, destState, expList2 ); + + expList1.empty(); + expList2.empty(); + + /* Get its bits and final state status. */ + destState->stateBits |= ( srcState->stateBits & ~SB_ISFINAL ); + if ( srcState->isFinState() ) + setFinState( destState ); + + /* Draw in any properties of srcState into destState. */ + if ( srcState == destState ) { + /* Duplicate the list to protect against write to source. The + * priorities sets are not copied in because that would have no + * effect. */ + destState->epsilonTrans.append( EpsilonTrans( srcState->epsilonTrans ) ); + + /* Get all actions, duplicating to protect against write to source. */ + destState->toStateActionTable.setActions( + ActionTable( srcState->toStateActionTable ) ); + destState->fromStateActionTable.setActions( + ActionTable( srcState->fromStateActionTable ) ); + destState->outActionTable.setActions( ActionTable( srcState->outActionTable ) ); + destState->outCondSet.insert( ActionSet( srcState->outCondSet ) ); + destState->errActionTable.setActions( ErrActionTable( srcState->errActionTable ) ); + destState->eofActionTable.setActions( ActionTable( srcState->eofActionTable ) ); + } + else { + /* Get the epsilons, out priorities. */ + destState->epsilonTrans.append( srcState->epsilonTrans ); + destState->outPriorTable.setPriors( srcState->outPriorTable ); + + /* Get all actions. */ + destState->toStateActionTable.setActions( srcState->toStateActionTable ); + destState->fromStateActionTable.setActions( srcState->fromStateActionTable ); + destState->outActionTable.setActions( srcState->outActionTable ); + destState->outCondSet.insert( srcState->outCondSet ); + destState->errActionTable.setActions( srcState->errActionTable ); + destState->eofActionTable.setActions( srcState->eofActionTable ); + } +} + +void FsmAp::fillInStates( MergeData &md ) +{ + /* Merge any states that are awaiting merging. This will likey cause + * other states to be added to the stfil list. */ + StateAp *state = md.stfillHead; + while ( state != 0 ) { + StateSet *stateSet = &state->stateDictEl->stateSet; + mergeStates( md, state, stateSet->data, stateSet->length() ); + state = state->alg.next; + } + + /* Delete the state sets of all states that are on the fill list. */ + state = md.stfillHead; + while ( state != 0 ) { + /* Delete and reset the state set. */ + delete state->stateDictEl; + state->stateDictEl = 0; + + /* Next state in the stfill list. */ + state = state->alg.next; + } + + /* StateDict will still have its ptrs/size set but all of it's element + * will be deleted so we don't need to clean it up. */ +} + +void FsmAp::findEmbedExpansions( ExpansionList &expansionList, + StateAp *destState, Action *condAction ) +{ + StateCondList destList; + PairIter<TransAp, StateCond> transCond( destState->outList.head, + destState->stateCondList.head ); + for ( ; !transCond.end(); transCond++ ) { + switch ( transCond.userState ) { + case RangeInS1: { + if ( transCond.s1Tel.lowKey <= keyOps->maxKey ) { + assert( transCond.s1Tel.highKey <= keyOps->maxKey ); + + /* Make a new state cond. */ + StateCond *newStateCond = new StateCond( transCond.s1Tel.lowKey, + transCond.s1Tel.highKey ); + newStateCond->condSpace = addCondSpace( CondSet( condAction ) ); + destList.append( newStateCond ); + + /* Create the expansion. */ + Expansion *expansion = new Expansion( transCond.s1Tel.lowKey, + transCond.s1Tel.highKey ); + expansion->fromTrans = new TransAp(*transCond.s1Tel.trans); + expansion->fromTrans->fromState = 0; + expansion->fromTrans->toState = transCond.s1Tel.trans->toState; + expansion->fromCondSpace = 0; + expansion->fromVals = 0; + expansion->toCondSpace = newStateCond->condSpace; + expansion->toValsList.append( 1 ); + #ifdef LOG_CONDS + logNewExpansion( expansion ); + #endif + expansionList.append( expansion ); + } + break; + } + case RangeInS2: { + /* Enhance state cond and find the expansion. */ + StateCond *stateCond = transCond.s2Tel.trans; + stateCond->lowKey = transCond.s2Tel.lowKey; + stateCond->highKey = transCond.s2Tel.highKey; + + CondSet &destCS = stateCond->condSpace->condSet; + long destLen = destCS.length(); + CondSpace *fromCondSpace = stateCond->condSpace; + + CondSet mergedCS = destCS; + mergedCS.insert( condAction ); + CondSpace *toCondSpace = addCondSpace( mergedCS ); + stateCond->condSpace = toCondSpace; + destList.append( stateCond ); + + /* Loop all values in the dest space. */ + for ( long destVals = 0; destVals < (1 << destLen); destVals++ ) { + long basicVals = 0; + for ( CondSet::Iter csi = destCS; csi.lte(); csi++ ) { + if ( destVals & (1 << csi.pos()) ) { + Action **cim = mergedCS.find( *csi ); + long bitPos = (cim - mergedCS.data); + basicVals |= 1 << bitPos; + } + } + + long targVals = basicVals; + Action **cim = mergedCS.find( condAction ); + long bitPos = (cim - mergedCS.data); + targVals |= 1 << bitPos; + + LongVect expandToVals( targVals ); + findCondExpInTrans( expansionList, destState, + transCond.s2Tel.lowKey, transCond.s2Tel.highKey, + fromCondSpace, toCondSpace, destVals, expandToVals ); + } + break; + } + + + case RangeOverlap: + case BreakS1: + case BreakS2: + assert( false ); + break; + } + } + + destState->stateCondList.transfer( destList ); +} + +void FsmAp::embedCondition( StateAp *state, Action *condAction ) +{ + MergeData md; + ExpansionList expList; + + /* Turn on misfit accounting to possibly catch the old start state. */ + setMisfitAccounting( true ); + + /* Worker. */ + embedCondition( md, state, condAction ); + + /* Fill in any states that were newed up as combinations of others. */ + fillInStates( md ); + + /* Remove the misfits and turn off misfit accounting. */ + removeMisfits(); + setMisfitAccounting( false ); +} + +void FsmAp::embedCondition( MergeData &md, StateAp *state, Action *condAction ) +{ + ExpansionList expList; + + findEmbedExpansions( expList, state, condAction ); + doExpand( md, state, expList ); + doRemove( md, state, expList ); + expList.empty(); +} + +/* Check if a machine defines a single character. This is useful in validating + * ranges and machines to export. */ +bool FsmAp::checkSingleCharMachine() +{ + /* Must have two states. */ + if ( stateList.length() != 2 ) + return false; + /* The start state cannot be final. */ + if ( startState->isFinState() ) + return false; + /* There should be only one final state. */ + if ( finStateSet.length() != 1 ) + return false; + /* The final state cannot have any transitions out. */ + if ( finStateSet[0]->outList.length() != 0 ) + return false; + /* The start state should have only one transition out. */ + if ( startState->outList.length() != 1 ) + return false; + /* The singe transition out of the start state should not be a range. */ + TransAp *startTrans = startState->outList.head; + if ( startTrans->lowKey != startTrans->highKey ) + return false; + return true; +} + diff --git a/contrib/tools/ragel5/ragel/fsmgraph.h b/contrib/tools/ragel5/ragel/fsmgraph.h new file mode 100644 index 00000000000..062031c3aa8 --- /dev/null +++ b/contrib/tools/ragel5/ragel/fsmgraph.h @@ -0,0 +1,1482 @@ +/* + * Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _FSMGRAPH_H +#define _FSMGRAPH_H + +#include <assert.h> +#include <iostream> +#include "common.h" +#include "vector.h" +#include "bstset.h" +#include "compare.h" +#include "avltree.h" +#include "dlist.h" +#include "bstmap.h" +#include "sbstmap.h" +#include "sbstset.h" +#include "sbsttable.h" +#include "avlset.h" +#include "avlmap.h" +#include "ragel.h" + +//#define LOG_CONDS + +/* Flags that control merging. */ +#define SB_GRAPH1 0x01 +#define SB_GRAPH2 0x02 +#define SB_BOTH 0x03 +#define SB_ISFINAL 0x04 +#define SB_ISMARKED 0x08 +#define SB_ONLIST 0x10 + +using std::ostream; + +struct TransAp; +struct StateAp; +struct FsmAp; +struct Action; +struct LongestMatchPart; + +/* State list element for unambiguous access to list element. */ +struct FsmListEl +{ + StateAp *prev, *next; +}; + +/* This is the marked index for a state pair. Used in minimization. It keeps + * track of whether or not the state pair is marked. */ +struct MarkIndex +{ + MarkIndex(int states); + ~MarkIndex(); + + void markPair(int state1, int state2); + bool isPairMarked(int state1, int state2); + +private: + int numStates; + bool *array; +}; + +extern KeyOps *keyOps; + +/* Transistion Action Element. */ +typedef SBstMapEl< int, Action* > ActionTableEl; + +/* Nodes in the tree that use this action. */ +struct NameInst; +struct InlineList; +typedef Vector<NameInst*> ActionRefs; + +/* Element in list of actions. Contains the string for the code to exectute. */ +struct Action +: + public DListEl<Action>, + public AvlTreeEl<Action> +{ +public: + + Action( const InputLoc &loc, const char *name, InlineList *inlineList, int condId ) + : + loc(loc), + name(name), + inlineList(inlineList), + actionId(-1), + numTransRefs(0), + numToStateRefs(0), + numFromStateRefs(0), + numEofRefs(0), + numCondRefs(0), + anyCall(false), + isLmAction(false), + condId(condId) + { + } + + /* Key for action dictionary. */ + const char *getKey() const { return name; } + + /* Data collected during parse. */ + InputLoc loc; + const char *name; + InlineList *inlineList; + int actionId; + + void actionName( ostream &out ) + { + if ( name != 0 ) + out << name; + else + out << loc.line << ":" << loc.col; + } + + /* Places in the input text that reference the action. */ + ActionRefs actionRefs; + + /* Number of references in the final machine. */ + int numRefs() + { return numTransRefs + numToStateRefs + numFromStateRefs + numEofRefs; } + int numTransRefs; + int numToStateRefs; + int numFromStateRefs; + int numEofRefs; + int numCondRefs; + bool anyCall; + + bool isLmAction; + int condId; +}; + +struct CmpCondId +{ + static inline int compare( const Action *cond1, const Action *cond2 ) + { + if ( cond1->condId < cond2->condId ) + return -1; + else if ( cond1->condId > cond2->condId ) + return 1; + return 0; + } +}; + +/* A list of actions. */ +typedef DList<Action> ActionList; +typedef AvlTree<Action, char *, CmpStr> ActionDict; + +/* Structure for reverse action mapping. */ +struct RevActionMapEl +{ + char *name; + InputLoc location; +}; + + +/* Transition Action Table. */ +struct ActionTable + : public SBstMap< int, Action*, CmpOrd<int> > +{ + void setAction( int ordering, Action *action ); + void setActions( int *orderings, Action **actions, int nActs ); + void setActions( const ActionTable &other ); + + bool hasAction( Action *action ); +}; + +typedef SBstSet< Action*, CmpOrd<Action*> > ActionSet; +typedef CmpSTable< Action*, CmpOrd<Action*> > CmpActionSet; + +/* Transistion Action Element. */ +typedef SBstMapEl< int, LongestMatchPart* > LmActionTableEl; + +/* Transition Action Table. */ +struct LmActionTable + : public SBstMap< int, LongestMatchPart*, CmpOrd<int> > +{ + void setAction( int ordering, LongestMatchPart *action ); + void setActions( const LmActionTable &other ); +}; + +/* Compare of a whole action table element (key & value). */ +struct CmpActionTableEl +{ + static int compare( const ActionTableEl &action1, + const ActionTableEl &action2 ) + { + if ( action1.key < action2.key ) + return -1; + else if ( action1.key > action2.key ) + return 1; + else if ( action1.value < action2.value ) + return -1; + else if ( action1.value > action2.value ) + return 1; + return 0; + } +}; + +/* Compare for ActionTable. */ +typedef CmpSTable< ActionTableEl, CmpActionTableEl > CmpActionTable; + +/* Compare of a whole lm action table element (key & value). */ +struct CmpLmActionTableEl +{ + static int compare( const LmActionTableEl &lmAction1, + const LmActionTableEl &lmAction2 ) + { + if ( lmAction1.key < lmAction2.key ) + return -1; + else if ( lmAction1.key > lmAction2.key ) + return 1; + else if ( lmAction1.value < lmAction2.value ) + return -1; + else if ( lmAction1.value > lmAction2.value ) + return 1; + return 0; + } +}; + +/* Compare for ActionTable. */ +typedef CmpSTable< LmActionTableEl, CmpLmActionTableEl > CmpLmActionTable; + +/* Action table element for error action tables. Adds the encoding of transfer + * point. */ +struct ErrActionTableEl +{ + ErrActionTableEl( Action *action, int ordering, int transferPoint ) + : ordering(ordering), action(action), transferPoint(transferPoint) { } + + /* Ordering and id of the action embedding. */ + int ordering; + Action *action; + + /* Id of point of transfere from Error action table to transtions and + * eofActionTable. */ + int transferPoint; + + int getKey() const { return ordering; } +}; + +struct ErrActionTable + : public SBstTable< ErrActionTableEl, int, CmpOrd<int> > +{ + void setAction( int ordering, Action *action, int transferPoint ); + void setActions( const ErrActionTable &other ); +}; + +/* Compare of an error action table element (key & value). */ +struct CmpErrActionTableEl +{ + static int compare( const ErrActionTableEl &action1, + const ErrActionTableEl &action2 ) + { + if ( action1.ordering < action2.ordering ) + return -1; + else if ( action1.ordering > action2.ordering ) + return 1; + else if ( action1.action < action2.action ) + return -1; + else if ( action1.action > action2.action ) + return 1; + else if ( action1.transferPoint < action2.transferPoint ) + return -1; + else if ( action1.transferPoint > action2.transferPoint ) + return 1; + return 0; + } +}; + +/* Compare for ErrActionTable. */ +typedef CmpSTable< ErrActionTableEl, CmpErrActionTableEl > CmpErrActionTable; + + +/* Descibe a priority, shared among PriorEls. + * Has key and whether or not used. */ +struct PriorDesc +{ + int key; + int priority; +}; + +/* Element in the arrays of priorities for transitions and arrays. Ordering is + * unique among instantiations of machines, desc is shared. */ +struct PriorEl +{ + PriorEl( int ordering, PriorDesc *desc ) + : ordering(ordering), desc(desc) { } + + int ordering; + PriorDesc *desc; +}; + +/* Compare priority elements, which are ordered by the priority descriptor + * key. */ +struct PriorElCmp +{ + static inline int compare( const PriorEl &pel1, const PriorEl &pel2 ) + { + if ( pel1.desc->key < pel2.desc->key ) + return -1; + else if ( pel1.desc->key > pel2.desc->key ) + return 1; + else + return 0; + } +}; + + +/* Priority Table. */ +struct PriorTable + : public SBstSet< PriorEl, PriorElCmp > +{ + void setPrior( int ordering, PriorDesc *desc ); + void setPriors( const PriorTable &other ); +}; + +/* Compare of prior table elements for distinguising state data. */ +struct CmpPriorEl +{ + static inline int compare( const PriorEl &pel1, const PriorEl &pel2 ) + { + if ( pel1.desc < pel2.desc ) + return -1; + else if ( pel1.desc > pel2.desc ) + return 1; + else if ( pel1.ordering < pel2.ordering ) + return -1; + else if ( pel1.ordering > pel2.ordering ) + return 1; + return 0; + } +}; + +/* Compare of PriorTable distinguising state data. Using a compare of the + * pointers is a little more strict than it needs be. It requires that + * prioritiy tables have the exact same set of priority assignment operators + * (from the input lang) to be considered equal. + * + * Really only key-value pairs need be tested and ordering be merged. However + * this would require that in the fuseing of states, priority descriptors be + * chosen for the new fused state based on priority. Since the out transition + * lists and ranges aren't necessarily going to line up, this is more work for + * little gain. Final compression resets all priorities first, so this would + * only be useful for compression at every operator, which is only an + * undocumented test feature. + */ +typedef CmpSTable<PriorEl, CmpPriorEl> CmpPriorTable; + +/* Plain action list that imposes no ordering. */ +typedef Vector<int> TransFuncList; + +/* Comparison for TransFuncList. */ +typedef CmpTable< int, CmpOrd<int> > TransFuncListCompare; + +/* Transition class that implements actions and priorities. */ +struct TransAp +{ + TransAp() : fromState(0), toState(0) {} + TransAp( const TransAp &other ) : + lowKey(other.lowKey), + highKey(other.highKey), + fromState(0), toState(0), + actionTable(other.actionTable), + priorTable(other.priorTable) + { + assert( lmActionTable.length() == 0 && other.lmActionTable.length() == 0 ); + } + + Key lowKey, highKey; + StateAp *fromState; + StateAp *toState; + + /* Pointers for outlist. */ + TransAp *prev, *next; + + /* Pointers for in-list. */ + TransAp *ilprev, *ilnext; + + /* The function table and priority for the transition. */ + ActionTable actionTable; + PriorTable priorTable; + + LmActionTable lmActionTable; +}; + +/* In transition list. Like DList except only has head pointers, which is all + * that is required. Insertion and deletion is handled by the graph. This + * class provides the iterator of a single list. */ +struct TransInList +{ + TransInList() : head(0) { } + + TransAp *head; + + struct Iter + { + /* Default construct. */ + Iter() : ptr(0) { } + + /* Construct, assign from a list. */ + Iter( const TransInList &il ) : ptr(il.head) { } + Iter &operator=( const TransInList &dl ) { ptr = dl.head; return *this; } + + /* At the end */ + bool lte() const { return ptr != 0; } + bool end() const { return ptr == 0; } + + /* At the first, last element. */ + bool first() const { return ptr && ptr->ilprev == 0; } + bool last() const { return ptr && ptr->ilnext == 0; } + + /* Cast, dereference, arrow ops. */ + operator TransAp*() const { return ptr; } + TransAp &operator *() const { return *ptr; } + TransAp *operator->() const { return ptr; } + + /* Increment, decrement. */ + inline void operator++(int) { ptr = ptr->ilnext; } + inline void operator--(int) { ptr = ptr->ilprev; } + + /* The iterator is simply a pointer. */ + TransAp *ptr; + }; +}; + +typedef DList<TransAp> TransList; + +/* Set of states, list of states. */ +typedef BstSet<StateAp*> StateSet; +typedef DList<StateAp> StateList; + +/* A element in a state dict. */ +struct StateDictEl +: + public AvlTreeEl<StateDictEl> +{ + StateDictEl(const StateSet &stateSet) + : stateSet(stateSet) { } + + const StateSet &getKey() { return stateSet; } + StateSet stateSet; + StateAp *targState; +}; + +/* Dictionary mapping a set of states to a target state. */ +typedef AvlTree< StateDictEl, StateSet, CmpTable<StateAp*> > StateDict; + +/* Data needed for a merge operation. */ +struct MergeData +{ + MergeData() + : stfillHead(0), stfillTail(0) { } + + StateDict stateDict; + + StateAp *stfillHead; + StateAp *stfillTail; + + void fillListAppend( StateAp *state ); +}; + +struct TransEl +{ + /* Constructors. */ + TransEl() { } + TransEl( Key lowKey, Key highKey ) + : lowKey(lowKey), highKey(highKey) { } + TransEl( Key lowKey, Key highKey, TransAp *value ) + : lowKey(lowKey), highKey(highKey), value(value) { } + + Key lowKey, highKey; + TransAp *value; +}; + +struct CmpKey +{ + static int compare( const Key key1, const Key key2 ) + { + if ( key1 < key2 ) + return -1; + else if ( key1 > key2 ) + return 1; + else + return 0; + } +}; + +/* Vector based set of key items. */ +typedef BstSet<Key, CmpKey> KeySet; + +struct MinPartition +{ + MinPartition() : active(false) { } + + StateList list; + bool active; + + MinPartition *prev, *next; +}; + +/* Epsilon transition stored in a state. Specifies the target */ +typedef Vector<int> EpsilonTrans; + +/* List of states that are to be drawn into this. */ +struct EptVectEl +{ + EptVectEl( StateAp *targ, bool leaving ) + : targ(targ), leaving(leaving) { } + + StateAp *targ; + bool leaving; +}; +typedef Vector<EptVectEl> EptVect; + +/* Set of entry ids that go into this state. */ +typedef BstSet<int> EntryIdSet; + +/* Set of longest match items that may be active in a given state. */ +typedef BstSet<LongestMatchPart*> LmItemSet; + +/* Conditions. */ +typedef BstSet< Action*, CmpCondId > CondSet; +typedef CmpTable< Action*, CmpCondId > CmpCondSet; + +struct CondSpace + : public AvlTreeEl<CondSpace> +{ + CondSpace( const CondSet &condSet ) + : condSet(condSet) {} + + const CondSet &getKey() { return condSet; } + + CondSet condSet; + Key baseKey; + long condSpaceId; +}; + +typedef Vector<CondSpace*> CondSpaceVect; + +typedef AvlTree<CondSpace, CondSet, CmpCondSet> CondSpaceMap; + +struct StateCond +{ + StateCond( Key lowKey, Key highKey ) : + lowKey(lowKey), highKey(highKey) {} + + Key lowKey; + Key highKey; + CondSpace *condSpace; + + StateCond *prev, *next; +}; + +typedef DList<StateCond> StateCondList; +typedef Vector<long> LongVect; + +struct Expansion +{ + Expansion( Key lowKey, Key highKey ) : + lowKey(lowKey), highKey(highKey), + fromTrans(0), fromCondSpace(0), + toCondSpace(0) {} + + ~Expansion() + { + if ( fromTrans != 0 ) + delete fromTrans; + } + + Key lowKey; + Key highKey; + + TransAp *fromTrans; + CondSpace *fromCondSpace; + long fromVals; + + CondSpace *toCondSpace; + LongVect toValsList; + + Expansion *prev, *next; +}; + +typedef DList<Expansion> ExpansionList; + +struct Removal +{ + Key lowKey; + Key highKey; + + Removal *next; +}; + +struct CondData +{ + CondData() : nextCondKey(0) {} + + /* Condition info. */ + Key nextCondKey; + + CondSpaceMap condSpaceMap; +}; + +extern CondData *condData; + +/* State class that implements actions and priorities. */ +struct StateAp +{ + StateAp(); + StateAp(const StateAp &other); + ~StateAp(); + + /* Is the state final? */ + bool isFinState() { return stateBits & SB_ISFINAL; } + + /* Out transition list and the pointer for the default out trans. */ + TransList outList; + + /* In transition Lists. */ + TransInList inList; + + /* Entry points into the state. */ + EntryIdSet entryIds; + + /* Epsilon transitions. */ + EpsilonTrans epsilonTrans; + + /* Condition info. */ + StateCondList stateCondList; + + /* Number of in transitions from states other than ourselves. */ + int foreignInTrans; + + /* Temporary data for various algorithms. */ + union { + /* When duplicating the fsm we need to map each + * state to the new state representing it. */ + StateAp *stateMap; + + /* When minimizing machines by partitioning, this maps to the group + * the state is in. */ + MinPartition *partition; + + /* When merging states (state machine operations) this next pointer is + * used for the list of states that need to be filled in. */ + StateAp *next; + + /* Identification for printing and stable minimization. */ + int stateNum; + + } alg; + + /* Data used in epsilon operation, maybe fit into alg? */ + StateAp *isolatedShadow; + int owningGraph; + + /* A pointer to a dict element that contains the set of states this state + * represents. This cannot go into alg, because alg.next is used during + * the merging process. */ + StateDictEl *stateDictEl; + + /* When drawing epsilon transitions, holds the list of states to merge + * with. */ + EptVect *eptVect; + + /* Bits controlling the behaviour of the state during collapsing to dfa. */ + int stateBits; + + /* State list elements. */ + StateAp *next, *prev; + + /* + * Priority and Action data. + */ + + /* Out priorities transfered to out transitions. */ + PriorTable outPriorTable; + + /* The following two action tables are distinguished by the fact that when + * toState actions are executed immediatly after transition actions of + * incoming transitions and the current character will be the same as the + * one available then. The fromState actions are executed immediately + * before the transition actions of outgoing transitions and the current + * character is same as the one available then. */ + + /* Actions to execute upon entering into a state. */ + ActionTable toStateActionTable; + + /* Actions to execute when going from the state to the transition. */ + ActionTable fromStateActionTable; + + /* Actions to add to any future transitions that leave via this state. */ + ActionTable outActionTable; + + /* Conditions to add to any future transiions that leave via this sttate. */ + ActionSet outCondSet; + + /* Error action tables. */ + ErrActionTable errActionTable; + + /* Actions to execute on eof. */ + ActionTable eofActionTable; + + /* Set of longest match items that may be active in this state. */ + LmItemSet lmItemSet; +}; + +template <class ListItem> struct NextTrans +{ + Key lowKey, highKey; + ListItem *trans; + ListItem *next; + + void load() { + if ( trans == 0 ) + next = 0; + else { + next = trans->next; + lowKey = trans->lowKey; + highKey = trans->highKey; + } + } + + void set( ListItem *t ) { + trans = t; + load(); + } + + void increment() { + trans = next; + load(); + } +}; + + +/* Encodes the different states that are meaningful to the of the iterator. */ +enum PairIterUserState +{ + RangeInS1, RangeInS2, + RangeOverlap, + BreakS1, BreakS2 +}; + +template <class ListItem1, class ListItem2 = ListItem1> struct PairIter +{ + /* Encodes the different states that an fsm iterator can be in. */ + enum IterState { + Begin, + ConsumeS1Range, ConsumeS2Range, + OnlyInS1Range, OnlyInS2Range, + S1SticksOut, S1SticksOutBreak, + S2SticksOut, S2SticksOutBreak, + S1DragsBehind, S1DragsBehindBreak, + S2DragsBehind, S2DragsBehindBreak, + ExactOverlap, End + }; + + PairIter( ListItem1 *list1, ListItem2 *list2 ); + + /* Query iterator. */ + bool lte() { return itState != End; } + bool end() { return itState == End; } + void operator++(int) { findNext(); } + void operator++() { findNext(); } + + /* Iterator state. */ + ListItem1 *list1; + ListItem2 *list2; + IterState itState; + PairIterUserState userState; + + NextTrans<ListItem1> s1Tel; + NextTrans<ListItem2> s2Tel; + Key bottomLow, bottomHigh; + ListItem1 *bottomTrans1; + ListItem2 *bottomTrans2; + +private: + void findNext(); +}; + +/* Init the iterator by advancing to the first item. */ +template <class ListItem1, class ListItem2> PairIter<ListItem1, ListItem2>::PairIter( + ListItem1 *list1, ListItem2 *list2 ) +: + list1(list1), + list2(list2), + itState(Begin) +{ + findNext(); +} + +/* Return and re-entry for the co-routine iterators. This should ALWAYS be + * used inside of a block. */ +#define CO_RETURN(label) \ + itState = label; \ + return; \ + entry##label: backIn = true + +/* Return and re-entry for the co-routine iterators. This should ALWAYS be + * used inside of a block. */ +#define CO_RETURN2(label, uState) \ + itState = label; \ + userState = uState; \ + return; \ + entry##label: backIn = true + +/* Advance to the next transition. When returns, trans points to the next + * transition, unless there are no more, in which case end() returns true. */ +template <class ListItem1, class ListItem2> void PairIter<ListItem1, ListItem2>::findNext() +{ + /* This variable is used in dummy statements that follow the entry + * goto labels. The compiler needs some statement to follow the label. */ + bool backIn; + + /* Jump into the iterator routine base on the iterator state. */ + switch ( itState ) { + case Begin: goto entryBegin; + case ConsumeS1Range: goto entryConsumeS1Range; + case ConsumeS2Range: goto entryConsumeS2Range; + case OnlyInS1Range: goto entryOnlyInS1Range; + case OnlyInS2Range: goto entryOnlyInS2Range; + case S1SticksOut: goto entryS1SticksOut; + case S1SticksOutBreak: goto entryS1SticksOutBreak; + case S2SticksOut: goto entryS2SticksOut; + case S2SticksOutBreak: goto entryS2SticksOutBreak; + case S1DragsBehind: goto entryS1DragsBehind; + case S1DragsBehindBreak: goto entryS1DragsBehindBreak; + case S2DragsBehind: goto entryS2DragsBehind; + case S2DragsBehindBreak: goto entryS2DragsBehindBreak; + case ExactOverlap: goto entryExactOverlap; + case End: goto entryEnd; + } + +entryBegin: + /* Set up the next structs at the head of the transition lists. */ + s1Tel.set( list1 ); + s2Tel.set( list2 ); + + /* Concurrently scan both out ranges. */ + while ( true ) { + if ( s1Tel.trans == 0 ) { + /* We are at the end of state1's ranges. Process the rest of + * state2's ranges. */ + while ( s2Tel.trans != 0 ) { + /* Range is only in s2. */ + CO_RETURN2( ConsumeS2Range, RangeInS2 ); + s2Tel.increment(); + } + break; + } + else if ( s2Tel.trans == 0 ) { + /* We are at the end of state2's ranges. Process the rest of + * state1's ranges. */ + while ( s1Tel.trans != 0 ) { + /* Range is only in s1. */ + CO_RETURN2( ConsumeS1Range, RangeInS1 ); + s1Tel.increment(); + } + break; + } + /* Both state1's and state2's transition elements are good. + * The signiture of no overlap is a back key being in front of a + * front key. */ + else if ( s1Tel.highKey < s2Tel.lowKey ) { + /* A range exists in state1 that does not overlap with state2. */ + CO_RETURN2( OnlyInS1Range, RangeInS1 ); + s1Tel.increment(); + } + else if ( s2Tel.highKey < s1Tel.lowKey ) { + /* A range exists in state2 that does not overlap with state1. */ + CO_RETURN2( OnlyInS2Range, RangeInS2 ); + s2Tel.increment(); + } + /* There is overlap, must mix the ranges in some way. */ + else if ( s1Tel.lowKey < s2Tel.lowKey ) { + /* Range from state1 sticks out front. Must break it into + * non-overlaping and overlaping segments. */ + bottomLow = s2Tel.lowKey; + bottomHigh = s1Tel.highKey; + s1Tel.highKey = s2Tel.lowKey; + s1Tel.highKey.decrement(); + bottomTrans1 = s1Tel.trans; + + /* Notify the caller that we are breaking s1. This gives them a + * chance to duplicate s1Tel[0,1].value. */ + CO_RETURN2( S1SticksOutBreak, BreakS1 ); + + /* Broken off range is only in s1. */ + CO_RETURN2( S1SticksOut, RangeInS1 ); + + /* Advance over the part sticking out front. */ + s1Tel.lowKey = bottomLow; + s1Tel.highKey = bottomHigh; + s1Tel.trans = bottomTrans1; + } + else if ( s2Tel.lowKey < s1Tel.lowKey ) { + /* Range from state2 sticks out front. Must break it into + * non-overlaping and overlaping segments. */ + bottomLow = s1Tel.lowKey; + bottomHigh = s2Tel.highKey; + s2Tel.highKey = s1Tel.lowKey; + s2Tel.highKey.decrement(); + bottomTrans2 = s2Tel.trans; + + /* Notify the caller that we are breaking s2. This gives them a + * chance to duplicate s2Tel[0,1].value. */ + CO_RETURN2( S2SticksOutBreak, BreakS2 ); + + /* Broken off range is only in s2. */ + CO_RETURN2( S2SticksOut, RangeInS2 ); + + /* Advance over the part sticking out front. */ + s2Tel.lowKey = bottomLow; + s2Tel.highKey = bottomHigh; + s2Tel.trans = bottomTrans2; + } + /* Low ends are even. Are the high ends even? */ + else if ( s1Tel.highKey < s2Tel.highKey ) { + /* Range from state2 goes longer than the range from state1. We + * must break the range from state2 into an evenly overlaping + * segment. */ + bottomLow = s1Tel.highKey; + bottomLow.increment(); + bottomHigh = s2Tel.highKey; + s2Tel.highKey = s1Tel.highKey; + bottomTrans2 = s2Tel.trans; + + /* Notify the caller that we are breaking s2. This gives them a + * chance to duplicate s2Tel[0,1].value. */ + CO_RETURN2( S2DragsBehindBreak, BreakS2 ); + + /* Breaking s2 produces exact overlap. */ + CO_RETURN2( S2DragsBehind, RangeOverlap ); + + /* Advance over the front we just broke off of range 2. */ + s2Tel.lowKey = bottomLow; + s2Tel.highKey = bottomHigh; + s2Tel.trans = bottomTrans2; + + /* Advance over the entire s1Tel. We have consumed it. */ + s1Tel.increment(); + } + else if ( s2Tel.highKey < s1Tel.highKey ) { + /* Range from state1 goes longer than the range from state2. We + * must break the range from state1 into an evenly overlaping + * segment. */ + bottomLow = s2Tel.highKey; + bottomLow.increment(); + bottomHigh = s1Tel.highKey; + s1Tel.highKey = s2Tel.highKey; + bottomTrans1 = s1Tel.trans; + + /* Notify the caller that we are breaking s1. This gives them a + * chance to duplicate s2Tel[0,1].value. */ + CO_RETURN2( S1DragsBehindBreak, BreakS1 ); + + /* Breaking s1 produces exact overlap. */ + CO_RETURN2( S1DragsBehind, RangeOverlap ); + + /* Advance over the front we just broke off of range 1. */ + s1Tel.lowKey = bottomLow; + s1Tel.highKey = bottomHigh; + s1Tel.trans = bottomTrans1; + + /* Advance over the entire s2Tel. We have consumed it. */ + s2Tel.increment(); + } + else { + /* There is an exact overlap. */ + CO_RETURN2( ExactOverlap, RangeOverlap ); + + s1Tel.increment(); + s2Tel.increment(); + } + } + + /* Done, go into end state. */ + CO_RETURN( End ); +} + + +/* Compare lists of epsilon transitions. Entries are name ids of targets. */ +typedef CmpTable< int, CmpOrd<int> > CmpEpsilonTrans; + +/* Compare class for the Approximate minimization. */ +class ApproxCompare +{ +public: + ApproxCompare() { } + int compare( const StateAp *pState1, const StateAp *pState2 ); +}; + +/* Compare class for the initial partitioning of a partition minimization. */ +class InitPartitionCompare +{ +public: + InitPartitionCompare() { } + int compare( const StateAp *pState1, const StateAp *pState2 ); +}; + +/* Compare class for the regular partitioning of a partition minimization. */ +class PartitionCompare +{ +public: + PartitionCompare() { } + int compare( const StateAp *pState1, const StateAp *pState2 ); +}; + +/* Compare class for a minimization that marks pairs. Provides the shouldMark + * routine. */ +class MarkCompare +{ +public: + MarkCompare() { } + bool shouldMark( MarkIndex &markIndex, const StateAp *pState1, + const StateAp *pState2 ); +}; + +/* List of partitions. */ +typedef DList< MinPartition > PartitionList; + +/* List of transtions out of a state. */ +typedef Vector<TransEl> TransListVect; + +/* Entry point map used for keeping track of entry points in a machine. */ +typedef BstSet< int > EntryIdSet; +typedef BstMapEl< int, StateAp* > EntryMapEl; +typedef BstMap< int, StateAp* > EntryMap; +typedef Vector<EntryMapEl> EntryMapBase; + +/* Graph class that implements actions and priorities. */ +struct FsmAp +{ + /* Constructors/Destructors. */ + FsmAp( ); + FsmAp( const FsmAp &graph ); + ~FsmAp(); + + /* The list of states. */ + StateList stateList; + StateList misfitList; + + /* The map of entry points. */ + EntryMap entryPoints; + + /* The start state. */ + StateAp *startState; + + /* Error state, possibly created only when the final machine has been + * created and the XML machine is about to be written. No transitions + * point to this state. */ + StateAp *errState; + + /* The set of final states. */ + StateSet finStateSet; + + /* Misfit Accounting. Are misfits put on a separate list. */ + bool misfitAccounting; + + /* + * Transition actions and priorities. + */ + + /* Set priorities on transtions. */ + void startFsmPrior( int ordering, PriorDesc *prior ); + void allTransPrior( int ordering, PriorDesc *prior ); + void finishFsmPrior( int ordering, PriorDesc *prior ); + void leaveFsmPrior( int ordering, PriorDesc *prior ); + + /* Action setting support. */ + void transferErrorActions( StateAp *state, int transferPoint ); + void setErrorAction( StateAp *state, int ordering, Action *action ); + + /* Fill all spaces in a transition list with an error transition. */ + void fillGaps( StateAp *state ); + + /* Similar to setErrorAction, instead gives a state to go to on error. */ + void setErrorTarget( StateAp *state, StateAp *target, int *orderings, + Action **actions, int nActs ); + + /* Set actions to execute. */ + void startFsmAction( int ordering, Action *action ); + void allTransAction( int ordering, Action *action ); + void finishFsmAction( int ordering, Action *action ); + void leaveFsmAction( int ordering, Action *action ); + void longMatchAction( int ordering, LongestMatchPart *lmPart ); + + /* Set conditions. */ + CondSpace *addCondSpace( const CondSet &condSet ); + + void findEmbedExpansions( ExpansionList &expansionList, + StateAp *destState, Action *condAction ); + void embedCondition( MergeData &md, StateAp *state, Action *condAction ); + void embedCondition( StateAp *state, Action *condAction ); + + void startFsmCondition( Action *condAction ); + void allTransCondition( Action *condAction ); + void leaveFsmCondition( Action *condAction ); + + /* Set error actions to execute. */ + void startErrorAction( int ordering, Action *action, int transferPoint ); + void allErrorAction( int ordering, Action *action, int transferPoint ); + void finalErrorAction( int ordering, Action *action, int transferPoint ); + void notStartErrorAction( int ordering, Action *action, int transferPoint ); + void notFinalErrorAction( int ordering, Action *action, int transferPoint ); + void middleErrorAction( int ordering, Action *action, int transferPoint ); + + /* Set EOF actions. */ + void startEOFAction( int ordering, Action *action ); + void allEOFAction( int ordering, Action *action ); + void finalEOFAction( int ordering, Action *action ); + void notStartEOFAction( int ordering, Action *action ); + void notFinalEOFAction( int ordering, Action *action ); + void middleEOFAction( int ordering, Action *action ); + + /* Set To State actions. */ + void startToStateAction( int ordering, Action *action ); + void allToStateAction( int ordering, Action *action ); + void finalToStateAction( int ordering, Action *action ); + void notStartToStateAction( int ordering, Action *action ); + void notFinalToStateAction( int ordering, Action *action ); + void middleToStateAction( int ordering, Action *action ); + + /* Set From State actions. */ + void startFromStateAction( int ordering, Action *action ); + void allFromStateAction( int ordering, Action *action ); + void finalFromStateAction( int ordering, Action *action ); + void notStartFromStateAction( int ordering, Action *action ); + void notFinalFromStateAction( int ordering, Action *action ); + void middleFromStateAction( int ordering, Action *action ); + + /* Shift the action ordering of the start transitions to start at + * fromOrder and increase in units of 1. Useful before kleene star + * operation. */ + int shiftStartActionOrder( int fromOrder ); + + /* Clear all priorities from the fsm to so they won't affcet minimization + * of the final fsm. */ + void clearAllPriorities(); + + /* Zero out all the function keys. */ + void nullActionKeys(); + + /* Walk the list of states and verify state properties. */ + void verifyStates(); + + /* Misfit Accounting. Are misfits put on a separate list. */ + void setMisfitAccounting( bool val ) + { misfitAccounting = val; } + + /* Set and Unset a state as final. */ + void setFinState( StateAp *state ); + void unsetFinState( StateAp *state ); + + void setStartState( StateAp *state ); + void unsetStartState( ); + + /* Set and unset a state as an entry point. */ + void setEntry( int id, StateAp *state ); + void changeEntry( int id, StateAp *to, StateAp *from ); + void unsetEntry( int id, StateAp *state ); + void unsetEntry( int id ); + void unsetAllEntryPoints(); + + /* Epsilon transitions. */ + void epsilonTrans( int id ); + void shadowReadWriteStates( MergeData &md ); + + /* + * Basic attaching and detaching. + */ + + /* Common to attaching/detaching list and default. */ + void attachToInList( StateAp *from, StateAp *to, TransAp *&head, TransAp *trans ); + void detachFromInList( StateAp *from, StateAp *to, TransAp *&head, TransAp *trans ); + + /* Attach with a new transition. */ + TransAp *attachNewTrans( StateAp *from, StateAp *to, + Key onChar1, Key onChar2 ); + + /* Attach with an existing transition that already in an out list. */ + void attachTrans( StateAp *from, StateAp *to, TransAp *trans ); + + /* Redirect a transition away from error and towards some state. */ + void redirectErrorTrans( StateAp *from, StateAp *to, TransAp *trans ); + + /* Detach a transition from a target state. */ + void detachTrans( StateAp *from, StateAp *to, TransAp *trans ); + + /* Detach a state from the graph. */ + void detachState( StateAp *state ); + + /* + * NFA to DFA conversion routines. + */ + + /* Duplicate a transition that will dropin to a free spot. */ + TransAp *dupTrans( StateAp *from, TransAp *srcTrans ); + + /* In crossing, two transitions both go to real states. */ + TransAp *fsmAttachStates( MergeData &md, StateAp *from, + TransAp *destTrans, TransAp *srcTrans ); + + /* Two transitions are to be crossed, handle the possibility of either + * going to the error state. */ + TransAp *mergeTrans( MergeData &md, StateAp *from, + TransAp *destTrans, TransAp *srcTrans ); + + /* Compare deterimne relative priorities of two transition tables. */ + int comparePrior( const PriorTable &priorTable1, const PriorTable &priorTable2 ); + + /* Cross a src transition with one that is already occupying a spot. */ + TransAp *crossTransitions( MergeData &md, StateAp *from, + TransAp *destTrans, TransAp *srcTrans ); + + void outTransCopy( MergeData &md, StateAp *dest, TransAp *srcList ); + + void doRemove( MergeData &md, StateAp *destState, ExpansionList &expList1 ); + void doExpand( MergeData &md, StateAp *destState, ExpansionList &expList1 ); + void findCondExpInTrans( ExpansionList &expansionList, StateAp *state, + Key lowKey, Key highKey, CondSpace *fromCondSpace, CondSpace *toCondSpace, + long destVals, LongVect &toValsList ); + void findTransExpansions( ExpansionList &expansionList, + StateAp *destState, StateAp *srcState ); + void findCondExpansions( ExpansionList &expansionList, + StateAp *destState, StateAp *srcState ); + void mergeStateConds( StateAp *destState, StateAp *srcState ); + + /* Merge a set of states into newState. */ + void mergeStates( MergeData &md, StateAp *destState, + StateAp **srcStates, int numSrc ); + void mergeStatesLeaving( MergeData &md, StateAp *destState, StateAp *srcState ); + void mergeStates( MergeData &md, StateAp *destState, StateAp *srcState ); + + /* Make all states that are combinations of other states and that + * have not yet had their out transitions filled in. This will + * empty out stateDict and stFil. */ + void fillInStates( MergeData &md ); + + /* + * Transition Comparison. + */ + + /* Compare transition data. Either of the pointers may be null. */ + static inline int compareDataPtr( TransAp *trans1, TransAp *trans2 ); + + /* Compare target state and transition data. Either pointer may be null. */ + static inline int compareFullPtr( TransAp *trans1, TransAp *trans2 ); + + /* Compare target partitions. Either pointer may be null. */ + static inline int comparePartPtr( TransAp *trans1, TransAp *trans2 ); + + /* Check marked status of target states. Either pointer may be null. */ + static inline bool shouldMarkPtr( MarkIndex &markIndex, + TransAp *trans1, TransAp *trans2 ); + + /* + * Callbacks. + */ + + /* Compare priority and function table of transitions. */ + static int compareTransData( TransAp *trans1, TransAp *trans2 ); + + /* Add in the properties of srcTrans into this. */ + void addInTrans( TransAp *destTrans, TransAp *srcTrans ); + + /* Compare states on data stored in the states. */ + static int compareStateData( const StateAp *state1, const StateAp *state2 ); + + /* Out transition data. */ + void clearOutData( StateAp *state ); + bool hasOutData( StateAp *state ); + void transferOutData( StateAp *destState, StateAp *srcState ); + + /* + * Allocation. + */ + + /* New up a state and add it to the graph. */ + StateAp *addState(); + + /* + * Building basic machines + */ + + void concatFsm( Key c ); + void concatFsm( Key *str, int len ); + void concatFsmCI( Key *str, int len ); + void orFsm( Key *set, int len ); + void rangeFsm( Key low, Key high ); + void rangeStarFsm( Key low, Key high ); + void emptyFsm( ); + void lambdaFsm( ); + + /* + * Fsm operators. + */ + + void starOp( ); + void repeatOp( int times ); + void optionalRepeatOp( int times ); + void concatOp( FsmAp *other ); + void unionOp( FsmAp *other ); + void intersectOp( FsmAp *other ); + void subtractOp( FsmAp *other ); + void epsilonOp(); + void joinOp( int startId, int finalId, FsmAp **others, int numOthers ); + void globOp( FsmAp **others, int numOthers ); + void deterministicEntry(); + + /* + * Operator workers + */ + + /* Determine if there are any entry points into a start state other than + * the start state. */ + bool isStartStateIsolated(); + + /* Make a new start state that has no entry points. Will not change the + * identity of the fsm. */ + void isolateStartState(); + + /* Workers for resolving epsilon transitions. */ + bool inEptVect( EptVect *eptVect, StateAp *targ ); + void epsilonFillEptVectFrom( StateAp *root, StateAp *from, bool parentLeaving ); + void resolveEpsilonTrans( MergeData &md ); + + /* Workers for concatenation and union. */ + void doConcat( FsmAp *other, StateSet *fromStates, bool optional ); + void doOr( FsmAp *other ); + + /* + * Final states + */ + + /* Unset any final states that are no longer to be final + * due to final bits. */ + void unsetIncompleteFinals(); + void unsetKilledFinals(); + + /* Bring in other's entry points. Assumes others states are going to be + * copied into this machine. */ + void copyInEntryPoints( FsmAp *other ); + + /* Ordering states. */ + void depthFirstOrdering( StateAp *state ); + void depthFirstOrdering(); + void sortStatesByFinal(); + + /* Set sqequential state numbers starting at 0. */ + void setStateNumbers( int base ); + + /* Unset all final states. */ + void unsetAllFinStates(); + + /* Set the bits of final states and clear the bits of non final states. */ + void setFinBits( int finStateBits ); + + /* + * Self-consistency checks. + */ + + /* Run a sanity check on the machine. */ + void verifyIntegrity(); + + /* Verify that there are no unreachable states, or dead end states. */ + void verifyReachability(); + void verifyNoDeadEndStates(); + + /* + * Path pruning + */ + + /* Mark all states reachable from state. */ + void markReachableFromHereReverse( StateAp *state ); + + /* Mark all states reachable from state. */ + void markReachableFromHere( StateAp *state ); + void markReachableFromHereStopFinal( StateAp *state ); + + /* Removes states that cannot be reached by any path in the fsm and are + * thus wasted silicon. */ + void removeDeadEndStates(); + + /* Removes states that cannot be reached by any path in the fsm and are + * thus wasted silicon. */ + void removeUnreachableStates(); + + /* Remove error actions from states on which the error transition will + * never be taken. */ + bool outListCovers( StateAp *state ); + bool anyErrorRange( StateAp *state ); + + /* Remove states that are on the misfit list. */ + void removeMisfits(); + + /* + * FSM Minimization + */ + + /* Minimization by partitioning. */ + void minimizePartition1(); + void minimizePartition2(); + + /* Minimize the final state Machine. The result is the minimal fsm. Slow + * but stable, correct minimization. Uses n^2 space (lookout) and average + * n^2 time. Worst case n^3 time, but a that is a very rare case. */ + void minimizeStable(); + + /* Minimize the final state machine. Does not find the minimal fsm, but a + * pretty good approximation. Does not use any extra space. Average n^2 + * time. Worst case n^3 time, but a that is a very rare case. */ + void minimizeApproximate(); + + /* This is the worker for the minimize approximate solution. It merges + * states that have identical out transitions. */ + bool minimizeRound( ); + + /* Given an intial partioning of states, split partitions that have out trans + * to differing partitions. */ + int partitionRound( StateAp **statePtrs, MinPartition *parts, int numParts ); + + /* Split partitions that have a transition to a previously split partition, until + * there are no more partitions to split. */ + int splitCandidates( StateAp **statePtrs, MinPartition *parts, int numParts ); + + /* Fuse together states in the same partition. */ + void fusePartitions( MinPartition *parts, int numParts ); + + /* Mark pairs where out final stateness differs, out trans data differs, + * trans pairs go to a marked pair or trans data differs. Should get + * alot of pairs. */ + void initialMarkRound( MarkIndex &markIndex ); + + /* One marking round on all state pairs. Considers if trans pairs go + * to a marked state only. Returns whether or not a pair was marked. */ + bool markRound( MarkIndex &markIndex ); + + /* Move the in trans into src into dest. */ + void inTransMove(StateAp *dest, StateAp *src); + + /* Make state src and dest the same state. */ + void fuseEquivStates(StateAp *dest, StateAp *src); + + /* Find any states that didn't get marked by the marking algorithm and + * merge them into the primary states of their equivalence class. */ + void fuseUnmarkedPairs( MarkIndex &markIndex ); + + /* Merge neighboring transitions go to the same state and have the same + * transitions data. */ + void compressTransitions(); + + /* Returns true if there is a transtion (either explicit or by a gap) to + * the error state. */ + bool checkErrTrans( StateAp *state, TransAp *trans ); + bool checkErrTransFinish( StateAp *state ); + bool hasErrorTrans(); + + /* Check if a machine defines a single character. This is useful in + * validating ranges and machines to export. */ + bool checkSingleCharMachine( ); +}; + + +#endif /* _FSMGRAPH_H */ diff --git a/contrib/tools/ragel5/ragel/fsmmin.cpp b/contrib/tools/ragel5/ragel/fsmmin.cpp new file mode 100644 index 00000000000..046d11afa6f --- /dev/null +++ b/contrib/tools/ragel5/ragel/fsmmin.cpp @@ -0,0 +1,732 @@ +/* + * Copyright 2002 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "fsmgraph.h" +#include "mergesort.h" + +int FsmAp::partitionRound( StateAp **statePtrs, MinPartition *parts, int numParts ) +{ + /* Need a mergesort object and a single partition compare. */ + MergeSort<StateAp*, PartitionCompare> mergeSort; + PartitionCompare partCompare; + + /* For each partition. */ + for ( int p = 0; p < numParts; p++ ) { + /* Fill the pointer array with the states in the partition. */ + StateList::Iter state = parts[p].list; + for ( int s = 0; state.lte(); state++, s++ ) + statePtrs[s] = state; + + /* Sort the states using the partitioning compare. */ + int numStates = parts[p].list.length(); + mergeSort.sort( statePtrs, numStates ); + + /* Assign the states into partitions based on the results of the sort. */ + int destPart = p, firstNewPart = numParts; + for ( int s = 1; s < numStates; s++ ) { + /* If this state differs from the last then move to the next partition. */ + if ( partCompare.compare( statePtrs[s-1], statePtrs[s] ) < 0 ) { + /* The new partition is the next avail spot. */ + destPart = numParts; + numParts += 1; + } + + /* If the state is not staying in the first partition, then + * transfer it to its destination partition. */ + if ( destPart != p ) { + StateAp *state = parts[p].list.detach( statePtrs[s] ); + parts[destPart].list.append( state ); + } + } + + /* Fix the partition pointer for all the states that got moved to a new + * partition. This must be done after the states are transfered so the + * result of the sort is not altered. */ + for ( int newPart = firstNewPart; newPart < numParts; newPart++ ) { + StateList::Iter state = parts[newPart].list; + for ( ; state.lte(); state++ ) + state->alg.partition = &parts[newPart]; + } + } + + return numParts; +} + +/** + * \brief Minimize by partitioning version 1. + * + * Repeatedly tries to split partitions until all partitions are unsplittable. + * Produces the most minimal FSM possible. + */ +void FsmAp::minimizePartition1() +{ + /* Need one mergesort object and partition compares. */ + MergeSort<StateAp*, InitPartitionCompare> mergeSort; + InitPartitionCompare initPartCompare; + + /* Nothing to do if there are no states. */ + if ( stateList.length() == 0 ) + return; + + /* + * First thing is to partition the states by final state status and + * transition functions. This gives us an initial partitioning to work + * with. + */ + + /* Make a array of pointers to states. */ + int numStates = stateList.length(); + StateAp** statePtrs = new StateAp*[numStates]; + + /* Fill up an array of pointers to the states for easy sorting. */ + StateList::Iter state = stateList; + for ( int s = 0; state.lte(); state++, s++ ) + statePtrs[s] = state; + + /* Sort the states using the array of states. */ + mergeSort.sort( statePtrs, numStates ); + + /* An array of lists of states is used to partition the states. */ + MinPartition *parts = new MinPartition[numStates]; + + /* Assign the states into partitions. */ + int destPart = 0; + for ( int s = 0; s < numStates; s++ ) { + /* If this state differs from the last then move to the next partition. */ + if ( s > 0 && initPartCompare.compare( statePtrs[s-1], statePtrs[s] ) < 0 ) { + /* Move to the next partition. */ + destPart += 1; + } + + /* Put the state into its partition. */ + statePtrs[s]->alg.partition = &parts[destPart]; + parts[destPart].list.append( statePtrs[s] ); + } + + /* We just moved all the states from the main list into partitions without + * taking them off the main list. So clean up the main list now. */ + stateList.abandon(); + + /* Split partitions. */ + int numParts = destPart + 1; + while ( true ) { + /* Test all partitions for splitting. */ + int newNum = partitionRound( statePtrs, parts, numParts ); + + /* When no partitions can be split, stop. */ + if ( newNum == numParts ) + break; + + numParts = newNum; + } + + /* Fuse states in the same partition. The states will end up back on the + * main list. */ + fusePartitions( parts, numParts ); + + /* Cleanup. */ + delete[] statePtrs; + delete[] parts; +} + +/* Split partitions that need splittting, decide which partitions might need + * to be split as a result, continue until there are no more that might need + * to be split. */ +int FsmAp::splitCandidates( StateAp **statePtrs, MinPartition *parts, int numParts ) +{ + /* Need a mergesort and a partition compare. */ + MergeSort<StateAp*, PartitionCompare> mergeSort; + PartitionCompare partCompare; + + /* The lists of unsplitable (partList) and splitable partitions. + * Only partitions in the splitable list are check for needing splitting. */ + PartitionList partList, splittable; + + /* Initially, all partitions are born from a split (the initial + * partitioning) and can cause other partitions to be split. So any + * partition with a state with a transition out to another partition is a + * candidate for splitting. This will make every partition except possibly + * partitions of final states split candidates. */ + for ( int p = 0; p < numParts; p++ ) { + /* Assume not active. */ + parts[p].active = false; + + /* Look for a trans out of any state in the partition. */ + for ( StateList::Iter state = parts[p].list; state.lte(); state++ ) { + /* If there is at least one transition out to another state then + * the partition becomes splittable. */ + if ( state->outList.length() > 0 ) { + parts[p].active = true; + break; + } + } + + /* If it was found active then it goes on the splittable list. */ + if ( parts[p].active ) + splittable.append( &parts[p] ); + else + partList.append( &parts[p] ); + } + + /* While there are partitions that are splittable, pull one off and try + * to split it. If it splits, determine which partitions may now be split + * as a result of the newly split partition. */ + while ( splittable.length() > 0 ) { + MinPartition *partition = splittable.detachFirst(); + + /* Fill the pointer array with the states in the partition. */ + StateList::Iter state = partition->list; + for ( int s = 0; state.lte(); state++, s++ ) + statePtrs[s] = state; + + /* Sort the states using the partitioning compare. */ + int numStates = partition->list.length(); + mergeSort.sort( statePtrs, numStates ); + + /* Assign the states into partitions based on the results of the sort. */ + MinPartition *destPart = partition; + int firstNewPart = numParts; + for ( int s = 1; s < numStates; s++ ) { + /* If this state differs from the last then move to the next partition. */ + if ( partCompare.compare( statePtrs[s-1], statePtrs[s] ) < 0 ) { + /* The new partition is the next avail spot. */ + destPart = &parts[numParts]; + numParts += 1; + } + + /* If the state is not staying in the first partition, then + * transfer it to its destination partition. */ + if ( destPart != partition ) { + StateAp *state = partition->list.detach( statePtrs[s] ); + destPart->list.append( state ); + } + } + + /* Fix the partition pointer for all the states that got moved to a new + * partition. This must be done after the states are transfered so the + * result of the sort is not altered. */ + int newPart; + for ( newPart = firstNewPart; newPart < numParts; newPart++ ) { + StateList::Iter state = parts[newPart].list; + for ( ; state.lte(); state++ ) + state->alg.partition = &parts[newPart]; + } + + /* Put the partition we just split and any new partitions that came out + * of the split onto the inactive list. */ + partition->active = false; + partList.append( partition ); + for ( newPart = firstNewPart; newPart < numParts; newPart++ ) { + parts[newPart].active = false; + partList.append( &parts[newPart] ); + } + + if ( destPart == partition ) + continue; + + /* Now determine which partitions are splittable as a result of + * splitting partition by walking the in lists of the states in + * partitions that got split. Partition is the faked first item in the + * loop. */ + MinPartition *causalPart = partition; + newPart = firstNewPart - 1; + while ( newPart < numParts ) { + /* Loop all states in the causal partition. */ + StateList::Iter state = causalPart->list; + for ( ; state.lte(); state++ ) { + /* Walk all transition into the state and put the partition + * that the from state is in onto the splittable list. */ + for ( TransInList::Iter trans = state->inList; trans.lte(); trans++ ) { + MinPartition *fromPart = trans->fromState->alg.partition; + if ( ! fromPart->active ) { + fromPart->active = true; + partList.detach( fromPart ); + splittable.append( fromPart ); + } + } + } + + newPart += 1; + causalPart = &parts[newPart]; + } + } + return numParts; +} + + +/** + * \brief Minimize by partitioning version 2 (best alg). + * + * Repeatedly tries to split partitions that may splittable until there are no + * more partitions that might possibly need splitting. Runs faster than + * version 1. Produces the most minimal fsm possible. + */ +void FsmAp::minimizePartition2() +{ + /* Need a mergesort and an initial partition compare. */ + MergeSort<StateAp*, InitPartitionCompare> mergeSort; + InitPartitionCompare initPartCompare; + + /* Nothing to do if there are no states. */ + if ( stateList.length() == 0 ) + return; + + /* + * First thing is to partition the states by final state status and + * transition functions. This gives us an initial partitioning to work + * with. + */ + + /* Make a array of pointers to states. */ + int numStates = stateList.length(); + StateAp** statePtrs = new StateAp*[numStates]; + + /* Fill up an array of pointers to the states for easy sorting. */ + StateList::Iter state = stateList; + for ( int s = 0; state.lte(); state++, s++ ) + statePtrs[s] = state; + + /* Sort the states using the array of states. */ + mergeSort.sort( statePtrs, numStates ); + + /* An array of lists of states is used to partition the states. */ + MinPartition *parts = new MinPartition[numStates]; + + /* Assign the states into partitions. */ + int destPart = 0; + for ( int s = 0; s < numStates; s++ ) { + /* If this state differs from the last then move to the next partition. */ + if ( s > 0 && initPartCompare.compare( statePtrs[s-1], statePtrs[s] ) < 0 ) { + /* Move to the next partition. */ + destPart += 1; + } + + /* Put the state into its partition. */ + statePtrs[s]->alg.partition = &parts[destPart]; + parts[destPart].list.append( statePtrs[s] ); + } + + /* We just moved all the states from the main list into partitions without + * taking them off the main list. So clean up the main list now. */ + stateList.abandon(); + + /* Split partitions. */ + int numParts = splitCandidates( statePtrs, parts, destPart+1 ); + + /* Fuse states in the same partition. The states will end up back on the + * main list. */ + fusePartitions( parts, numParts ); + + /* Cleanup. */ + delete[] statePtrs; + delete[] parts; +} + +void FsmAp::initialMarkRound( MarkIndex &markIndex ) +{ + /* P and q for walking pairs. */ + StateAp *p = stateList.head, *q; + + /* Need an initial partition compare. */ + InitPartitionCompare initPartCompare; + + /* Walk all unordered pairs of (p, q) where p != q. + * The second depth of the walk stops before reaching p. This + * gives us all unordered pairs of states (p, q) where p != q. */ + while ( p != 0 ) { + q = stateList.head; + while ( q != p ) { + /* If the states differ on final state status, out transitions or + * any transition data then they should be separated on the initial + * round. */ + if ( initPartCompare.compare( p, q ) != 0 ) + markIndex.markPair( p->alg.stateNum, q->alg.stateNum ); + + q = q->next; + } + p = p->next; + } +} + +bool FsmAp::markRound( MarkIndex &markIndex ) +{ + /* P an q for walking pairs. Take note if any pair gets marked. */ + StateAp *p = stateList.head, *q; + bool pairWasMarked = false; + + /* Need a mark comparison. */ + MarkCompare markCompare; + + /* Walk all unordered pairs of (p, q) where p != q. + * The second depth of the walk stops before reaching p. This + * gives us all unordered pairs of states (p, q) where p != q. */ + while ( p != 0 ) { + q = stateList.head; + while ( q != p ) { + /* Should we mark the pair? */ + if ( !markIndex.isPairMarked( p->alg.stateNum, q->alg.stateNum ) ) { + if ( markCompare.shouldMark( markIndex, p, q ) ) { + markIndex.markPair( p->alg.stateNum, q->alg.stateNum ); + pairWasMarked = true; + } + } + q = q->next; + } + p = p->next; + } + + return pairWasMarked; +} + + +/** + * \brief Minimize by pair marking. + * + * Decides if each pair of states is distinct or not. Uses O(n^2) memory and + * should only be used on small graphs. Produces the most minmimal FSM + * possible. + */ +void FsmAp::minimizeStable() +{ + /* Set the state numbers. */ + setStateNumbers( 0 ); + + /* This keeps track of which pairs have been marked. */ + MarkIndex markIndex( stateList.length() ); + + /* Mark pairs where final stateness, out trans, or trans data differ. */ + initialMarkRound( markIndex ); + + /* While the last round of marking succeeded in marking a state + * continue to do another round. */ + int modified = markRound( markIndex ); + while (modified) + modified = markRound( markIndex ); + + /* Merge pairs that are unmarked. */ + fuseUnmarkedPairs( markIndex ); +} + +bool FsmAp::minimizeRound() +{ + /* Nothing to do if there are no states. */ + if ( stateList.length() == 0 ) + return false; + + /* Need a mergesort on approx compare and an approx compare. */ + MergeSort<StateAp*, ApproxCompare> mergeSort; + ApproxCompare approxCompare; + + /* Fill up an array of pointers to the states. */ + StateAp **statePtrs = new StateAp*[stateList.length()]; + StateList::Iter state = stateList; + for ( int s = 0; state.lte(); state++, s++ ) + statePtrs[s] = state; + + bool modified = false; + + /* Sort The list. */ + mergeSort.sort( statePtrs, stateList.length() ); + + /* Walk the list looking for duplicates next to each other, + * merge in any duplicates. */ + StateAp **pLast = statePtrs; + StateAp **pState = statePtrs + 1; + for ( int i = 1; i < stateList.length(); i++, pState++ ) { + if ( approxCompare.compare( *pLast, *pState ) == 0 ) { + /* Last and pState are the same, so fuse together. Move forward + * with pState but not with pLast. If any more are identical, we + * must */ + fuseEquivStates( *pLast, *pState ); + modified = true; + } + else { + /* Last and this are different, do not set to merge them. Move + * pLast to the current (it may be way behind from merging many + * states) and pState forward one to consider the next pair. */ + pLast = pState; + } + } + delete[] statePtrs; + return modified; +} + +/** + * \brief Minmimize by an approximation. + * + * Repeatedly tries to find states with transitions out to the same set of + * states on the same set of keys until no more identical states can be found. + * Does not produce the most minimial FSM possible. + */ +void FsmAp::minimizeApproximate() +{ + /* While the last minimization round succeeded in compacting states, + * continue to try to compact states. */ + while ( true ) { + bool modified = minimizeRound(); + if ( ! modified ) + break; + } +} + + +/* Remove states that have no path to them from the start state. Recursively + * traverses the graph marking states that have paths into them. Then removes + * all states that did not get marked. */ +void FsmAp::removeUnreachableStates() +{ + /* Misfit accounting should be off and there should be no states on the + * misfit list. */ + assert( !misfitAccounting && misfitList.length() == 0 ); + + /* Mark all the states that can be reached + * through the existing set of entry points. */ + markReachableFromHere( startState ); + for ( EntryMap::Iter en = entryPoints; en.lte(); en++ ) + markReachableFromHere( en->value ); + + /* Delete all states that are not marked + * and unmark the ones that are marked. */ + StateAp *state = stateList.head; + while ( state ) { + StateAp *next = state->next; + + if ( state->stateBits & SB_ISMARKED ) + state->stateBits &= ~ SB_ISMARKED; + else { + detachState( state ); + stateList.detach( state ); + delete state; + } + + state = next; + } +} + +bool FsmAp::outListCovers( StateAp *state ) +{ + /* Must be at least one range to cover. */ + if ( state->outList.length() == 0 ) + return false; + + /* The first must start at the lower bound. */ + TransList::Iter trans = state->outList.first(); + if ( keyOps->minKey < trans->lowKey ) + return false; + + /* Loop starts at second el. */ + trans.increment(); + + /* Loop checks lower against prev upper. */ + for ( ; trans.lte(); trans++ ) { + /* Lower end of the trans must be one greater than the + * previous' high end. */ + Key lowKey = trans->lowKey; + lowKey.decrement(); + if ( trans->prev->highKey < lowKey ) + return false; + } + + /* Require that the last range extends to the upper bound. */ + trans = state->outList.last(); + if ( trans->highKey < keyOps->maxKey ) + return false; + + return true; +} + +/* Remove states that that do not lead to a final states. Works recursivly traversing + * the graph in reverse (starting from all final states) and marking seen states. Then + * removes states that did not get marked. */ +void FsmAp::removeDeadEndStates() +{ + /* Misfit accounting should be off and there should be no states on the + * misfit list. */ + assert( !misfitAccounting && misfitList.length() == 0 ); + + /* Mark all states that have paths to the final states. */ + StateAp **st = finStateSet.data; + int nst = finStateSet.length(); + for ( int i = 0; i < nst; i++, st++ ) + markReachableFromHereReverse( *st ); + + /* Start state gets honorary marking. If the machine accepts nothing we + * still want the start state to hang around. This must be done after the + * recursive call on all the final states so that it does not cause the + * start state in transitions to be skipped when the start state is + * visited by the traversal. */ + startState->stateBits |= SB_ISMARKED; + + /* Delete all states that are not marked + * and unmark the ones that are marked. */ + StateAp *state = stateList.head; + while ( state != 0 ) { + StateAp *next = state->next; + + if ( state->stateBits & SB_ISMARKED ) + state->stateBits &= ~ SB_ISMARKED; + else { + detachState( state ); + stateList.detach( state ); + delete state; + } + + state = next; + } +} + +/* Remove states on the misfit list. To work properly misfit accounting should + * be on when this is called. The detaching of a state will likely cause + * another misfit to be collected and it can then be removed. */ +void FsmAp::removeMisfits() +{ + while ( misfitList.length() > 0 ) { + /* Get the first state. */ + StateAp *state = misfitList.head; + + /* Detach and delete. */ + detachState( state ); + + /* The state was previously on the misfit list and detaching can only + * remove in transitions so the state must still be on the misfit + * list. */ + misfitList.detach( state ); + delete state; + } +} + +/* Fuse src into dest because they have been deemed equivalent states. + * Involves moving transitions into src to go into dest and invoking + * callbacks. Src is deleted detached from the graph and deleted. */ +void FsmAp::fuseEquivStates( StateAp *dest, StateAp *src ) +{ + /* This would get ugly. */ + assert( dest != src ); + + /* Cur is a duplicate. We can merge it with trail. */ + inTransMove( dest, src ); + + detachState( src ); + stateList.detach( src ); + delete src; +} + +void FsmAp::fuseUnmarkedPairs( MarkIndex &markIndex ) +{ + StateAp *p = stateList.head, *nextP, *q; + + /* Definition: The primary state of an equivalence class is the first state + * encounterd that belongs to the equivalence class. All equivalence + * classes have primary state including equivalence classes with one state + * in it. */ + + /* For each unmarked pair merge p into q and delete p. q is always the + * primary state of it's equivalence class. We wouldn't have landed on it + * here if it were not, because it would have been deleted. + * + * Proof that q is the primaray state of it's equivalence class: Assume q + * is not the primary state of it's equivalence class, then it would be + * merged into some state that came before it and thus p would be + * equivalent to that state. But q is the first state that p is equivalent + * to so we have a contradiction. */ + + /* Walk all unordered pairs of (p, q) where p != q. + * The second depth of the walk stops before reaching p. This + * gives us all unordered pairs of states (p, q) where p != q. */ + while ( p != 0 ) { + nextP = p->next; + + q = stateList.head; + while ( q != p ) { + /* If one of p or q is a final state then mark. */ + if ( ! markIndex.isPairMarked( p->alg.stateNum, q->alg.stateNum ) ) { + fuseEquivStates( q, p ); + break; + } + q = q->next; + } + p = nextP; + } +} + +void FsmAp::fusePartitions( MinPartition *parts, int numParts ) +{ + /* For each partition, fuse state 2, 3, ... into state 1. */ + for ( int p = 0; p < numParts; p++ ) { + /* Assume that there will always be at least one state. */ + StateAp *first = parts[p].list.head, *toFuse = first->next; + + /* Put the first state back onto the main state list. Don't bother + * removing it from the partition list first. */ + stateList.append( first ); + + /* Fuse the rest of the state into the first. */ + while ( toFuse != 0 ) { + /* Save the next. We will trash it before it is needed. */ + StateAp *next = toFuse->next; + + /* Put the state to be fused in to the first back onto the main + * list before it is fuse. the graph. The state needs to be on + * the main list for the detach from the graph to work. Don't + * bother removing the state from the partition list first. We + * need not maintain it. */ + stateList.append( toFuse ); + + /* Now fuse to the first. */ + fuseEquivStates( first, toFuse ); + + /* Go to the next that we saved before trashing the next pointer. */ + toFuse = next; + } + + /* We transfered the states from the partition list into the main list without + * removing the states from the partition list first. Clean it up. */ + parts[p].list.abandon(); + } +} + + +/* Merge neighboring transitions go to the same state and have the same + * transitions data. */ +void FsmAp::compressTransitions() +{ + for ( StateList::Iter st = stateList; st.lte(); st++ ) { + if ( st->outList.length() > 1 ) { + for ( TransList::Iter trans = st->outList, next = trans.next(); next.lte(); ) { + Key nextLow = next->lowKey; + nextLow.decrement(); + if ( trans->highKey == nextLow && trans->toState == next->toState && + CmpActionTable::compare( trans->actionTable, next->actionTable ) == 0 ) + { + trans->highKey = next->highKey; + st->outList.detach( next ); + detachTrans( next->fromState, next->toState, next ); + delete next; + next = trans.next(); + } + else { + trans.increment(); + next.increment(); + } + } + } + } +} diff --git a/contrib/tools/ragel5/ragel/fsmstate.cpp b/contrib/tools/ragel5/ragel/fsmstate.cpp new file mode 100644 index 00000000000..4322c1060fe --- /dev/null +++ b/contrib/tools/ragel5/ragel/fsmstate.cpp @@ -0,0 +1,463 @@ +/* + * Copyright 2002 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <string.h> +#include <assert.h> +#include "fsmgraph.h" + +#include <iostream> +using namespace std; + +/* Construct a mark index for a specified number of states. Must new up + * an array that is states^2 in size. */ +MarkIndex::MarkIndex( int states ) : numStates(states) +{ + /* Total pairs is states^2. Actually only use half of these, but we allocate + * them all to make indexing into the array easier. */ + int total = states * states; + + /* New up chars so that individual DListEl constructors are + * not called. Zero out the mem manually. */ + array = new bool[total]; + memset( array, 0, sizeof(bool) * total ); +} + +/* Free the array used to store state pairs. */ +MarkIndex::~MarkIndex() +{ + delete[] array; +} + +/* Mark a pair of states. States are specified by their number. The + * marked states are moved from the unmarked list to the marked list. */ +void MarkIndex::markPair(int state1, int state2) +{ + int pos = ( state1 >= state2 ) ? + ( state1 * numStates ) + state2 : + ( state2 * numStates ) + state1; + + array[pos] = true; +} + +/* Returns true if the pair of states are marked. Returns false otherwise. + * Ordering of states given does not matter. */ +bool MarkIndex::isPairMarked(int state1, int state2) +{ + int pos = ( state1 >= state2 ) ? + ( state1 * numStates ) + state2 : + ( state2 * numStates ) + state1; + + return array[pos]; +} + +/* Create a new fsm state. State has not out transitions or in transitions, not + * out out transition data and not number. */ +StateAp::StateAp() +: + /* No out or in transitions. */ + outList(), + inList(), + + /* No entry points, or epsilon trans. */ + entryIds(), + epsilonTrans(), + + /* Conditions. */ + stateCondList(), + + /* No transitions in from other states. */ + foreignInTrans(0), + + /* Only used during merging. Normally null. */ + stateDictEl(0), + eptVect(0), + + /* No state identification bits. */ + stateBits(0), + + /* No Priority data. */ + outPriorTable(), + + /* No Action data. */ + toStateActionTable(), + fromStateActionTable(), + outActionTable(), + outCondSet(), + errActionTable(), + eofActionTable() +{ +} + +/* Copy everything except actual the transitions. That is left up to the + * FsmAp copy constructor. */ +StateAp::StateAp(const StateAp &other) +: + /* All lists are cleared. They will be filled in when the + * individual transitions are duplicated and attached. */ + outList(), + inList(), + + /* Duplicate the entry id set and epsilon transitions. These + * are sets of integers and as such need no fixing. */ + entryIds(other.entryIds), + epsilonTrans(other.epsilonTrans), + + /* Copy in the elements of the conditions. */ + stateCondList( other.stateCondList ), + + /* No transitions in from other states. */ + foreignInTrans(0), + + /* This is only used during merging. Normally null. */ + stateDictEl(0), + eptVect(0), + + /* Fsm state data. */ + stateBits(other.stateBits), + + /* Copy in priority data. */ + outPriorTable(other.outPriorTable), + + /* Copy in action data. */ + toStateActionTable(other.toStateActionTable), + fromStateActionTable(other.fromStateActionTable), + outActionTable(other.outActionTable), + outCondSet(other.outCondSet), + errActionTable(other.errActionTable), + eofActionTable(other.eofActionTable) +{ + /* Duplicate all the transitions. */ + for ( TransList::Iter trans = other.outList; trans.lte(); trans++ ) { + /* Dupicate and store the orginal target in the transition. This will + * be corrected once all the states have been created. */ + TransAp *newTrans = new TransAp(*trans); + newTrans->toState = trans->toState; + outList.append( newTrans ); + } +} + +/* If there is a state dict element, then delete it. Everything else is left + * up to the FsmGraph destructor. */ +StateAp::~StateAp() +{ + if ( stateDictEl != 0 ) + delete stateDictEl; +} + +/* Compare two states using pointers to the states. With the approximate + * compare the idea is that if the compare finds them the same, they can + * immediately be merged. */ +int ApproxCompare::compare( const StateAp *state1 , const StateAp *state2 ) +{ + int compareRes; + + /* Test final state status. */ + if ( (state1->stateBits & SB_ISFINAL) && !(state2->stateBits & SB_ISFINAL) ) + return -1; + else if ( !(state1->stateBits & SB_ISFINAL) && (state2->stateBits & SB_ISFINAL) ) + return 1; + + /* Test epsilon transition sets. */ + compareRes = CmpEpsilonTrans::compare( state1->epsilonTrans, + state2->epsilonTrans ); + if ( compareRes != 0 ) + return compareRes; + + /* Compare the out transitions. */ + compareRes = FsmAp::compareStateData( state1, state2 ); + if ( compareRes != 0 ) + return compareRes; + + /* Use a pair iterator to get the transition pairs. */ + PairIter<TransAp> outPair( state1->outList.head, state2->outList.head ); + for ( ; !outPair.end(); outPair++ ) { + switch ( outPair.userState ) { + + case RangeInS1: + compareRes = FsmAp::compareFullPtr( outPair.s1Tel.trans, 0 ); + if ( compareRes != 0 ) + return compareRes; + break; + + case RangeInS2: + compareRes = FsmAp::compareFullPtr( 0, outPair.s2Tel.trans ); + if ( compareRes != 0 ) + return compareRes; + break; + + case RangeOverlap: + compareRes = FsmAp::compareFullPtr( + outPair.s1Tel.trans, outPair.s2Tel.trans ); + if ( compareRes != 0 ) + return compareRes; + break; + + case BreakS1: + case BreakS2: + break; + } + } + + /* Got through the entire state comparison, deem them equal. */ + return 0; +} + +/* Compare class for the sort that does the intial partition of compaction. */ +int InitPartitionCompare::compare( const StateAp *state1 , const StateAp *state2 ) +{ + int compareRes; + + /* Test final state status. */ + if ( (state1->stateBits & SB_ISFINAL) && !(state2->stateBits & SB_ISFINAL) ) + return -1; + else if ( !(state1->stateBits & SB_ISFINAL) && (state2->stateBits & SB_ISFINAL) ) + return 1; + + /* Test epsilon transition sets. */ + compareRes = CmpEpsilonTrans::compare( state1->epsilonTrans, + state2->epsilonTrans ); + if ( compareRes != 0 ) + return compareRes; + + /* Compare the out transitions. */ + compareRes = FsmAp::compareStateData( state1, state2 ); + if ( compareRes != 0 ) + return compareRes; + + /* Use a pair iterator to test the condition pairs. */ + PairIter<StateCond> condPair( state1->stateCondList.head, state2->stateCondList.head ); + for ( ; !condPair.end(); condPair++ ) { + switch ( condPair.userState ) { + case RangeInS1: + return 1; + case RangeInS2: + return -1; + + case RangeOverlap: { + CondSpace *condSpace1 = condPair.s1Tel.trans->condSpace; + CondSpace *condSpace2 = condPair.s2Tel.trans->condSpace; + if ( condSpace1 < condSpace2 ) + return -1; + else if ( condSpace1 > condSpace2 ) + return 1; + break; + } + case BreakS1: + case BreakS2: + break; + } + } + + /* Use a pair iterator to test the transition pairs. */ + PairIter<TransAp> outPair( state1->outList.head, state2->outList.head ); + for ( ; !outPair.end(); outPair++ ) { + switch ( outPair.userState ) { + + case RangeInS1: + compareRes = FsmAp::compareDataPtr( outPair.s1Tel.trans, 0 ); + if ( compareRes != 0 ) + return compareRes; + break; + + case RangeInS2: + compareRes = FsmAp::compareDataPtr( 0, outPair.s2Tel.trans ); + if ( compareRes != 0 ) + return compareRes; + break; + + case RangeOverlap: + compareRes = FsmAp::compareDataPtr( + outPair.s1Tel.trans, outPair.s2Tel.trans ); + if ( compareRes != 0 ) + return compareRes; + break; + + case BreakS1: + case BreakS2: + break; + } + } + + return 0; +} + +/* Compare class for the sort that does the partitioning. */ +int PartitionCompare::compare( const StateAp *state1, const StateAp *state2 ) +{ + int compareRes; + + /* Use a pair iterator to get the transition pairs. */ + PairIter<TransAp> outPair( state1->outList.head, state2->outList.head ); + for ( ; !outPair.end(); outPair++ ) { + switch ( outPair.userState ) { + + case RangeInS1: + compareRes = FsmAp::comparePartPtr( outPair.s1Tel.trans, 0 ); + if ( compareRes != 0 ) + return compareRes; + break; + + case RangeInS2: + compareRes = FsmAp::comparePartPtr( 0, outPair.s2Tel.trans ); + if ( compareRes != 0 ) + return compareRes; + break; + + case RangeOverlap: + compareRes = FsmAp::comparePartPtr( + outPair.s1Tel.trans, outPair.s2Tel.trans ); + if ( compareRes != 0 ) + return compareRes; + break; + + case BreakS1: + case BreakS2: + break; + } + } + + return 0; +} + +/* Compare class for the sort that does the partitioning. */ +bool MarkCompare::shouldMark( MarkIndex &markIndex, const StateAp *state1, + const StateAp *state2 ) +{ + /* Use a pair iterator to get the transition pairs. */ + PairIter<TransAp> outPair( state1->outList.head, state2->outList.head ); + for ( ; !outPair.end(); outPair++ ) { + switch ( outPair.userState ) { + + case RangeInS1: + if ( FsmAp::shouldMarkPtr( markIndex, outPair.s1Tel.trans, 0 ) ) + return true; + break; + + case RangeInS2: + if ( FsmAp::shouldMarkPtr( markIndex, 0, outPair.s2Tel.trans ) ) + return true; + break; + + case RangeOverlap: + if ( FsmAp::shouldMarkPtr( markIndex, + outPair.s1Tel.trans, outPair.s2Tel.trans ) ) + return true; + break; + + case BreakS1: + case BreakS2: + break; + } + } + + return false; +} + +/* + * Transition Comparison. + */ + +/* Compare target partitions. Either pointer may be null. */ +int FsmAp::comparePartPtr( TransAp *trans1, TransAp *trans2 ) +{ + if ( trans1 != 0 ) { + /* If trans1 is set then so should trans2. The initial partitioning + * guarantees this for us. */ + if ( trans1->toState == 0 && trans2->toState != 0 ) + return -1; + else if ( trans1->toState != 0 && trans2->toState == 0 ) + return 1; + else if ( trans1->toState != 0 ) { + /* Both of targets are set. */ + return CmpOrd< MinPartition* >::compare( + trans1->toState->alg.partition, trans2->toState->alg.partition ); + } + } + return 0; +} + + +/* Compares two transition pointers according to priority and functions. + * Either pointer may be null. Does not consider to state or from state. */ +int FsmAp::compareDataPtr( TransAp *trans1, TransAp *trans2 ) +{ + if ( trans1 == 0 && trans2 != 0 ) + return -1; + else if ( trans1 != 0 && trans2 == 0 ) + return 1; + else if ( trans1 != 0 ) { + /* Both of the transition pointers are set. */ + int compareRes = compareTransData( trans1, trans2 ); + if ( compareRes != 0 ) + return compareRes; + } + return 0; +} + +/* Compares two transitions according to target state, priority and functions. + * Does not consider from state. Either of the pointers may be null. */ +int FsmAp::compareFullPtr( TransAp *trans1, TransAp *trans2 ) +{ + if ( (trans1 != 0) ^ (trans2 != 0) ) { + /* Exactly one of the transitions is set. */ + if ( trans1 != 0 ) + return -1; + else + return 1; + } + else if ( trans1 != 0 ) { + /* Both of the transition pointers are set. Test target state, + * priority and funcs. */ + if ( trans1->toState < trans2->toState ) + return -1; + else if ( trans1->toState > trans2->toState ) + return 1; + else if ( trans1->toState != 0 ) { + /* Test transition data. */ + int compareRes = compareTransData( trans1, trans2 ); + if ( compareRes != 0 ) + return compareRes; + } + } + return 0; +} + + +bool FsmAp::shouldMarkPtr( MarkIndex &markIndex, TransAp *trans1, + TransAp *trans2 ) +{ + if ( (trans1 != 0) ^ (trans2 != 0) ) { + /* Exactly one of the transitions is set. The initial mark round + * should rule out this case. */ + assert( false ); + } + else if ( trans1 != 0 ) { + /* Both of the transitions are set. If the target pair is marked, then + * the pair we are considering gets marked. */ + return markIndex.isPairMarked( trans1->toState->alg.stateNum, + trans2->toState->alg.stateNum ); + } + + /* Neither of the transitiosn are set. */ + return false; +} + + diff --git a/contrib/tools/ragel5/ragel/main.cpp b/contrib/tools/ragel5/ragel/main.cpp new file mode 100644 index 00000000000..a22a34f1b01 --- /dev/null +++ b/contrib/tools/ragel5/ragel/main.cpp @@ -0,0 +1,355 @@ +/* + * Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <iostream> +#include <fstream> +#ifndef _WIN32 +# include <unistd.h> +#endif +#include <sstream> + +/* Parsing. */ +#include "ragel.h" +#include "rlscan.h" + +/* Parameters and output. */ +#include "pcheck.h" +#include "vector.h" +#include "version.h" +#include "common.h" + +#ifdef _MSC_VER +# define strncasecmp _strnicmp
+# define strcasecmp _stricmp
+#endif + +using std::istream; +using std::ostream; +using std::ifstream; +using std::ofstream; +using std::cin; +using std::cout; +using std::cerr; +using std::endl; + +/* Controls minimization. */ +MinimizeLevel minimizeLevel = MinimizePartition2; +MinimizeOpt minimizeOpt = MinimizeMostOps; + +/* Graphviz dot file generation. */ +char *machineSpec = 0, *machineName = 0; +bool machineSpecFound = false; + +bool printStatistics = false; + +/* Print a summary of the options. */ +void usage() +{ + cout << +"usage: ragel [options] file\n" +"general:\n" +" -h, -H, -?, --help Print this usage and exit\n" +" -v, --version Print version information and exit\n" +" -o <file> Write output to <file>\n" +" -s Print some statistics on stderr\n" +"fsm minimization:\n" +" -n Do not perform minimization\n" +" -m Minimize at the end of the compilation\n" +" -l Minimize after most operations (default)\n" +" -e Minimize after every operation\n" +"machine selection:\n" +" -S <spec> FSM specification to output for -V\n" +" -M <machine> Machine definition/instantiation to output for -V\n" +"host language:\n" +" -C The host language is C, C++, Obj-C or Obj-C++ (default)\n" +" -D The host language is D\n" +" -J The host language is Java\n" +" -R The host language is Ruby\n" + ; +} + +/* Print version information. */ +void version() +{ + cout << "Ragel State Machine Compiler version " VERSION << " " PUBDATE << endl << + "Copyright (c) 2001-2006 by Adrian Thurston" << endl; +} + +/* Total error count. */ +int gblErrorCount = 0; + +/* Print the opening to a warning in the input, then return the error ostream. */ +ostream &warning( const InputLoc &loc ) +{ + assert( loc.fileName != 0 ); + cerr << loc.fileName << ":" << loc.line << ":" << + loc.col << ": warning: "; + return cerr; +} + +/* Print the opening to a program error, then return the error stream. */ +ostream &error() +{ + gblErrorCount += 1; + cerr << PROGNAME ": "; + return cerr; +} + +ostream &error( const InputLoc &loc ) +{ + gblErrorCount += 1; + assert( loc.fileName != 0 ); + cerr << loc.fileName << ":" << loc.line << ": "; + return cerr; +} + +void escapeLineDirectivePath( std::ostream &out, char *path ) +{ + for ( char *pc = path; *pc != 0; pc++ ) { + if ( *pc == '\\' ) + out << "\\\\"; + else + out << *pc; + } +} + +/* Main, process args and call yyparse to start scanning input. */ +int main(int argc, char **argv) +{ + ParamCheck pc("o:nmleabjkS:M:CDJRvHh?-:s", argc, argv); + char *inputFileName = 0; + char inputFileNameArr[] = "<stdin>"; + char *outputFileName = 0; + + while ( pc.check() ) { + switch ( pc.state ) { + case ParamCheck::match: + switch ( pc.parameter ) { + /* Output. */ + case 'o': + if ( *pc.parameterArg == 0 ) + error() << "a zero length output file name was given" << endl; + else if ( outputFileName != 0 ) + error() << "more than one output file name was given" << endl; + else { + /* Ok, remember the output file name. */ + outputFileName = pc.parameterArg; + } + break; + + /* Minimization, mostly hidden options. */ + case 'n': + minimizeOpt = MinimizeNone; + break; + case 'm': + minimizeOpt = MinimizeEnd; + break; + case 'l': + minimizeOpt = MinimizeMostOps; + break; + case 'e': + minimizeOpt = MinimizeEveryOp; + break; + case 'a': + minimizeLevel = MinimizeApprox; + break; + case 'b': + minimizeLevel = MinimizeStable; + break; + case 'j': + minimizeLevel = MinimizePartition1; + break; + case 'k': + minimizeLevel = MinimizePartition2; + break; + + /* Machine spec. */ + case 'S': + if ( *pc.parameterArg == 0 ) + error() << "please specify an argument to -S" << endl; + else if ( machineSpec != 0 ) + error() << "more than one -S argument was given" << endl; + else { + /* Ok, remember the path to the machine to generate. */ + machineSpec = pc.parameterArg; + } + break; + + /* Machine path. */ + case 'M': + if ( *pc.parameterArg == 0 ) + error() << "please specify an argument to -M" << endl; + else if ( machineName != 0 ) + error() << "more than one -M argument was given" << endl; + else { + /* Ok, remember the machine name to generate. */ + machineName = pc.parameterArg; + } + break; + + /* Host language types. */ + case 'C': + hostLangType = CCode; + hostLang = &hostLangC; + break; + case 'D': + hostLangType = DCode; + hostLang = &hostLangD; + break; + case 'J': + hostLangType = JavaCode; + hostLang = &hostLangJava; + break; + case 'R': + hostLangType = RubyCode; + hostLang = &hostLangRuby; + break; + + /* Version and help. */ + case 'v': + version(); + exit(0); + case 'H': case 'h': case '?': + usage(); + exit(0); + case 's': + printStatistics = true; + break; + case '-': + if ( strcasecmp(pc.parameterArg, "help") == 0 ) { + usage(); + exit(0); + } + else if ( strcasecmp(pc.parameterArg, "version") == 0 ) { + version(); + exit(0); + } + else { + error() << "--" << pc.parameterArg << + " is an invalid argument" << endl; + } + } + break; + + case ParamCheck::invalid: + error() << "-" << pc.parameter << " is an invalid argument" << endl; + break; + + case ParamCheck::noparam: + /* It is interpreted as an input file. */ + if ( *pc.curArg == 0 ) + error() << "a zero length input file name was given" << endl; + else if ( inputFileName != 0 ) + error() << "more than one input file name was given" << endl; + else { + /* OK, Remember the filename. */ + inputFileName = pc.curArg; + } + break; + } + } + + /* Bail on above errors. */ + if ( gblErrorCount > 0 ) + exit(1); + + /* Make sure we are not writing to the same file as the input file. */ + if ( inputFileName != 0 && outputFileName != 0 && + strcmp( inputFileName, outputFileName ) == 0 ) + { + error() << "output file \"" << outputFileName << + "\" is the same as the input file" << endl; + } + + /* Open the input file for reading. */ + istream *inStream; + if ( inputFileName != 0 ) { + /* Open the input file for reading. */ + ifstream *inFile = new ifstream( inputFileName ); + inStream = inFile; + if ( ! inFile->is_open() ) + error() << "could not open " << inputFileName << " for reading" << endl; + } + else { + inStream = &cin; + } + + + /* Bail on above errors. */ + if ( gblErrorCount > 0 ) + exit(1); + + std::ostringstream outputBuffer; + + if ( machineSpec == 0 && machineName == 0 ) + outputBuffer << "<host line=\"1\" col=\"1\">"; + +#if defined _WIN32 || defined _WIN64 + if (inputFileName != 0) { + NormalizeWinPath(inputFileName); + } +#endif + if (inputFileName == 0) { + inputFileName = inputFileNameArr; + } + + if (strrchr(inputFileName, '/') == NULL) { + error() << "input file path should be absolute: " << inputFileName << endl; + exit(1); + } + + Scanner scanner( inputFileName, *inStream, outputBuffer, 0, 0, 0, false ); + scanner.do_scan(); + + /* Finished, final check for errors.. */ + if ( gblErrorCount > 0 ) + return 1; + + /* Now send EOF to all parsers. */ + terminateAllParsers(); + + /* Finished, final check for errors.. */ + if ( gblErrorCount > 0 ) + return 1; + + if ( machineSpec == 0 && machineName == 0 ) + outputBuffer << "</host>\n"; + + if ( gblErrorCount > 0 ) + return 1; + + ostream *outputFile = 0; + if ( outputFileName != 0 ) + outputFile = new ofstream( outputFileName ); + else + outputFile = &cout; + + /* Write the machines, then the surrounding code. */ + writeMachines( *outputFile, outputBuffer.str(), inputFileName ); + + if ( outputFileName != 0 ) + delete outputFile; + + return 0; +} diff --git a/contrib/tools/ragel5/ragel/parsedata.cpp b/contrib/tools/ragel5/ragel/parsedata.cpp new file mode 100644 index 00000000000..3e14cc618a3 --- /dev/null +++ b/contrib/tools/ragel5/ragel/parsedata.cpp @@ -0,0 +1,1505 @@ +/* + * Copyright 2001-2006 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <iostream> +#include <iomanip> +#include <errno.h> +#include <stdlib.h> +#include <limits.h> + +#include "ragel.h" +#include "rlparse.h" +#include "parsedata.h" +#include "parsetree.h" +#include "mergesort.h" +#include "xmlcodegen.h" + +using namespace std; + +char mainMachine[] = "main"; + +void Token::set(const char *str, int len ) +{ + length = len; + data = new char[len+1]; + memcpy( data, str, len ); + data[len] = 0; +} + +void Token::append( const Token &other ) +{ + int newLength = length + other.length; + char *newString = new char[newLength+1]; + memcpy( newString, data, length ); + memcpy( newString + length, other.data, other.length ); + newString[newLength] = 0; + data = newString; + length = newLength; +} + +/* Perform minimization after an operation according + * to the command line args. */ +void afterOpMinimize( FsmAp *fsm, bool lastInSeq ) +{ + /* Switch on the prefered minimization algorithm. */ + if ( minimizeOpt == MinimizeEveryOp || minimizeOpt == MinimizeMostOps && lastInSeq ) { + /* First clean up the graph. FsmAp operations may leave these + * lying around. There should be no dead end states. The subtract + * intersection operators are the only places where they may be + * created and those operators clean them up. */ + fsm->removeUnreachableStates(); + + switch ( minimizeLevel ) { + case MinimizeApprox: + fsm->minimizeApproximate(); + break; + case MinimizePartition1: + fsm->minimizePartition1(); + break; + case MinimizePartition2: + fsm->minimizePartition2(); + break; + case MinimizeStable: + fsm->minimizeStable(); + break; + } + } +} + +/* Count the transitions in the fsm by walking the state list. */ +int countTransitions( FsmAp *fsm ) +{ + int numTrans = 0; + StateAp *state = fsm->stateList.head; + while ( state != 0 ) { + numTrans += state->outList.length(); + state = state->next; + } + return numTrans; +} + +Key makeFsmKeyHex( char *str, const InputLoc &loc, ParseData *pd ) +{ + /* Reset errno so we can check for overflow or underflow. In the event of + * an error, sets the return val to the upper or lower bound being tested + * against. */ + errno = 0; + unsigned int size = keyOps->alphType->size; + bool unusedBits = size < sizeof(unsigned long); + + unsigned long ul = strtoul( str, 0, 16 ); + + if ( errno == ERANGE || unusedBits && ul >> (size * 8) ) { + error(loc) << "literal " << str << " overflows the alphabet type" << endl; + ul = 1 << (size * 8); + } + + if ( unusedBits && keyOps->alphType->isSigned && ul >> (size * 8 - 1) ) + ul |= (0xffffffff >> (size*8 ) ) << (size*8); + + return Key( (long)ul ); +} + +#ifdef _MSC_VER +# define strtoll _strtoi64 +#endif + +Key makeFsmKeyDec( char *str, const InputLoc &loc, ParseData *pd ) +{ + /* Convert the number to a decimal. First reset errno so we can check + * for overflow or underflow. */ + errno = 0; + long long minVal = keyOps->alphType->minVal; + long long maxVal = keyOps->alphType->maxVal; + + long long ll = strtoll( str, 0, 10 ); + + /* Check for underflow. */ + if ( errno == ERANGE && ll < 0 || ll < minVal) { + error(loc) << "literal " << str << " underflows the alphabet type" << endl; + ll = minVal; + } + /* Check for overflow. */ + else if ( errno == ERANGE && ll > 0 || ll > maxVal ) { + error(loc) << "literal " << str << " overflows the alphabet type" << endl; + ll = maxVal; + } + + if ( keyOps->alphType->isSigned ) + return Key( (long)ll ); + else + return Key( (unsigned long)ll ); +} + +/* Make an fsm key in int format (what the fsm graph uses) from an alphabet + * number returned by the parser. Validates that the number doesn't overflow + * the alphabet type. */ +Key makeFsmKeyNum( char *str, const InputLoc &loc, ParseData *pd ) +{ + /* Switch on hex/decimal format. */ + if ( str[0] == '0' && str[1] == 'x' ) + return makeFsmKeyHex( str, loc, pd ); + else + return makeFsmKeyDec( str, loc, pd ); +} + +/* Make an fsm int format (what the fsm graph uses) from a single character. + * Performs proper conversion depending on signed/unsigned property of the + * alphabet. */ +Key makeFsmKeyChar( char c, ParseData *pd ) +{ + if ( keyOps->isSigned ) { + /* Copy from a char type. */ + return Key( c ); + } + else { + /* Copy from an unsigned byte type. */ + return Key( (unsigned char)c ); + } +} + +/* Make an fsm key array in int format (what the fsm graph uses) from a string + * of characters. Performs proper conversion depending on signed/unsigned + * property of the alphabet. */ +void makeFsmKeyArray( Key *result, char *data, int len, ParseData *pd ) +{ + if ( keyOps->isSigned ) { + /* Copy from a char star type. */ + char *src = data; + for ( int i = 0; i < len; i++ ) + result[i] = Key(src[i]); + } + else { + /* Copy from an unsigned byte ptr type. */ + unsigned char *src = (unsigned char*) data; + for ( int i = 0; i < len; i++ ) + result[i] = Key(src[i]); + } +} + +/* Like makeFsmKeyArray except the result has only unique keys. They ordering + * will be changed. */ +void makeFsmUniqueKeyArray( KeySet &result, char *data, int len, + bool caseInsensitive, ParseData *pd ) +{ + /* Use a transitions list for getting unique keys. */ + if ( keyOps->isSigned ) { + /* Copy from a char star type. */ + char *src = data; + for ( int si = 0; si < len; si++ ) { + Key key( src[si] ); + result.insert( key ); + if ( caseInsensitive ) { + if ( key.isLower() ) + result.insert( key.toUpper() ); + else if ( key.isUpper() ) + result.insert( key.toLower() ); + } + } + } + else { + /* Copy from an unsigned byte ptr type. */ + unsigned char *src = (unsigned char*) data; + for ( int si = 0; si < len; si++ ) { + Key key( src[si] ); + result.insert( key ); + if ( caseInsensitive ) { + if ( key.isLower() ) + result.insert( key.toUpper() ); + else if ( key.isUpper() ) + result.insert( key.toLower() ); + } + } + } +} + +FsmAp *dotFsm( ParseData *pd ) +{ + FsmAp *retFsm = new FsmAp(); + retFsm->rangeFsm( keyOps->minKey, keyOps->maxKey ); + return retFsm; +} + +FsmAp *dotStarFsm( ParseData *pd ) +{ + FsmAp *retFsm = new FsmAp(); + retFsm->rangeStarFsm( keyOps->minKey, keyOps->maxKey ); + return retFsm; +} + +/* Make a builtin type. Depends on the signed nature of the alphabet type. */ +FsmAp *makeBuiltin( BuiltinMachine builtin, ParseData *pd ) +{ + /* FsmAp created to return. */ + FsmAp *retFsm = 0; + bool isSigned = keyOps->isSigned; + + switch ( builtin ) { + case BT_Any: { + /* All characters. */ + retFsm = dotFsm( pd ); + break; + } + case BT_Ascii: { + /* Ascii characters 0 to 127. */ + retFsm = new FsmAp(); + retFsm->rangeFsm( 0, 127 ); + break; + } + case BT_Extend: { + /* Ascii extended characters. This is the full byte range. Dependent + * on signed, vs no signed. If the alphabet is one byte then just use + * dot fsm. */ + if ( isSigned ) { + retFsm = new FsmAp(); + retFsm->rangeFsm( -128, 127 ); + } + else { + retFsm = new FsmAp(); + retFsm->rangeFsm( 0, 255 ); + } + break; + } + case BT_Alpha: { + /* Alpha [A-Za-z]. */ + FsmAp *upper = new FsmAp(), *lower = new FsmAp(); + upper->rangeFsm( 'A', 'Z' ); + lower->rangeFsm( 'a', 'z' ); + upper->unionOp( lower ); + upper->minimizePartition2(); + retFsm = upper; + break; + } + case BT_Digit: { + /* Digits [0-9]. */ + retFsm = new FsmAp(); + retFsm->rangeFsm( '0', '9' ); + break; + } + case BT_Alnum: { + /* Alpha numerics [0-9A-Za-z]. */ + FsmAp *digit = new FsmAp(), *lower = new FsmAp(); + FsmAp *upper = new FsmAp(); + digit->rangeFsm( '0', '9' ); + upper->rangeFsm( 'A', 'Z' ); + lower->rangeFsm( 'a', 'z' ); + digit->unionOp( upper ); + digit->unionOp( lower ); + digit->minimizePartition2(); + retFsm = digit; + break; + } + case BT_Lower: { + /* Lower case characters. */ + retFsm = new FsmAp(); + retFsm->rangeFsm( 'a', 'z' ); + break; + } + case BT_Upper: { + /* Upper case characters. */ + retFsm = new FsmAp(); + retFsm->rangeFsm( 'A', 'Z' ); + break; + } + case BT_Cntrl: { + /* Control characters. */ + FsmAp *cntrl = new FsmAp(); + FsmAp *highChar = new FsmAp(); + cntrl->rangeFsm( 0, 31 ); + highChar->concatFsm( 127 ); + cntrl->unionOp( highChar ); + cntrl->minimizePartition2(); + retFsm = cntrl; + break; + } + case BT_Graph: { + /* Graphical ascii characters [!-~]. */ + retFsm = new FsmAp(); + retFsm->rangeFsm( '!', '~' ); + break; + } + case BT_Print: { + /* Printable characters. Same as graph except includes space. */ + retFsm = new FsmAp(); + retFsm->rangeFsm( ' ', '~' ); + break; + } + case BT_Punct: { + /* Punctuation. */ + FsmAp *range1 = new FsmAp(); + FsmAp *range2 = new FsmAp(); + FsmAp *range3 = new FsmAp(); + FsmAp *range4 = new FsmAp(); + range1->rangeFsm( '!', '/' ); + range2->rangeFsm( ':', '@' ); + range3->rangeFsm( '[', '`' ); + range4->rangeFsm( '{', '~' ); + range1->unionOp( range2 ); + range1->unionOp( range3 ); + range1->unionOp( range4 ); + range1->minimizePartition2(); + retFsm = range1; + break; + } + case BT_Space: { + /* Whitespace: [\t\v\f\n\r ]. */ + FsmAp *cntrl = new FsmAp(); + FsmAp *space = new FsmAp(); + cntrl->rangeFsm( '\t', '\r' ); + space->concatFsm( ' ' ); + cntrl->unionOp( space ); + cntrl->minimizePartition2(); + retFsm = cntrl; + break; + } + case BT_Xdigit: { + /* Hex digits [0-9A-Fa-f]. */ + FsmAp *digit = new FsmAp(); + FsmAp *upper = new FsmAp(); + FsmAp *lower = new FsmAp(); + digit->rangeFsm( '0', '9' ); + upper->rangeFsm( 'A', 'F' ); + lower->rangeFsm( 'a', 'f' ); + digit->unionOp( upper ); + digit->unionOp( lower ); + digit->minimizePartition2(); + retFsm = digit; + break; + } + case BT_Lambda: { + retFsm = new FsmAp(); + retFsm->lambdaFsm(); + break; + } + case BT_Empty: { + retFsm = new FsmAp(); + retFsm->emptyFsm(); + break; + }} + + return retFsm; +} + +/* Check if this name inst or any name inst below is referenced. */ +bool NameInst::anyRefsRec() +{ + if ( numRefs > 0 ) + return true; + + /* Recurse on children until true. */ + for ( NameVect::Iter ch = childVect; ch.lte(); ch++ ) { + if ( (*ch)->anyRefsRec() ) + return true; + } + + return false; +} + +/* + * ParseData + */ + +/* Initialize the structure that will collect info during the parse of a + * machine. */ +ParseData::ParseData(const char *fileName, char *sectionName, + const InputLoc §ionLoc ) +: + sectionGraph(0), + generatingSectionSubset(false), + nextPriorKey(0), + /* 0 is reserved for global error actions. */ + nextLocalErrKey(1), + nextNameId(0), + nextCondId(0), + alphTypeSet(false), + getKeyExpr(0), + accessExpr(0), + curStateExpr(0), + lowerNum(0), + upperNum(0), + fileName(fileName), + sectionName(sectionName), + sectionLoc(sectionLoc), + errorCount(0), + curActionOrd(0), + curPriorOrd(0), + rootName(0), + exportsRootName(0), + nextEpsilonResolvedLink(0), + nextLongestMatchId(1), + lmRequiresErrorState(false) +{ + /* Initialize the dictionary of graphs. This is our symbol table. The + * initialization needs to be done on construction which happens at the + * beginning of a machine spec so any assignment operators can reference + * the builtins. */ + initGraphDict(); +} + +/* Clean up the data collected during a parse. */ +ParseData::~ParseData() +{ + /* Delete all the nodes in the action list. Will cause all the + * string data that represents the actions to be deallocated. */ + actionList.empty(); +} + +/* Make a name id in the current name instantiation scope if it is not + * already there. */ +NameInst *ParseData::addNameInst( const InputLoc &loc, const char *data, bool isLabel ) +{ + /* Create the name instantitaion object and insert it. */ + NameInst *newNameInst = new NameInst( loc, curNameInst, data, nextNameId++, isLabel ); + curNameInst->childVect.append( newNameInst ); + if ( data != 0 ) + curNameInst->children.insertMulti( data, newNameInst ); + return newNameInst; +} + +void ParseData::initNameWalk() +{ + curNameInst = rootName; + curNameChild = 0; +} + +void ParseData::initExportsNameWalk() +{ + curNameInst = exportsRootName; + curNameChild = 0; +} + +/* Goes into the next child scope. The number of the child is already set up. + * We need this for the syncronous name tree and parse tree walk to work + * properly. It is reset on entry into a scope and advanced on poping of a + * scope. A call to enterNameScope should be accompanied by a corresponding + * popNameScope. */ +NameFrame ParseData::enterNameScope( bool isLocal, int numScopes ) +{ + /* Save off the current data. */ + NameFrame retFrame; + retFrame.prevNameInst = curNameInst; + retFrame.prevNameChild = curNameChild; + retFrame.prevLocalScope = localNameScope; + + /* Enter into the new name scope. */ + for ( int i = 0; i < numScopes; i++ ) { + curNameInst = curNameInst->childVect[curNameChild]; + curNameChild = 0; + } + + if ( isLocal ) + localNameScope = curNameInst; + + return retFrame; +} + +/* Return from a child scope to a parent. The parent info must be specified as + * an argument and is obtained from the corresponding call to enterNameScope. + * */ +void ParseData::popNameScope( const NameFrame &frame ) +{ + /* Pop the name scope. */ + curNameInst = frame.prevNameInst; + curNameChild = frame.prevNameChild+1; + localNameScope = frame.prevLocalScope; +} + +void ParseData::resetNameScope( const NameFrame &frame ) +{ + /* Pop the name scope. */ + curNameInst = frame.prevNameInst; + curNameChild = frame.prevNameChild; + localNameScope = frame.prevLocalScope; +} + + +void ParseData::unsetObsoleteEntries( FsmAp *graph ) +{ + /* Loop the reference names and increment the usage. Names that are no + * longer needed will be unset in graph. */ + for ( NameVect::Iter ref = curNameInst->referencedNames; ref.lte(); ref++ ) { + /* Get the name. */ + NameInst *name = *ref; + name->numUses += 1; + + /* If the name is no longer needed unset its corresponding entry. */ + if ( name->numUses == name->numRefs ) { + assert( graph->entryPoints.find( name->id ) != 0 ); + graph->unsetEntry( name->id ); + assert( graph->entryPoints.find( name->id ) == 0 ); + } + } +} + +NameSet ParseData::resolvePart( NameInst *refFrom, const char *data, bool recLabelsOnly ) +{ + /* Queue needed for breadth-first search, load it with the start node. */ + NameInstList nameQueue; + nameQueue.append( refFrom ); + + NameSet result; + while ( nameQueue.length() > 0 ) { + /* Pull the next from location off the queue. */ + NameInst *from = nameQueue.detachFirst(); + + /* Look for the name. */ + NameMapEl *low, *high; + if ( from->children.findMulti( data, low, high ) ) { + /* Record all instances of the name. */ + for ( ; low <= high; low++ ) + result.insert( low->value ); + } + + /* Name not there, do breadth-first operation of appending all + * childrent to the processing queue. */ + for ( NameVect::Iter name = from->childVect; name.lte(); name++ ) { + if ( !recLabelsOnly || (*name)->isLabel ) + nameQueue.append( *name ); + } + } + + /* Queue exhausted and name never found. */ + return result; +} + +void ParseData::resolveFrom( NameSet &result, NameInst *refFrom, + const NameRef &nameRef, int namePos ) +{ + /* Look for the name in the owning scope of the factor with aug. */ + NameSet partResult = resolvePart( refFrom, nameRef[namePos], false ); + + /* If there are more parts to the name then continue on. */ + if ( ++namePos < nameRef.length() ) { + /* There are more components to the name, search using all the part + * results as the base. */ + for ( NameSet::Iter name = partResult; name.lte(); name++ ) + resolveFrom( result, *name, nameRef, namePos ); + } + else { + /* This is the last component, append the part results to the final + * results. */ + result.insert( partResult ); + } +} + +/* Write out a name reference. */ +ostream &operator<<( ostream &out, const NameRef &nameRef ) +{ + int pos = 0; + if ( nameRef[pos] == 0 ) { + out << "::"; + pos += 1; + } + out << nameRef[pos++]; + for ( ; pos < nameRef.length(); pos++ ) + out << "::" << nameRef[pos]; + return out; +} + +ostream &operator<<( ostream &out, const NameInst &nameInst ) +{ + /* Count the number fully qualified name parts. */ + int numParents = 0; + NameInst *curParent = nameInst.parent; + while ( curParent != 0 ) { + numParents += 1; + curParent = curParent->parent; + } + + /* Make an array and fill it in. */ + curParent = nameInst.parent; + NameInst **parents = new NameInst*[numParents]; + for ( int p = numParents-1; p >= 0; p-- ) { + parents[p] = curParent; + curParent = curParent->parent; + } + + /* Write the parents out, skip the root. */ + for ( int p = 1; p < numParents; p++ ) + out << "::" << ( parents[p]->name != 0 ? parents[p]->name : "<ANON>" ); + + /* Write the name and cleanup. */ + out << "::" << ( nameInst.name != 0 ? nameInst.name : "<ANON>" ); + delete[] parents; + return out; +} + +struct CmpNameInstLoc +{ + static int compare( const NameInst *ni1, const NameInst *ni2 ) + { + if ( ni1->loc.line < ni2->loc.line ) + return -1; + else if ( ni1->loc.line > ni2->loc.line ) + return 1; + else if ( ni1->loc.col < ni2->loc.col ) + return -1; + else if ( ni1->loc.col > ni2->loc.col ) + return 1; + return 0; + } +}; + +void errorStateLabels( const NameSet &resolved ) +{ + MergeSort<NameInst*, CmpNameInstLoc> mergeSort; + mergeSort.sort( resolved.data, resolved.length() ); + for ( NameSet::Iter res = resolved; res.lte(); res++ ) + error((*res)->loc) << " -> " << **res << endl; +} + + +NameInst *ParseData::resolveStateRef( const NameRef &nameRef, InputLoc &loc, Action *action ) +{ + NameInst *nameInst = 0; + + /* Do the local search if the name is not strictly a root level name + * search. */ + if ( nameRef[0] != 0 ) { + /* If the action is referenced, resolve all of them. */ + if ( action != 0 && action->actionRefs.length() > 0 ) { + /* Look for the name in all referencing scopes. */ + NameSet resolved; + for ( ActionRefs::Iter actRef = action->actionRefs; actRef.lte(); actRef++ ) + resolveFrom( resolved, *actRef, nameRef, 0 ); + + if ( resolved.length() > 0 ) { + /* Take the first one. */ + nameInst = resolved[0]; + if ( resolved.length() > 1 ) { + /* Complain about the multiple references. */ + error(loc) << "state reference " << nameRef << + " resolves to multiple entry points" << endl; + errorStateLabels( resolved ); + } + } + } + } + + /* If not found in the local scope, look in global. */ + if ( nameInst == 0 ) { + NameSet resolved; + int fromPos = nameRef[0] != 0 ? 0 : 1; + resolveFrom( resolved, rootName, nameRef, fromPos ); + + if ( resolved.length() > 0 ) { + /* Take the first. */ + nameInst = resolved[0]; + if ( resolved.length() > 1 ) { + /* Complain about the multiple references. */ + error(loc) << "state reference " << nameRef << + " resolves to multiple entry points" << endl; + errorStateLabels( resolved ); + } + } + } + + if ( nameInst == 0 ) { + /* If not found then complain. */ + error(loc) << "could not resolve state reference " << nameRef << endl; + } + return nameInst; +} + +void ParseData::resolveNameRefs( InlineList *inlineList, Action *action ) +{ + for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) { + switch ( item->type ) { + case InlineItem::Entry: case InlineItem::Goto: + case InlineItem::Call: case InlineItem::Next: { + /* Resolve, pass action for local search. */ + NameInst *target = resolveStateRef( *item->nameRef, item->loc, action ); + + /* Check if the target goes into a longest match. */ + NameInst *search = target->parent; + while ( search != 0 ) { + if ( search->isLongestMatch ) { + error(item->loc) << "cannot enter inside a longest " + "match construction as an entry point" << endl; + break; + } + search = search->parent; + } + + /* Note the reference in the name. This will cause the entry + * point to survive to the end of the graph generating walk. */ + if ( target != 0 ) + target->numRefs += 1; + item->nameTarg = target; + break; + } + default: + break; + } + + /* Some of the item types may have children. */ + if ( item->children != 0 ) + resolveNameRefs( item->children, action ); + } +} + +/* Resolve references to labels in actions. */ +void ParseData::resolveActionNameRefs() +{ + for ( ActionList::Iter act = actionList; act.lte(); act++ ) { + /* Only care about the actions that are referenced. */ + if ( act->actionRefs.length() > 0 ) + resolveNameRefs( act->inlineList, act ); + } +} + +/* Walk a name tree starting at from and fill the name index. */ +void ParseData::fillNameIndex( NameInst *from ) +{ + /* Fill the value for from in the name index. */ + nameIndex[from->id] = from; + + /* Recurse on the implicit final state and then all children. */ + if ( from->final != 0 ) + fillNameIndex( from->final ); + for ( NameVect::Iter name = from->childVect; name.lte(); name++ ) + fillNameIndex( *name ); +} + +void ParseData::makeRootNames() +{ + /* Create the root name. */ + rootName = new NameInst( InputLoc(), 0, 0, nextNameId++, false ); + exportsRootName = new NameInst( InputLoc(), 0, 0, nextNameId++, false ); +} + +/* Build the name tree and supporting data structures. */ +void ParseData::makeNameTree( GraphDictEl *dictEl ) +{ + /* Set up curNameInst for the walk. */ + initNameWalk(); + + if ( dictEl != 0 ) { + /* A start location has been specified. */ + dictEl->value->makeNameTree( dictEl->loc, this ); + } + else { + /* First make the name tree. */ + for ( GraphList::Iter glel = instanceList; glel.lte(); glel++ ) { + /* Recurse on the instance. */ + glel->value->makeNameTree( glel->loc, this ); + } + } + + /* The number of nodes in the tree can now be given by nextNameId */ + nameIndex = new NameInst*[nextNameId]; + memset( nameIndex, 0, sizeof(NameInst*)*nextNameId ); + fillNameIndex( rootName ); + fillNameIndex( exportsRootName ); +} + + +void ParseData::createBuiltin(const char *name, BuiltinMachine builtin ) +{ + Expression *expression = new Expression( builtin ); + Join *join = new Join( expression ); + JoinOrLm *joinOrLm = new JoinOrLm( join ); + VarDef *varDef = new VarDef( name, joinOrLm ); + GraphDictEl *graphDictEl = new GraphDictEl( name, varDef ); + graphDict.insert( graphDictEl ); +} + +/* Initialize the graph dict with builtin types. */ +void ParseData::initGraphDict( ) +{ + createBuiltin( "any", BT_Any ); + createBuiltin( "ascii", BT_Ascii ); + createBuiltin( "extend", BT_Extend ); + createBuiltin( "alpha", BT_Alpha ); + createBuiltin( "digit", BT_Digit ); + createBuiltin( "alnum", BT_Alnum ); + createBuiltin( "lower", BT_Lower ); + createBuiltin( "upper", BT_Upper ); + createBuiltin( "cntrl", BT_Cntrl ); + createBuiltin( "graph", BT_Graph ); + createBuiltin( "print", BT_Print ); + createBuiltin( "punct", BT_Punct ); + createBuiltin( "space", BT_Space ); + createBuiltin( "xdigit", BT_Xdigit ); + createBuiltin( "null", BT_Lambda ); + createBuiltin( "zlen", BT_Lambda ); + createBuiltin( "empty", BT_Empty ); +} + +/* Set the alphabet type. If the types are not valid returns false. */ +bool ParseData::setAlphType( char *s1, char *s2 ) +{ + bool valid = false; + for ( int i = 0; i < hostLang->numHostTypes; i++ ) { + if ( strcmp( s1, hostLang->hostTypes[i].data1 ) == 0 && + hostLang->hostTypes[i].data2 != 0 && + strcmp( s2, hostLang->hostTypes[i].data2 ) == 0 ) + { + valid = true; + userAlphType = hostLang->hostTypes + i; + break; + } + } + + alphTypeSet = true; + return valid; +} + +/* Set the alphabet type. If the types are not valid returns false. */ +bool ParseData::setAlphType( char *s1 ) +{ + bool valid = false; + for ( int i = 0; i < hostLang->numHostTypes; i++ ) { + if ( strcmp( s1, hostLang->hostTypes[i].data1 ) == 0 && + hostLang->hostTypes[i].data2 == 0 ) + { + valid = true; + userAlphType = hostLang->hostTypes + i; + break; + } + } + + alphTypeSet = true; + return valid; +} + +/* Initialize the key operators object that will be referenced by all fsms + * created. */ +void ParseData::initKeyOps( ) +{ + /* Signedness and bounds. */ + HostType *alphType = alphTypeSet ? userAlphType : hostLang->defaultAlphType; + thisKeyOps.setAlphType( alphType ); + + if ( lowerNum != 0 ) { + /* If ranges are given then interpret the alphabet type. */ + thisKeyOps.minKey = makeFsmKeyNum( lowerNum, rangeLowLoc, this ); + thisKeyOps.maxKey = makeFsmKeyNum( upperNum, rangeHighLoc, this ); + } + + thisCondData.nextCondKey = thisKeyOps.maxKey; + thisCondData.nextCondKey.increment(); +} + +void ParseData::printNameInst( NameInst *nameInst, int level ) +{ + for ( int i = 0; i < level; i++ ) + cerr << " "; + cerr << (nameInst->name != 0 ? nameInst->name : "<ANON>") << + " id: " << nameInst->id << + " refs: " << nameInst->numRefs << + " uses: " << nameInst->numUses << endl; + for ( NameVect::Iter name = nameInst->childVect; name.lte(); name++ ) + printNameInst( *name, level+1 ); +} + +/* Remove duplicates of unique actions from an action table. */ +void ParseData::removeDups( ActionTable &table ) +{ + /* Scan through the table looking for unique actions to + * remove duplicates of. */ + for ( int i = 0; i < table.length(); i++ ) { + /* Remove any duplicates ahead of i. */ + for ( int r = i+1; r < table.length(); ) { + if ( table[r].value == table[i].value ) + table.vremove(r); + else + r += 1; + } + } +} + +/* Remove duplicates from action lists. This operates only on transition and + * eof action lists and so should be called once all actions have been + * transfered to their final resting place. */ +void ParseData::removeActionDups( FsmAp *graph ) +{ + /* Loop all states. */ + for ( StateList::Iter state = graph->stateList; state.lte(); state++ ) { + /* Loop all transitions. */ + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) + removeDups( trans->actionTable ); + removeDups( state->toStateActionTable ); + removeDups( state->fromStateActionTable ); + removeDups( state->eofActionTable ); + } +} + +Action *ParseData::newAction(const char *name, InlineList *inlineList ) +{ + InputLoc loc; + loc.line = 1; + loc.col = 1; + loc.fileName = "<NONE>"; + + Action *action = new Action( loc, name, inlineList, nextCondId++ ); + action->actionRefs.append( rootName ); + actionList.append( action ); + return action; +} + +void ParseData::initLongestMatchData() +{ + if ( lmList.length() > 0 ) { + /* The initTokStart action resets the token start. */ + InlineList *il1 = new InlineList; + il1->append( new InlineItem( InputLoc(), InlineItem::LmInitTokStart ) ); + initTokStart = newAction( "initts", il1 ); + initTokStart->isLmAction = true; + + /* The initActId action gives act a default value. */ + InlineList *il4 = new InlineList; + il4->append( new InlineItem( InputLoc(), InlineItem::LmInitAct ) ); + initActId = newAction( "initact", il4 ); + initActId->isLmAction = true; + + /* The setTokStart action sets tokstart. */ + InlineList *il5 = new InlineList; + il5->append( new InlineItem( InputLoc(), InlineItem::LmSetTokStart ) ); + setTokStart = newAction( "tokstart", il5 ); + setTokStart->isLmAction = true; + + /* The setTokEnd action sets tokend. */ + InlineList *il3 = new InlineList; + il3->append( new InlineItem( InputLoc(), InlineItem::LmSetTokEnd ) ); + setTokEnd = newAction( "tokend", il3 ); + setTokEnd->isLmAction = true; + + /* The action will also need an ordering: ahead of all user action + * embeddings. */ + initTokStartOrd = curActionOrd++; + initActIdOrd = curActionOrd++; + setTokStartOrd = curActionOrd++; + setTokEndOrd = curActionOrd++; + } +} + +/* After building the graph, do some extra processing to ensure the runtime + * data of the longest mactch operators is consistent. */ +void ParseData::setLongestMatchData( FsmAp *graph ) +{ + if ( lmList.length() > 0 ) { + /* Make sure all entry points (targets of fgoto, fcall, fnext, fentry) + * init the tokstart. */ + for ( EntryMap::Iter en = graph->entryPoints; en.lte(); en++ ) { + /* This is run after duplicates are removed, we must guard against + * inserting a duplicate. */ + ActionTable &actionTable = en->value->toStateActionTable; + if ( ! actionTable.hasAction( initTokStart ) ) + actionTable.setAction( initTokStartOrd, initTokStart ); + } + + /* Find the set of states that are the target of transitions with + * actions that have calls. These states will be targeted by fret + * statements. */ + StateSet states; + for ( StateList::Iter state = graph->stateList; state.lte(); state++ ) { + for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { + for ( ActionTable::Iter ati = trans->actionTable; ati.lte(); ati++ ) { + if ( ati->value->anyCall && trans->toState != 0 ) + states.insert( trans->toState ); + } + } + } + + + /* Init tokstart upon entering the above collected states. */ + for ( StateSet::Iter ps = states; ps.lte(); ps++ ) { + /* This is run after duplicates are removed, we must guard against + * inserting a duplicate. */ + ActionTable &actionTable = (*ps)->toStateActionTable; + if ( ! actionTable.hasAction( initTokStart ) ) + actionTable.setAction( initTokStartOrd, initTokStart ); + } + } +} + +/* Make the graph from a graph dict node. Does minimization and state sorting. */ +FsmAp *ParseData::makeInstance( GraphDictEl *gdNode ) +{ + /* Build the graph from a walk of the parse tree. */ + FsmAp *graph = gdNode->value->walk( this ); + + /* Resolve any labels that point to multiple states. Any labels that are + * still around are referenced only by gotos and calls and they need to be + * made into deterministic entry points. */ + graph->deterministicEntry(); + + /* + * All state construction is now complete. + */ + + /* Transfer global error actions. */ + for ( StateList::Iter state = graph->stateList; state.lte(); state++ ) + graph->transferErrorActions( state, 0 ); + + removeActionDups( graph ); + + /* Remove unreachable states. There should be no dead end states. The + * subtract and intersection operators are the only places where they may + * be created and those operators clean them up. */ + graph->removeUnreachableStates(); + + /* No more fsm operations are to be done. Action ordering numbers are + * no longer of use and will just hinder minimization. Clear them. */ + graph->nullActionKeys(); + + /* Transition priorities are no longer of use. We can clear them + * because they will just hinder minimization as well. Clear them. */ + graph->clearAllPriorities(); + + if ( minimizeOpt != MinimizeNone ) { + /* Minimize here even if we minimized at every op. Now that function + * keys have been cleared we may get a more minimal fsm. */ + switch ( minimizeLevel ) { + case MinimizeApprox: + graph->minimizeApproximate(); + break; + case MinimizeStable: + graph->minimizeStable(); + break; + case MinimizePartition1: + graph->minimizePartition1(); + break; + case MinimizePartition2: + graph->minimizePartition2(); + break; + } + } + + graph->compressTransitions(); + + return graph; +} + +void ParseData::printNameTree() +{ + /* Print the name instance map. */ + for ( NameVect::Iter name = rootName->childVect; name.lte(); name++ ) + printNameInst( *name, 0 ); + + cerr << "name index:" << endl; + /* Show that the name index is correct. */ + for ( int ni = 0; ni < nextNameId; ni++ ) { + cerr << ni << ": "; + const char *name = nameIndex[ni]->name; + cerr << ( name != 0 ? name : "<ANON>" ) << endl; + } +} + +FsmAp *ParseData::makeSpecific( GraphDictEl *gdNode ) +{ + /* Build the name tree and supporting data structures. */ + makeNameTree( gdNode ); + + /* Resove name references from gdNode. */ + initNameWalk(); + gdNode->value->resolveNameRefs( this ); + + /* Do not resolve action references. Since we are not building the entire + * graph there's a good chance that many name references will fail. This + * is okay since generating part of the graph is usually only done when + * inspecting the compiled machine. */ + + /* Same story for extern entry point references. */ + + /* Flag this case so that the XML code generator is aware that we haven't + * looked up name references in actions. It can then avoid segfaulting. */ + generatingSectionSubset = true; + + /* Just building the specified graph. */ + initNameWalk(); + FsmAp *mainGraph = makeInstance( gdNode ); + + return mainGraph; +} + +FsmAp *ParseData::makeAll() +{ + /* Build the name tree and supporting data structures. */ + makeNameTree( 0 ); + + /* Resove name references in the tree. */ + initNameWalk(); + for ( GraphList::Iter glel = instanceList; glel.lte(); glel++ ) + glel->value->resolveNameRefs( this ); + + /* Resolve action code name references. */ + resolveActionNameRefs(); + + /* Force name references to the top level instantiations. */ + for ( NameVect::Iter inst = rootName->childVect; inst.lte(); inst++ ) + (*inst)->numRefs += 1; + + FsmAp *mainGraph = 0; + FsmAp **graphs = new FsmAp*[instanceList.length()]; + int numOthers = 0; + + /* Make all the instantiations, we know that main exists in this list. */ + initNameWalk(); + for ( GraphList::Iter glel = instanceList; glel.lte(); glel++ ) { + if ( strcmp( glel->key, mainMachine ) == 0 ) { + /* Main graph is always instantiated. */ + mainGraph = makeInstance( glel ); + } + else { + /* Instantiate and store in others array. */ + graphs[numOthers++] = makeInstance( glel ); + } + } + + if ( mainGraph == 0 ) + mainGraph = graphs[--numOthers]; + + if ( numOthers > 0 ) { + /* Add all the other graphs into main. */ + mainGraph->globOp( graphs, numOthers ); + } + + delete[] graphs; + return mainGraph; +} + +void ParseData::analyzeAction( Action *action, InlineList *inlineList ) +{ + /* FIXME: Actions used as conditions should be very constrained. */ + for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) { + if ( item->type == InlineItem::Call || item->type == InlineItem::CallExpr ) + action->anyCall = true; + + /* Need to recurse into longest match items. */ + if ( item->type == InlineItem::LmSwitch ) { + LongestMatch *lm = item->longestMatch; + for ( LmPartList::Iter lmi = *lm->longestMatchList; lmi.lte(); lmi++ ) { + if ( lmi->action != 0 ) + analyzeAction( action, lmi->action->inlineList ); + } + } + + if ( item->type == InlineItem::LmOnLast || + item->type == InlineItem::LmOnNext || + item->type == InlineItem::LmOnLagBehind ) + { + LongestMatchPart *lmi = item->longestMatchPart; + if ( lmi->action != 0 ) + analyzeAction( action, lmi->action->inlineList ); + } + + if ( item->children != 0 ) + analyzeAction( action, item->children ); + } +} + + +/* Check actions for bad uses of fsm directives. We don't go inside longest + * match items in actions created by ragel, since we just want the user + * actions. */ +void ParseData::checkInlineList( Action *act, InlineList *inlineList ) +{ + for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) { + /* EOF checks. */ + if ( act->numEofRefs > 0 ) { + switch ( item->type ) { + case InlineItem::PChar: + error(item->loc) << "pointer to current element does not exist in " + "EOF action code" << endl; + break; + case InlineItem::Char: + error(item->loc) << "current element does not exist in " + "EOF action code" << endl; + break; + case InlineItem::Hold: + error(item->loc) << "changing the current element not possible in " + "EOF action code" << endl; + break; + case InlineItem::Exec: + error(item->loc) << "changing the current element not possible in " + "EOF action code" << endl; + break; + case InlineItem::Goto: case InlineItem::Call: + case InlineItem::Next: case InlineItem::GotoExpr: + case InlineItem::CallExpr: case InlineItem::NextExpr: + case InlineItem::Ret: + error(item->loc) << "changing the current state not possible in " + "EOF action code" << endl; + break; + default: + break; + } + } + + /* Recurse. */ + if ( item->children != 0 ) + checkInlineList( act, item->children ); + } +} + +void ParseData::checkAction( Action *action ) +{ + /* Check for actions with calls that are embedded within a longest match + * machine. */ + if ( !action->isLmAction && action->numRefs() > 0 && action->anyCall ) { + for ( ActionRefs::Iter ar = action->actionRefs; ar.lte(); ar++ ) { + NameInst *check = *ar; + while ( check != 0 ) { + if ( check->isLongestMatch ) { + error(action->loc) << "within a scanner, fcall is permitted" + " only in pattern actions" << endl; + break; + } + check = check->parent; + } + } + } + + checkInlineList( action, action->inlineList ); +} + + +void ParseData::analyzeGraph( FsmAp *graph ) +{ + for ( ActionList::Iter act = actionList; act.lte(); act++ ) + analyzeAction( act, act->inlineList ); + + for ( StateList::Iter st = graph->stateList; st.lte(); st++ ) { + /* The transition list. */ + for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) { + for ( ActionTable::Iter at = trans->actionTable; at.lte(); at++ ) + at->value->numTransRefs += 1; + } + + for ( ActionTable::Iter at = st->toStateActionTable; at.lte(); at++ ) + at->value->numToStateRefs += 1; + + for ( ActionTable::Iter at = st->fromStateActionTable; at.lte(); at++ ) + at->value->numFromStateRefs += 1; + + for ( ActionTable::Iter at = st->eofActionTable; at.lte(); at++ ) + at->value->numEofRefs += 1; + + for ( StateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) { + for ( CondSet::Iter sci = sc->condSpace->condSet; sci.lte(); sci++ ) + (*sci)->numCondRefs += 1; + } + } + + /* Checks for bad usage of directives in action code. */ + for ( ActionList::Iter act = actionList; act.lte(); act++ ) + checkAction( act ); +} + +void ParseData::makeExportsNameTree() +{ + /* Make a name tree for the exports. */ + initExportsNameWalk(); + + /* First make the name tree. */ + for ( GraphDict::Iter gdel = graphDict; gdel.lte(); gdel++ ) { + if ( gdel->value->isExport ) { + /* Recurse on the instance. */ + gdel->value->makeNameTree( gdel->loc, this ); + } + } +} + +void ParseData::makeExports() +{ + makeExportsNameTree(); + + /* Resove name references in the tree. */ + initExportsNameWalk(); + for ( GraphDict::Iter gdel = graphDict; gdel.lte(); gdel++ ) { + if ( gdel->value->isExport ) + gdel->value->resolveNameRefs( this ); + } + + /* Make all the instantiations, we know that main exists in this list. */ + initExportsNameWalk(); + for ( GraphDict::Iter gdel = graphDict; gdel.lte(); gdel++ ) { + /* Check if this var def is an export. */ + if ( gdel->value->isExport ) { + /* Build the graph from a walk of the parse tree. */ + FsmAp *graph = gdel->value->walk( this ); + + /* Build the graph from a walk of the parse tree. */ + if ( !graph->checkSingleCharMachine() ) { + error(gdel->loc) << "bad export machine, must define " + "a single character" << endl; + } + else { + /* Safe to extract the key and declare the export. */ + Key exportKey = graph->startState->outList.head->lowKey; + exportList.append( new Export( gdel->value->name, exportKey ) ); + } + } + } + +} + +void ParseData::prepareMachineGen( GraphDictEl *graphDictEl ) +{ + beginProcessing(); + initKeyOps(); + makeRootNames(); + initLongestMatchData(); + + /* Make the graph, do minimization. */ + if ( graphDictEl == 0 ) + sectionGraph = makeAll(); + else + sectionGraph = makeSpecific( graphDictEl ); + + /* Compute exports from the export definitions. */ + makeExports(); + + /* If any errors have occured in the input file then don't write anything. */ + if ( gblErrorCount > 0 ) + return; + + analyzeGraph( sectionGraph ); + + /* Depends on the graph analysis. */ + setLongestMatchData( sectionGraph ); + + /* Decide if an error state is necessary. + * 1. There is an error transition + * 2. There is a gap in the transitions + * 3. The longest match operator requires it. */ + if ( lmRequiresErrorState || sectionGraph->hasErrorTrans() ) + sectionGraph->errState = sectionGraph->addState(); + + /* State numbers need to be assigned such that all final states have a + * larger state id number than all non-final states. This enables the + * first_final mechanism to function correctly. We also want states to be + * ordered in a predictable fashion. So we first apply a depth-first + * search, then do a stable sort by final state status, then assign + * numbers. */ + + sectionGraph->depthFirstOrdering(); + sectionGraph->sortStatesByFinal(); + sectionGraph->setStateNumbers( 0 ); +} + +void ParseData::generateXML( ostream &out ) +{ + beginProcessing(); + + /* Make the generator. */ + XMLCodeGen codeGen( sectionName, this, sectionGraph, out ); + + /* Write out with it. */ + codeGen.writeXML(); + + if ( printStatistics ) { + cerr << "fsm name : " << sectionName << endl; + cerr << "num states: " << sectionGraph->stateList.length() << endl; + cerr << endl; + } +} + +/* Send eof to all parsers. */ +void terminateAllParsers( ) +{ + /* FIXME: a proper token is needed here. Suppose we should use the + * location of EOF in the last file that the parser was referenced in. */ + InputLoc loc; + loc.fileName = "<EOF>"; + loc.line = 0; + loc.col = 0; + for ( ParserDict::Iter pdel = parserDict; pdel.lte(); pdel++ ) + pdel->value->token( loc, _eof, 0, 0 ); +} + +void writeLanguage( std::ostream &out ) +{ + out << " lang=\""; + switch ( hostLangType ) { + case CCode: out << "C"; break; + case DCode: out << "D"; break; + case JavaCode: out << "Java"; break; + case RubyCode: out << "Ruby"; break; + } + out << "\""; + +} + +void writeMachines( std::ostream &out, std::string hostData, const char *inputFileName ) +{ + if ( machineSpec == 0 && machineName == 0 ) { + /* No machine spec or machine name given. Generate everything. */ + for ( ParserDict::Iter parser = parserDict; parser.lte(); parser++ ) { + ParseData *pd = parser->value->pd; + if ( pd->instanceList.length() > 0 ) + pd->prepareMachineGen( 0 ); + } + + if ( gblErrorCount == 0 ) { + out << "<ragel 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( out ); + } + out << hostData; + out << "</ragel>\n"; + } + } + else if ( parserDict.length() > 0 ) { + /* There is either a machine spec or machine name given. */ + ParseData *parseData = 0; + GraphDictEl *graphDictEl = 0; + + /* Traverse the sections, break out when we find a section/machine + * that matches the one specified. */ + for ( ParserDict::Iter parser = parserDict; parser.lte(); parser++ ) { + ParseData *checkPd = parser->value->pd; + if ( machineSpec == 0 || strcmp( checkPd->sectionName, machineSpec ) == 0 ) { + GraphDictEl *checkGdEl = 0; + if ( machineName == 0 || (checkGdEl = + checkPd->graphDict.find( machineName )) != 0 ) + { + /* Have a machine spec and/or machine name that matches + * the -M/-S options. */ + parseData = checkPd; + graphDictEl = checkGdEl; + break; + } + } + } + + if ( parseData == 0 ) + error() << "could not locate machine specified with -S and/or -M" << endl; + else { + /* Section/Machine to emit was found. Prepare and emit it. */ + parseData->prepareMachineGen( graphDictEl ); + if ( gblErrorCount == 0 ) { + out << "<ragel filename=\"" << inputFileName << "\""; + writeLanguage( out ); + out << ">\n"; + parseData->generateXML( out ); + out << hostData; + out << "</ragel>\n"; + } + } + } +} diff --git a/contrib/tools/ragel5/ragel/parsedata.h b/contrib/tools/ragel5/ragel/parsedata.h new file mode 100644 index 00000000000..2baa7373d2c --- /dev/null +++ b/contrib/tools/ragel5/ragel/parsedata.h @@ -0,0 +1,401 @@ +/* + * Copyright 2001-2006 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PARSEDATA_H +#define _PARSEDATA_H + +#include <iostream> +#include <limits.h> +#include "avlmap.h" +#include "bstmap.h" +#include "vector.h" +#include "dlist.h" +#include "fsmgraph.h" +#include "compare.h" +#include "vector.h" +#include "common.h" +#include "parsetree.h" + +/* Forwards. */ +using std::ostream; + +struct VarDef; +struct Join; +struct Expression; +struct Term; +struct FactorWithAug; +struct FactorWithLabel; +struct FactorWithRep; +struct FactorWithNeg; +struct Factor; +struct Literal; +struct Range; +struct RegExpr; +struct ReItem; +struct ReOrBlock; +struct ReOrItem; +struct LongestMatch; +typedef DList<LongestMatch> LmList; + +/* Graph dictionary. */ +struct GraphDictEl +: + public AvlTreeEl<GraphDictEl>, + public DListEl<GraphDictEl> +{ + GraphDictEl(const char *k ) + : key(k), value(0), isInstance(false) { } + GraphDictEl(const char *k, VarDef *value ) + : key(k), value(value), isInstance(false) { } + + const char *getKey() { return key; } + + const char *key; + VarDef *value; + bool isInstance; + + /* Location info of graph definition. Points to variable name of assignment. */ + InputLoc loc; +}; + +typedef AvlTree<GraphDictEl, char*, CmpStr> GraphDict; +typedef DList<GraphDictEl> GraphList; + +/* Priority name dictionary. */ +typedef AvlMapEl<char*, int> PriorDictEl; +typedef AvlMap<char*, int, CmpStr> PriorDict; + +/* Local error name dictionary. */ +typedef AvlMapEl<const char*, int> LocalErrDictEl; +typedef AvlMap<const char*, int, CmpStr> LocalErrDict; + +/* Tree of instantiated names. */ +typedef BstMapEl<const char*, NameInst*> NameMapEl; +typedef BstMap<const char*, NameInst*, CmpStr> NameMap; +typedef Vector<NameInst*> NameVect; +typedef BstSet<NameInst*> NameSet; + +/* Node in the tree of instantiated names. */ +struct NameInst +{ + NameInst( const InputLoc &loc, NameInst *parent, const char *name, int id, bool isLabel ) : + loc(loc), parent(parent), name(name), id(id), isLabel(isLabel), + isLongestMatch(false), numRefs(0), numUses(0), start(0), final(0) {} + + InputLoc loc; + + /* Keep parent pointers in the name tree to retrieve + * fully qulified names. */ + NameInst *parent; + + const char *name; + int id; + bool isLabel; + bool isLongestMatch; + + int numRefs; + int numUses; + + /* Names underneath us, excludes anonymous names. */ + NameMap children; + + /* All names underneath us in order of appearance. */ + NameVect childVect; + + /* Join scopes need an implicit "final" target. */ + NameInst *start, *final; + + /* During a fsm generation walk, lists the names that are referenced by + * epsilon operations in the current scope. After the link is made by the + * epsilon reference and the join operation is complete, the label can + * have its refcount decremented. Once there are no more references the + * entry point can be removed from the fsm returned. */ + NameVect referencedNames; + + /* Pointers for the name search queue. */ + NameInst *prev, *next; + + /* Check if this name inst or any name inst below is referenced. */ + bool anyRefsRec(); +}; + +typedef DList<NameInst> NameInstList; + +/* Stack frame used in walking the name tree. */ +struct NameFrame +{ + NameInst *prevNameInst; + int prevNameChild; + NameInst *prevLocalScope; +}; + +/* Class to collect information about the machine during the + * parse of input. */ +struct ParseData +{ + /* Create a new parse data object. This is done at the beginning of every + * fsm specification. */ + ParseData(const char *fileName, char *sectionName, const InputLoc §ionLoc ); + ~ParseData(); + + /* + * Setting up the graph dict. + */ + + /* Initialize a graph dict with the basic fsms. */ + void initGraphDict(); + void createBuiltin(const char *name, BuiltinMachine builtin ); + + /* Make a name id in the current name instantiation scope if it is not + * already there. */ + NameInst *addNameInst( const InputLoc &loc, const char *data, bool isLabel ); + void makeRootNames(); + void makeNameTree( GraphDictEl *gdNode ); + void makeExportsNameTree(); + void fillNameIndex( NameInst *from ); + void printNameTree(); + + /* Increments the usage count on entry names. Names that are no longer + * needed will have their entry points unset. */ + void unsetObsoleteEntries( FsmAp *graph ); + + /* Resove name references in action code and epsilon transitions. */ + NameSet resolvePart( NameInst *refFrom, const char *data, bool recLabelsOnly ); + void resolveFrom( NameSet &result, NameInst *refFrom, + const NameRef &nameRef, int namePos ); + NameInst *resolveStateRef( const NameRef &nameRef, InputLoc &loc, Action *action ); + void resolveNameRefs( InlineList *inlineList, Action *action ); + void resolveActionNameRefs(); + + /* Set the alphabet type. If type types are not valid returns false. */ + bool setAlphType( char *s1, char *s2 ); + bool setAlphType( char *s1 ); + + /* Unique actions. */ + void removeDups( ActionTable &actionTable ); + void removeActionDups( FsmAp *graph ); + + /* Dumping the name instantiation tree. */ + void printNameInst( NameInst *nameInst, int level ); + + /* Make the graph from a graph dict node. Does minimization. */ + FsmAp *makeInstance( GraphDictEl *gdNode ); + FsmAp *makeSpecific( GraphDictEl *gdNode ); + FsmAp *makeAll(); + + /* Checking the contents of actions. */ + void checkAction( Action *action ); + void checkInlineList( Action *act, InlineList *inlineList ); + + void analyzeAction( Action *action, InlineList *inlineList ); + void analyzeGraph( FsmAp *graph ); + void makeExports(); + + void prepareMachineGen( GraphDictEl *graphDictEl ); + void generateXML( ostream &out ); + FsmAp *sectionGraph; + bool generatingSectionSubset; + + void initKeyOps(); + + /* + * Data collected during the parse. + */ + + /* Dictionary of graphs. Both instances and non-instances go here. */ + GraphDict graphDict; + + /* The list of instances. */ + GraphList instanceList; + + /* Dictionary of actions. Lets actions be defined and then referenced. */ + ActionDict actionDict; + + /* Dictionary of named priorities. */ + PriorDict priorDict; + + /* Dictionary of named local errors. */ + LocalErrDict localErrDict; + + /* List of actions. Will be pasted into a switch statement. */ + ActionList actionList; + + /* The id of the next priority name and label. */ + int nextPriorKey, nextLocalErrKey, nextNameId, nextCondId; + + /* The default priority number key for a machine. This is active during + * the parse of the rhs of a machine assignment. */ + int curDefPriorKey; + + int curDefLocalErrKey; + + /* Alphabet type. */ + HostType *userAlphType; + bool alphTypeSet; + + /* Element type and get key expression. */ + InlineList *getKeyExpr; + InlineList *accessExpr; + InlineList *curStateExpr; + + /* The alphabet range. */ + char *lowerNum, *upperNum; + Key lowKey, highKey; + InputLoc rangeLowLoc, rangeHighLoc; + + /* The name of the file the fsm is from, and the spec name. */ + const char *fileName; + char *sectionName; + InputLoc sectionLoc; + + /* Number of errors encountered parsing the fsm spec. */ + int errorCount; + + /* Counting the action and priority ordering. */ + int curActionOrd; + int curPriorOrd; + + /* Root of the name tree. One root is for the instantiated machines. The + * other root is for exported definitions. */ + NameInst *rootName; + NameInst *exportsRootName; + + /* Name tree walking. */ + NameInst *curNameInst; + int curNameChild; + + /* The place where resolved epsilon transitions go. These cannot go into + * the parse tree because a single epsilon op can resolve more than once + * to different nameInsts if the machine it's in is used more than once. */ + NameVect epsilonResolvedLinks; + int nextEpsilonResolvedLink; + + /* Root of the name tree used for doing local name searches. */ + NameInst *localNameScope; + + void setLmInRetLoc( InlineList *inlineList ); + void initLongestMatchData(); + void setLongestMatchData( FsmAp *graph ); + void initNameWalk(); + void initExportsNameWalk(); + NameInst *nextNameScope() { return curNameInst->childVect[curNameChild]; } + NameFrame enterNameScope( bool isLocal, int numScopes ); + void popNameScope( const NameFrame &frame ); + void resetNameScope( const NameFrame &frame ); + + /* Make name ids to name inst pointers. */ + NameInst **nameIndex; + + /* Counter for assigning ids to longest match items. */ + int nextLongestMatchId; + bool lmRequiresErrorState; + + /* List of all longest match parse tree items. */ + LmList lmList; + + Action *newAction(const char *name, InlineList *inlineList ); + + Action *initTokStart; + int initTokStartOrd; + + Action *setTokStart; + int setTokStartOrd; + + Action *initActId; + int initActIdOrd; + + Action *setTokEnd; + int setTokEndOrd; + + void beginProcessing() + { + ::condData = &thisCondData; + ::keyOps = &thisKeyOps; + } + + CondData thisCondData; + KeyOps thisKeyOps; + + ExportList exportList; +}; + +void afterOpMinimize( FsmAp *fsm, bool lastInSeq = true ); +Key makeFsmKeyHex( char *str, const InputLoc &loc, ParseData *pd ); +Key makeFsmKeyDec( char *str, const InputLoc &loc, ParseData *pd ); +Key makeFsmKeyNum( char *str, const InputLoc &loc, ParseData *pd ); +Key makeFsmKeyChar( char c, ParseData *pd ); +void makeFsmKeyArray( Key *result, char *data, int len, ParseData *pd ); +void makeFsmUniqueKeyArray( KeySet &result, char *data, int len, + bool caseInsensitive, ParseData *pd ); +FsmAp *makeBuiltin( BuiltinMachine builtin, ParseData *pd ); +FsmAp *dotFsm( ParseData *pd ); +FsmAp *dotStarFsm( ParseData *pd ); + +void errorStateLabels( const NameSet &locations ); + +/* Data used by the parser specific to the current file. Supports the include + * system, since a new parser is executed for each included file. */ +struct InputData +{ + InputData( char *fileName, char *includeSpec, char *includeTo ) : + pd(0), sectionName(0), defaultParseData(0), + first_line(1), first_column(1), + last_line(1), last_column(0), + fileName(fileName), includeSpec(includeSpec), + includeTo(includeTo), active(true) + {} + + /* For collecting a name references. */ + NameRef nameRef; + NameRefList nameRefList; + + /* The parse data. For each fsm spec, the parser collects things that it parses + * in data structures in here. */ + ParseData *pd; + + char *sectionName; + ParseData *defaultParseData; + + int first_line; + int first_column; + int last_line; + int last_column; + + char *fileName; + + /* If this is an included file, this contains the specification to search + * for. IncludeTo will contain the spec name that does the includng. */ + char *includeSpec; + char *includeTo; + + bool active; + InputLoc sectionLoc; +}; + +struct Parser; + +typedef AvlMap<char*, Parser *, CmpStr> ParserDict; +typedef AvlMapEl<char*, Parser *> ParserDictEl; + +extern ParserDict parserDict; + + +#endif /* _PARSEDATA_H */ diff --git a/contrib/tools/ragel5/ragel/parsetree.cpp b/contrib/tools/ragel5/ragel/parsetree.cpp new file mode 100644 index 00000000000..4755e3085ba --- /dev/null +++ b/contrib/tools/ragel5/ragel/parsetree.cpp @@ -0,0 +1,2089 @@ +/* + * Copyright 2001-2006 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <iostream> +#include <iomanip> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +/* Parsing. */ +#include "ragel.h" +#include "rlparse.h" +#include "parsetree.h" + +using namespace std; +ostream &operator<<( ostream &out, const NameRef &nameRef ); +ostream &operator<<( ostream &out, const NameInst &nameInst ); + +/* Convert the literal string which comes in from the scanner into an array of + * characters with escapes and options interpreted. Also null terminates the + * string. Though this null termination should not be relied on for + * interpreting literals in the parser because the string may contain a + * literal string with \0 */ +void Token::prepareLitString( Token &result, bool &caseInsensitive ) +{ + result.data = new char[this->length+1]; + caseInsensitive = false; + + char *src = this->data + 1; + char *end = this->data + this->length - 1; + + while ( *end != '\'' && *end != '\"' ) { + if ( *end == 'i' ) + caseInsensitive = true; + else { + error( this->loc ) << "literal string '" << *end << + "' option not supported" << endl; + } + end -= 1; + } + + char *dest = result.data; + int len = 0; + while ( src != end ) { + if ( *src == '\\' ) { + switch ( src[1] ) { + case '0': dest[len++] = '\0'; break; + case 'a': dest[len++] = '\a'; break; + case 'b': dest[len++] = '\b'; break; + case 't': dest[len++] = '\t'; break; + case 'n': dest[len++] = '\n'; break; + case 'v': dest[len++] = '\v'; break; + case 'f': dest[len++] = '\f'; break; + case 'r': dest[len++] = '\r'; break; + case '\n': break; + default: dest[len++] = src[1]; break; + } + src += 2; + } + else { + dest[len++] = *src++; + } + } + result.length = len; + result.data[result.length] = 0; +} + + +FsmAp *VarDef::walk( ParseData *pd ) +{ + /* We enter into a new name scope. */ + NameFrame nameFrame = pd->enterNameScope( true, 1 ); + + /* Recurse on the expression. */ + FsmAp *rtnVal = joinOrLm->walk( pd ); + + /* Do the tranfer of local error actions. */ + LocalErrDictEl *localErrDictEl = pd->localErrDict.find( name ); + if ( localErrDictEl != 0 ) { + for ( StateList::Iter state = rtnVal->stateList; state.lte(); state++ ) + rtnVal->transferErrorActions( state, localErrDictEl->value ); + } + + /* If the expression below is a join operation with multiple expressions + * then it just had epsilon transisions resolved. If it is a join + * with only a single expression then run the epsilon op now. */ + if ( joinOrLm->type == JoinOrLm::JoinType && joinOrLm->join->exprList.length() == 1 ) + rtnVal->epsilonOp(); + + /* We can now unset entry points that are not longer used. */ + pd->unsetObsoleteEntries( rtnVal ); + + /* If the name of the variable is referenced then add the entry point to + * the graph. */ + if ( pd->curNameInst->numRefs > 0 ) + rtnVal->setEntry( pd->curNameInst->id, rtnVal->startState ); + + /* Pop the name scope. */ + pd->popNameScope( nameFrame ); + return rtnVal; +} + +void VarDef::makeNameTree( const InputLoc &loc, ParseData *pd ) +{ + /* The variable definition enters a new scope. */ + NameInst *prevNameInst = pd->curNameInst; + pd->curNameInst = pd->addNameInst( loc, name, false ); + + if ( joinOrLm->type == JoinOrLm::LongestMatchType ) + pd->curNameInst->isLongestMatch = true; + + /* Recurse. */ + joinOrLm->makeNameTree( pd ); + + /* The name scope ends, pop the name instantiation. */ + pd->curNameInst = prevNameInst; +} + +void VarDef::resolveNameRefs( ParseData *pd ) +{ + /* Entering into a new scope. */ + NameFrame nameFrame = pd->enterNameScope( true, 1 ); + + /* Recurse. */ + joinOrLm->resolveNameRefs( pd ); + + /* The name scope ends, pop the name instantiation. */ + pd->popNameScope( nameFrame ); +} + +InputLoc LongestMatchPart::getLoc() +{ + return action != 0 ? action->loc : semiLoc; +} + +/* + * If there are any LMs then all of the following entry points must reset + * tokstart: + * + * 1. fentry(StateRef) + * 2. ftoto(StateRef), fcall(StateRef), fnext(StateRef) + * 3. targt of any transition that has an fcall (the return loc). + * 4. start state of all longest match routines. + */ + +Action *LongestMatch::newAction( ParseData *pd, const InputLoc &loc, + const char *name, InlineList *inlineList ) +{ + Action *action = new Action( loc, name, inlineList, pd->nextCondId++ ); + action->actionRefs.append( pd->curNameInst ); + pd->actionList.append( action ); + action->isLmAction = true; + return action; +} + +void LongestMatch::makeActions( ParseData *pd ) +{ + /* Make actions that set the action id. */ + for ( LmPartList::Iter lmi = *longestMatchList; lmi.lte(); lmi++ ) { + /* For each part create actions for setting the match type. We need + * to do this so that the actions will go into the actionIndex. */ + InlineList *inlineList = new InlineList; + inlineList->append( new InlineItem( lmi->getLoc(), this, lmi, InlineItem::LmSetActId ) ); + char *actName = new char[50]; + sprintf( actName, "store%i", lmi->longestMatchId ); + lmi->setActId = newAction( pd, lmi->getLoc(), actName, inlineList ); + } + + /* Make actions that execute the user action and restart on the last character. */ + for ( LmPartList::Iter lmi = *longestMatchList; lmi.lte(); lmi++ ) { + /* For each part create actions for setting the match type. We need + * to do this so that the actions will go into the actionIndex. */ + InlineList *inlineList = new InlineList; + inlineList->append( new InlineItem( lmi->getLoc(), this, lmi, + InlineItem::LmOnLast ) ); + char *actName = new char[50]; + sprintf( actName, "imm%i", lmi->longestMatchId ); + lmi->actOnLast = newAction( pd, lmi->getLoc(), actName, inlineList ); + } + + /* Make actions that execute the user action and restart on the next + * character. These actions will set tokend themselves (it is the current + * char). */ + for ( LmPartList::Iter lmi = *longestMatchList; lmi.lte(); lmi++ ) { + /* For each part create actions for setting the match type. We need + * to do this so that the actions will go into the actionIndex. */ + InlineList *inlineList = new InlineList; + inlineList->append( new InlineItem( lmi->getLoc(), this, lmi, + InlineItem::LmOnNext ) ); + char *actName = new char[50]; + sprintf( actName, "lagh%i", lmi->longestMatchId ); + lmi->actOnNext = newAction( pd, lmi->getLoc(), actName, inlineList ); + } + + /* Make actions that execute the user action and restart at tokend. These + * actions execute some time after matching the last char. */ + for ( LmPartList::Iter lmi = *longestMatchList; lmi.lte(); lmi++ ) { + /* For each part create actions for setting the match type. We need + * to do this so that the actions will go into the actionIndex. */ + InlineList *inlineList = new InlineList; + inlineList->append( new InlineItem( lmi->getLoc(), this, lmi, + InlineItem::LmOnLagBehind ) ); + char *actName = new char[50]; + sprintf( actName, "lag%i", lmi->longestMatchId ); + lmi->actLagBehind = newAction( pd, lmi->getLoc(), actName, inlineList ); + } + + InputLoc loc; + loc.line = 1; + loc.col = 1; + + /* Create the error action. */ + InlineList *il6 = new InlineList; + il6->append( new InlineItem( loc, this, 0, InlineItem::LmSwitch ) ); + lmActSelect = newAction( pd, loc, "lagsel", il6 ); +} + +void LongestMatch::findName( ParseData *pd ) +{ + NameInst *nameInst = pd->curNameInst; + while ( nameInst->name == 0 ) { + nameInst = nameInst->parent; + /* Since every machine must must have a name, we should always find a + * name for the longest match. */ + assert( nameInst != 0 ); + } + name = nameInst->name; +} + +void LongestMatch::makeNameTree( ParseData *pd ) +{ + /* Create an anonymous scope for the longest match. Will be used for + * restarting machine after matching a token. */ + NameInst *prevNameInst = pd->curNameInst; + pd->curNameInst = pd->addNameInst( loc, 0, false ); + + /* Recurse into all parts of the longest match operator. */ + for ( LmPartList::Iter lmi = *longestMatchList; lmi.lte(); lmi++ ) + lmi->join->makeNameTree( pd ); + + /* Traverse the name tree upwards to find a name for this lm. */ + findName( pd ); + + /* Also make the longest match's actions at this point. */ + makeActions( pd ); + + /* The name scope ends, pop the name instantiation. */ + pd->curNameInst = prevNameInst; +} + +void LongestMatch::resolveNameRefs( ParseData *pd ) +{ + /* The longest match gets its own name scope. */ + NameFrame nameFrame = pd->enterNameScope( true, 1 ); + + /* Take an action reference for each longest match item and recurse. */ + for ( LmPartList::Iter lmi = *longestMatchList; lmi.lte(); lmi++ ) { + /* Record the reference if the item has an action. */ + if ( lmi->action != 0 ) + lmi->action->actionRefs.append( pd->localNameScope ); + + /* Recurse down the join. */ + lmi->join->resolveNameRefs( pd ); + } + + /* The name scope ends, pop the name instantiation. */ + pd->popNameScope( nameFrame ); +} + +void LongestMatch::restart( FsmAp *graph, TransAp *trans ) +{ + StateAp *fromState = trans->fromState; + graph->detachTrans( fromState, trans->toState, trans ); + graph->attachTrans( fromState, graph->startState, trans ); +} + +void LongestMatch::runLonestMatch( ParseData *pd, FsmAp *graph ) +{ + graph->markReachableFromHereStopFinal( graph->startState ); + for ( StateList::Iter ms = graph->stateList; ms.lte(); ms++ ) { + if ( ms->stateBits & SB_ISMARKED ) { + ms->lmItemSet.insert( 0 ); + ms->stateBits &= ~ SB_ISMARKED; + } + } + + /* Transfer the first item of non-empty lmAction tables to the item sets + * of the states that follow. Exclude states that have no transitions out. + * This must happen on a separate pass so that on each iteration of the + * next pass we have the item set entries from all lmAction tables. */ + for ( StateList::Iter st = graph->stateList; st.lte(); st++ ) { + for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) { + if ( trans->lmActionTable.length() > 0 ) { + LmActionTableEl *lmAct = trans->lmActionTable.data; + StateAp *toState = trans->toState; + assert( toState ); + + /* Check if there are transitions out, this may be a very + * close approximation? Out transitions going nowhere? + * FIXME: Check. */ + if ( toState->outList.length() > 0 ) { + /* Fill the item sets. */ + graph->markReachableFromHereStopFinal( toState ); + for ( StateList::Iter ms = graph->stateList; ms.lte(); ms++ ) { + if ( ms->stateBits & SB_ISMARKED ) { + ms->lmItemSet.insert( lmAct->value ); + ms->stateBits &= ~ SB_ISMARKED; + } + } + } + } + } + } + + /* The lmItem sets are now filled, telling us which longest match rules + * can succeed in which states. First determine if we need to make sure + * act is defaulted to zero. We need to do this if there are any states + * with lmItemSet.length() > 1 and NULL is included. That is, that the + * switch may get called when in fact nothing has been matched. */ + int maxItemSetLength = 0; + graph->markReachableFromHereStopFinal( graph->startState ); + for ( StateList::Iter ms = graph->stateList; ms.lte(); ms++ ) { + if ( ms->stateBits & SB_ISMARKED ) { + if ( ms->lmItemSet.length() > maxItemSetLength ) + maxItemSetLength = ms->lmItemSet.length(); + ms->stateBits &= ~ SB_ISMARKED; + } + } + + /* The actions executed on starting to match a token. */ + graph->startState->toStateActionTable.setAction( pd->initTokStartOrd, pd->initTokStart ); + graph->startState->fromStateActionTable.setAction( pd->setTokStartOrd, pd->setTokStart ); + if ( maxItemSetLength > 1 ) { + /* The longest match action switch may be called when tokens are + * matched, in which case act must be initialized, there must be a + * case to handle the error, and the generated machine will require an + * error state. */ + lmSwitchHandlesError = true; + pd->lmRequiresErrorState = true; + graph->startState->toStateActionTable.setAction( pd->initActIdOrd, pd->initActId ); + } + + /* The place to store transitions to restart. It maybe possible for the + * restarting to affect the searching through the graph that follows. For + * now take the safe route and save the list of transitions to restart + * until after all searching is done. */ + Vector<TransAp*> restartTrans; + + /* Set actions that do immediate token recognition, set the longest match part + * id and set the token ending. */ + for ( StateList::Iter st = graph->stateList; st.lte(); st++ ) { + for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) { + if ( trans->lmActionTable.length() > 0 ) { + LmActionTableEl *lmAct = trans->lmActionTable.data; + StateAp *toState = trans->toState; + assert( toState ); + + /* Check if there are transitions out, this may be a very + * close approximation? Out transitions going nowhere? + * FIXME: Check. */ + if ( toState->outList.length() == 0 ) { + /* Can execute the immediate action for the longest match + * part. Redirect the action to the start state. */ + trans->actionTable.setAction( lmAct->key, + lmAct->value->actOnLast ); + restartTrans.append( trans ); + } + else { + /* Look for non final states that have a non-empty item + * set. If these are present then we need to record the + * end of the token. Also Find the highest item set + * length reachable from here (excluding at transtions to + * final states). */ + bool nonFinalNonEmptyItemSet = false; + maxItemSetLength = 0; + graph->markReachableFromHereStopFinal( toState ); + for ( StateList::Iter ms = graph->stateList; ms.lte(); ms++ ) { + if ( ms->stateBits & SB_ISMARKED ) { + if ( ms->lmItemSet.length() > 0 && !ms->isFinState() ) + nonFinalNonEmptyItemSet = true; + if ( ms->lmItemSet.length() > maxItemSetLength ) + maxItemSetLength = ms->lmItemSet.length(); + ms->stateBits &= ~ SB_ISMARKED; + } + } + + /* If there are reachable states that are not final and + * have non empty item sets or that have an item set + * length greater than one then we need to set tokend + * because the error action that matches the token will + * require it. */ + if ( nonFinalNonEmptyItemSet || maxItemSetLength > 1 ) + trans->actionTable.setAction( pd->setTokEndOrd, pd->setTokEnd ); + + /* Some states may not know which longest match item to + * execute, must set it. */ + if ( maxItemSetLength > 1 ) { + /* There are transitions out, another match may come. */ + trans->actionTable.setAction( lmAct->key, + lmAct->value->setActId ); + } + } + } + } + } + + /* Now that all graph searching is done it certainly safe set the + * restarting. It may be safe above, however this must be verified. */ + for ( Vector<TransAp*>::Iter pt = restartTrans; pt.lte(); pt++ ) + restart( graph, *pt ); + + int lmErrActionOrd = pd->curActionOrd++; + + /* Embed the error for recognizing a char. */ + for ( StateList::Iter st = graph->stateList; st.lte(); st++ ) { + if ( st->lmItemSet.length() == 1 && st->lmItemSet[0] != 0 ) { + if ( st->isFinState() ) { + /* On error execute the onActNext action, which knows that + * the last character of the token was one back and restart. */ + graph->setErrorTarget( st, graph->startState, &lmErrActionOrd, + &st->lmItemSet[0]->actOnNext, 1 ); + } + else { + graph->setErrorTarget( st, graph->startState, &lmErrActionOrd, + &st->lmItemSet[0]->actLagBehind, 1 ); + } + } + else if ( st->lmItemSet.length() > 1 ) { + /* Need to use the select. Take note of the which items the select + * is needed for so only the necessary actions are included. */ + for ( LmItemSet::Iter plmi = st->lmItemSet; plmi.lte(); plmi++ ) { + if ( *plmi != 0 ) + (*plmi)->inLmSelect = true; + } + /* On error, execute the action select and go to the start state. */ + graph->setErrorTarget( st, graph->startState, &lmErrActionOrd, + &lmActSelect, 1 ); + } + } + + /* Finally, the start state should be made final. */ + graph->setFinState( graph->startState ); +} + +FsmAp *LongestMatch::walk( ParseData *pd ) +{ + /* The longest match has it's own name scope. */ + NameFrame nameFrame = pd->enterNameScope( true, 1 ); + + /* Make each part of the longest match. */ + FsmAp **parts = new FsmAp*[longestMatchList->length()]; + LmPartList::Iter lmi = *longestMatchList; + for ( int i = 0; lmi.lte(); lmi++, i++ ) { + /* Create the machine and embed the setting of the longest match id. */ + parts[i] = lmi->join->walk( pd ); + parts[i]->longMatchAction( pd->curActionOrd++, lmi ); + } + + /* Union machines one and up with machine zero. The grammar dictates that + * there will always be at least one part. */ + FsmAp *rtnVal = parts[0]; + for ( int i = 1; i < longestMatchList->length(); i++ ) { + rtnVal->unionOp( parts[i] ); + afterOpMinimize( rtnVal ); + } + + runLonestMatch( pd, rtnVal ); + + /* Pop the name scope. */ + pd->popNameScope( nameFrame ); + + delete[] parts; + return rtnVal; +} + +FsmAp *JoinOrLm::walk( ParseData *pd ) +{ + FsmAp *rtnVal = 0; + switch ( type ) { + case JoinType: + rtnVal = join->walk( pd ); + break; + case LongestMatchType: + rtnVal = longestMatch->walk( pd ); + break; + } + return rtnVal; +} + +void JoinOrLm::makeNameTree( ParseData *pd ) +{ + switch ( type ) { + case JoinType: + join->makeNameTree( pd ); + break; + case LongestMatchType: + longestMatch->makeNameTree( pd ); + break; + } +} + +void JoinOrLm::resolveNameRefs( ParseData *pd ) +{ + switch ( type ) { + case JoinType: + join->resolveNameRefs( pd ); + break; + case LongestMatchType: + longestMatch->resolveNameRefs( pd ); + break; + } +} + + +/* Construct with a location and the first expression. */ +Join::Join( const InputLoc &loc, Expression *expr ) +: + loc(loc) +{ + exprList.append( expr ); +} + +/* Construct with a location and the first expression. */ +Join::Join( Expression *expr ) +: + loc(loc) +{ + exprList.append( expr ); +} + +/* Walk an expression node. */ +FsmAp *Join::walk( ParseData *pd ) +{ + if ( exprList.length() > 1 ) + return walkJoin( pd ); + else + return exprList.head->walk( pd ); +} + +/* There is a list of expressions to join. */ +FsmAp *Join::walkJoin( ParseData *pd ) +{ + /* We enter into a new name scope. */ + NameFrame nameFrame = pd->enterNameScope( true, 1 ); + + /* Evaluate the machines. */ + FsmAp **fsms = new FsmAp*[exprList.length()]; + ExprList::Iter expr = exprList; + for ( int e = 0; e < exprList.length(); e++, expr++ ) + fsms[e] = expr->walk( pd ); + + /* Get the start and final names. Final is + * guaranteed to exist, start is not. */ + NameInst *startName = pd->curNameInst->start; + NameInst *finalName = pd->curNameInst->final; + + int startId = -1; + if ( startName != 0 ) { + /* Take note that there was an implicit link to the start machine. */ + pd->localNameScope->referencedNames.append( startName ); + startId = startName->id; + } + + /* A final id of -1 indicates there is no epsilon that references the + * final state, therefor do not create one or set an entry point to it. */ + int finalId = -1; + if ( finalName->numRefs > 0 ) + finalId = finalName->id; + + /* Join machines 1 and up onto machine 0. */ + FsmAp *retFsm = fsms[0]; + retFsm->joinOp( startId, finalId, fsms+1, exprList.length()-1 ); + + /* We can now unset entry points that are not longer used. */ + pd->unsetObsoleteEntries( retFsm ); + + /* Pop the name scope. */ + pd->popNameScope( nameFrame ); + + delete[] fsms; + return retFsm; +} + +void Join::makeNameTree( ParseData *pd ) +{ + if ( exprList.length() > 1 ) { + /* Create the new anonymous scope. */ + NameInst *prevNameInst = pd->curNameInst; + pd->curNameInst = pd->addNameInst( loc, 0, false ); + + /* Join scopes need an implicit "final" target. */ + pd->curNameInst->final = new NameInst( InputLoc(), pd->curNameInst, "final", + pd->nextNameId++, false ); + + /* Recurse into all expressions in the list. */ + for ( ExprList::Iter expr = exprList; expr.lte(); expr++ ) + expr->makeNameTree( pd ); + + /* The name scope ends, pop the name instantiation. */ + pd->curNameInst = prevNameInst; + } + else { + /* Recurse into the single expression. */ + exprList.head->makeNameTree( pd ); + } +} + + +void Join::resolveNameRefs( ParseData *pd ) +{ + /* Branch on whether or not there is to be a join. */ + if ( exprList.length() > 1 ) { + /* The variable definition enters a new scope. */ + NameFrame nameFrame = pd->enterNameScope( true, 1 ); + + /* The join scope must contain a start label. */ + NameSet resolved = pd->resolvePart( pd->localNameScope, "start", true ); + if ( resolved.length() > 0 ) { + /* Take the first. */ + pd->curNameInst->start = resolved[0]; + if ( resolved.length() > 1 ) { + /* Complain about the multiple references. */ + error(loc) << "multiple start labels" << endl; + errorStateLabels( resolved ); + } + } + + /* Make sure there is a start label. */ + if ( pd->curNameInst->start != 0 ) { + /* There is an implicit reference to start name. */ + pd->curNameInst->start->numRefs += 1; + } + else { + /* No start label. Complain and recover by adding a label to the + * adding one. Recover ignoring the problem. */ + error(loc) << "no start label" << endl; + } + + /* Recurse into all expressions in the list. */ + for ( ExprList::Iter expr = exprList; expr.lte(); expr++ ) + expr->resolveNameRefs( pd ); + + /* The name scope ends, pop the name instantiation. */ + pd->popNameScope( nameFrame ); + } + else { + /* Recurse into the single expression. */ + exprList.head->resolveNameRefs( pd ); + } +} + +/* Clean up after an expression node. */ +Expression::~Expression() +{ + switch ( type ) { + case OrType: case IntersectType: case SubtractType: + case StrongSubtractType: + delete expression; + delete term; + break; + case TermType: + delete term; + break; + case BuiltinType: + break; + } +} + +/* Evaluate a single expression node. */ +FsmAp *Expression::walk( ParseData *pd, bool lastInSeq ) +{ + FsmAp *rtnVal = 0; + switch ( type ) { + case OrType: { + /* Evaluate the expression. */ + rtnVal = expression->walk( pd, false ); + /* Evaluate the term. */ + FsmAp *rhs = term->walk( pd ); + /* Perform union. */ + rtnVal->unionOp( rhs ); + afterOpMinimize( rtnVal, lastInSeq ); + break; + } + case IntersectType: { + /* Evaluate the expression. */ + rtnVal = expression->walk( pd ); + /* Evaluate the term. */ + FsmAp *rhs = term->walk( pd ); + /* Perform intersection. */ + rtnVal->intersectOp( rhs ); + afterOpMinimize( rtnVal, lastInSeq ); + break; + } + case SubtractType: { + /* Evaluate the expression. */ + rtnVal = expression->walk( pd ); + /* Evaluate the term. */ + FsmAp *rhs = term->walk( pd ); + /* Perform subtraction. */ + rtnVal->subtractOp( rhs ); + afterOpMinimize( rtnVal, lastInSeq ); + break; + } + case StrongSubtractType: { + /* Evaluate the expression. */ + rtnVal = expression->walk( pd ); + + /* Evaluate the term and pad it with any* machines. */ + FsmAp *rhs = dotStarFsm( pd ); + FsmAp *termFsm = term->walk( pd ); + FsmAp *trailAnyStar = dotStarFsm( pd ); + rhs->concatOp( termFsm ); + rhs->concatOp( trailAnyStar ); + + /* Perform subtraction. */ + rtnVal->subtractOp( rhs ); + afterOpMinimize( rtnVal, lastInSeq ); + break; + } + case TermType: { + /* Return result of the term. */ + rtnVal = term->walk( pd ); + break; + } + case BuiltinType: { + /* Duplicate the builtin. */ + rtnVal = makeBuiltin( builtin, pd ); + break; + } + } + + return rtnVal; +} + +void Expression::makeNameTree( ParseData *pd ) +{ + switch ( type ) { + case OrType: + case IntersectType: + case SubtractType: + case StrongSubtractType: + expression->makeNameTree( pd ); + term->makeNameTree( pd ); + break; + case TermType: + term->makeNameTree( pd ); + break; + case BuiltinType: + break; + } +} + +void Expression::resolveNameRefs( ParseData *pd ) +{ + switch ( type ) { + case OrType: + case IntersectType: + case SubtractType: + case StrongSubtractType: + expression->resolveNameRefs( pd ); + term->resolveNameRefs( pd ); + break; + case TermType: + term->resolveNameRefs( pd ); + break; + case BuiltinType: + break; + } +} + +/* Clean up after a term node. */ +Term::~Term() +{ + switch ( type ) { + case ConcatType: + case RightStartType: + case RightFinishType: + case LeftType: + delete term; + delete factorWithAug; + break; + case FactorWithAugType: + delete factorWithAug; + break; + } +} + +/* Evaluate a term node. */ +FsmAp *Term::walk( ParseData *pd, bool lastInSeq ) +{ + FsmAp *rtnVal = 0; + switch ( type ) { + case ConcatType: { + /* Evaluate the Term. */ + rtnVal = term->walk( pd, false ); + /* Evaluate the FactorWithRep. */ + FsmAp *rhs = factorWithAug->walk( pd ); + /* Perform concatenation. */ + rtnVal->concatOp( rhs ); + afterOpMinimize( rtnVal, lastInSeq ); + break; + } + case RightStartType: { + /* Evaluate the Term. */ + rtnVal = term->walk( pd ); + + /* Evaluate the FactorWithRep. */ + FsmAp *rhs = factorWithAug->walk( pd ); + + /* Set up the priority descriptors. The left machine gets the + * lower priority where as the right get the higher start priority. */ + priorDescs[0].key = pd->nextPriorKey++; + priorDescs[0].priority = 0; + rtnVal->allTransPrior( pd->curPriorOrd++, &priorDescs[0] ); + + /* The start transitions right machine get the higher priority. + * Use the same unique key. */ + priorDescs[1].key = priorDescs[0].key; + priorDescs[1].priority = 1; + rhs->startFsmPrior( pd->curPriorOrd++, &priorDescs[1] ); + + /* Perform concatenation. */ + rtnVal->concatOp( rhs ); + afterOpMinimize( rtnVal, lastInSeq ); + break; + } + case RightFinishType: { + /* Evaluate the Term. */ + rtnVal = term->walk( pd ); + + /* Evaluate the FactorWithRep. */ + FsmAp *rhs = factorWithAug->walk( pd ); + + /* Set up the priority descriptors. The left machine gets the + * lower priority where as the finishing transitions to the right + * get the higher priority. */ + priorDescs[0].key = pd->nextPriorKey++; + priorDescs[0].priority = 0; + rtnVal->allTransPrior( pd->curPriorOrd++, &priorDescs[0] ); + + /* The finishing transitions of the right machine get the higher + * priority. Use the same unique key. */ + priorDescs[1].key = priorDescs[0].key; + priorDescs[1].priority = 1; + rhs->finishFsmPrior( pd->curPriorOrd++, &priorDescs[1] ); + + /* Perform concatenation. */ + rtnVal->concatOp( rhs ); + afterOpMinimize( rtnVal, lastInSeq ); + break; + } + case LeftType: { + /* Evaluate the Term. */ + rtnVal = term->walk( pd ); + + /* Evaluate the FactorWithRep. */ + FsmAp *rhs = factorWithAug->walk( pd ); + + /* Set up the priority descriptors. The left machine gets the + * higher priority. */ + priorDescs[0].key = pd->nextPriorKey++; + priorDescs[0].priority = 1; + rtnVal->allTransPrior( pd->curPriorOrd++, &priorDescs[0] ); + + /* The right machine gets the lower priority. Since + * startTransPrior might unnecessarily increase the number of + * states during the state machine construction process (due to + * isolation), we use allTransPrior instead, which has the same + * effect. */ + priorDescs[1].key = priorDescs[0].key; + priorDescs[1].priority = 0; + rhs->allTransPrior( pd->curPriorOrd++, &priorDescs[1] ); + + /* Perform concatenation. */ + rtnVal->concatOp( rhs ); + afterOpMinimize( rtnVal, lastInSeq ); + break; + } + case FactorWithAugType: { + rtnVal = factorWithAug->walk( pd ); + break; + } + } + return rtnVal; +} + +void Term::makeNameTree( ParseData *pd ) +{ + switch ( type ) { + case ConcatType: + case RightStartType: + case RightFinishType: + case LeftType: + term->makeNameTree( pd ); + factorWithAug->makeNameTree( pd ); + break; + case FactorWithAugType: + factorWithAug->makeNameTree( pd ); + break; + } +} + +void Term::resolveNameRefs( ParseData *pd ) +{ + switch ( type ) { + case ConcatType: + case RightStartType: + case RightFinishType: + case LeftType: + term->resolveNameRefs( pd ); + factorWithAug->resolveNameRefs( pd ); + break; + case FactorWithAugType: + factorWithAug->resolveNameRefs( pd ); + break; + } +} + +/* Clean up after a factor with augmentation node. */ +FactorWithAug::~FactorWithAug() +{ + delete factorWithRep; + + /* Walk the vector of parser actions, deleting function names. */ + + /* Clean up priority descriptors. */ + if ( priorDescs != 0 ) + delete[] priorDescs; +} + +void FactorWithAug::assignActions( ParseData *pd, FsmAp *graph, int *actionOrd ) +{ + /* Assign actions. */ + for ( int i = 0; i < actions.length(); i++ ) { + switch ( actions[i].type ) { + /* Transition actions. */ + case at_start: + graph->startFsmAction( actionOrd[i], actions[i].action ); + afterOpMinimize( graph ); + break; + case at_all: + graph->allTransAction( actionOrd[i], actions[i].action ); + break; + case at_finish: + graph->finishFsmAction( actionOrd[i], actions[i].action ); + break; + case at_leave: + graph->leaveFsmAction( actionOrd[i], actions[i].action ); + break; + + /* Global error actions. */ + case at_start_gbl_error: + graph->startErrorAction( actionOrd[i], actions[i].action, 0 ); + afterOpMinimize( graph ); + break; + case at_all_gbl_error: + graph->allErrorAction( actionOrd[i], actions[i].action, 0 ); + break; + case at_final_gbl_error: + graph->finalErrorAction( actionOrd[i], actions[i].action, 0 ); + break; + case at_not_start_gbl_error: + graph->notStartErrorAction( actionOrd[i], actions[i].action, 0 ); + break; + case at_not_final_gbl_error: + graph->notFinalErrorAction( actionOrd[i], actions[i].action, 0 ); + break; + case at_middle_gbl_error: + graph->middleErrorAction( actionOrd[i], actions[i].action, 0 ); + break; + + /* Local error actions. */ + case at_start_local_error: + graph->startErrorAction( actionOrd[i], actions[i].action, + actions[i].localErrKey ); + afterOpMinimize( graph ); + break; + case at_all_local_error: + graph->allErrorAction( actionOrd[i], actions[i].action, + actions[i].localErrKey ); + break; + case at_final_local_error: + graph->finalErrorAction( actionOrd[i], actions[i].action, + actions[i].localErrKey ); + break; + case at_not_start_local_error: + graph->notStartErrorAction( actionOrd[i], actions[i].action, + actions[i].localErrKey ); + break; + case at_not_final_local_error: + graph->notFinalErrorAction( actionOrd[i], actions[i].action, + actions[i].localErrKey ); + break; + case at_middle_local_error: + graph->middleErrorAction( actionOrd[i], actions[i].action, + actions[i].localErrKey ); + break; + + /* EOF actions. */ + case at_start_eof: + graph->startEOFAction( actionOrd[i], actions[i].action ); + afterOpMinimize( graph ); + break; + case at_all_eof: + graph->allEOFAction( actionOrd[i], actions[i].action ); + break; + case at_final_eof: + graph->finalEOFAction( actionOrd[i], actions[i].action ); + break; + case at_not_start_eof: + graph->notStartEOFAction( actionOrd[i], actions[i].action ); + break; + case at_not_final_eof: + graph->notFinalEOFAction( actionOrd[i], actions[i].action ); + break; + case at_middle_eof: + graph->middleEOFAction( actionOrd[i], actions[i].action ); + break; + + /* To State Actions. */ + case at_start_to_state: + graph->startToStateAction( actionOrd[i], actions[i].action ); + afterOpMinimize( graph ); + break; + case at_all_to_state: + graph->allToStateAction( actionOrd[i], actions[i].action ); + break; + case at_final_to_state: + graph->finalToStateAction( actionOrd[i], actions[i].action ); + break; + case at_not_start_to_state: + graph->notStartToStateAction( actionOrd[i], actions[i].action ); + break; + case at_not_final_to_state: + graph->notFinalToStateAction( actionOrd[i], actions[i].action ); + break; + case at_middle_to_state: + graph->middleToStateAction( actionOrd[i], actions[i].action ); + break; + + /* From State Actions. */ + case at_start_from_state: + graph->startFromStateAction( actionOrd[i], actions[i].action ); + afterOpMinimize( graph ); + break; + case at_all_from_state: + graph->allFromStateAction( actionOrd[i], actions[i].action ); + break; + case at_final_from_state: + graph->finalFromStateAction( actionOrd[i], actions[i].action ); + break; + case at_not_start_from_state: + graph->notStartFromStateAction( actionOrd[i], actions[i].action ); + break; + case at_not_final_from_state: + graph->notFinalFromStateAction( actionOrd[i], actions[i].action ); + break; + case at_middle_from_state: + graph->middleFromStateAction( actionOrd[i], actions[i].action ); + break; + + /* Remaining cases, prevented by the parser. */ + default: + assert( false ); + break; + } + } +} + +void FactorWithAug::assignPriorities( FsmAp *graph, int *priorOrd ) +{ + /* Assign priorities. */ + for ( int i = 0; i < priorityAugs.length(); i++ ) { + switch ( priorityAugs[i].type ) { + case at_start: + graph->startFsmPrior( priorOrd[i], &priorDescs[i]); + /* Start fsm priorities are a special case that may require + * minimization afterwards. */ + afterOpMinimize( graph ); + break; + case at_all: + graph->allTransPrior( priorOrd[i], &priorDescs[i] ); + break; + case at_finish: + graph->finishFsmPrior( priorOrd[i], &priorDescs[i] ); + break; + case at_leave: + graph->leaveFsmPrior( priorOrd[i], &priorDescs[i] ); + break; + + default: + /* Parser Prevents this case. */ + break; + } + } +} + +void FactorWithAug::assignConditions( FsmAp *graph ) +{ + for ( int i = 0; i < conditions.length(); i++ ) { + switch ( conditions[i].type ) { + /* Transition actions. */ + case at_start: + graph->startFsmCondition( conditions[i].action ); + afterOpMinimize( graph ); + break; + case at_all: + graph->allTransCondition( conditions[i].action ); + break; + case at_leave: + graph->leaveFsmCondition( conditions[i].action ); + break; + default: + break; + } + } +} + + +/* Evaluate a factor with augmentation node. */ +FsmAp *FactorWithAug::walk( ParseData *pd ) +{ + /* Enter into the scopes created for the labels. */ + NameFrame nameFrame = pd->enterNameScope( false, labels.length() ); + + /* Make the array of function orderings. */ + int *actionOrd = 0; + if ( actions.length() > 0 ) + actionOrd = new int[actions.length()]; + + /* First walk the list of actions, assigning order to all starting + * actions. */ + for ( int i = 0; i < actions.length(); i++ ) { + if ( actions[i].type == at_start || + actions[i].type == at_start_gbl_error || + actions[i].type == at_start_local_error || + actions[i].type == at_start_to_state || + actions[i].type == at_start_from_state || + actions[i].type == at_start_eof ) + actionOrd[i] = pd->curActionOrd++; + } + + /* Evaluate the factor with repetition. */ + FsmAp *rtnVal = factorWithRep->walk( pd ); + + /* Compute the remaining action orderings. */ + for ( int i = 0; i < actions.length(); i++ ) { + if ( actions[i].type != at_start && + actions[i].type != at_start_gbl_error && + actions[i].type != at_start_local_error && + actions[i].type != at_start_to_state && + actions[i].type != at_start_from_state && + actions[i].type != at_start_eof ) + actionOrd[i] = pd->curActionOrd++; + } + + /* Embed conditions. */ + assignConditions( rtnVal ); + + /* Embed actions. */ + assignActions( pd, rtnVal , actionOrd ); + + /* Make the array of priority orderings. Orderings are local to this walk + * of the factor with augmentation. */ + int *priorOrd = 0; + if ( priorityAugs.length() > 0 ) + priorOrd = new int[priorityAugs.length()]; + + /* Walk all priorities, assigning the priority ordering. */ + for ( int i = 0; i < priorityAugs.length(); i++ ) + priorOrd[i] = pd->curPriorOrd++; + + /* If the priority descriptors have not been made, make them now. Make + * priority descriptors for each priority asignment that will be passed to + * the fsm. Used to keep track of the key, value and used bit. */ + if ( priorDescs == 0 && priorityAugs.length() > 0 ) { + priorDescs = new PriorDesc[priorityAugs.length()]; + for ( int i = 0; i < priorityAugs.length(); i++ ) { + /* Init the prior descriptor for the priority setting. */ + priorDescs[i].key = priorityAugs[i].priorKey; + priorDescs[i].priority = priorityAugs[i].priorValue; + } + } + + /* Assign priorities into the machine. */ + assignPriorities( rtnVal, priorOrd ); + + /* Assign epsilon transitions. */ + for ( int e = 0; e < epsilonLinks.length(); e++ ) { + /* Get the name, which may not exist. If it doesn't then silently + * ignore it because an error has already been reported. */ + NameInst *epTarg = pd->epsilonResolvedLinks[pd->nextEpsilonResolvedLink++]; + if ( epTarg != 0 ) { + /* Make the epsilon transitions. */ + rtnVal->epsilonTrans( epTarg->id ); + + /* Note that we have made a link to the name. */ + pd->localNameScope->referencedNames.append( epTarg ); + } + } + + /* Set entry points for labels. */ + if ( labels.length() > 0 ) { + /* Pop the names. */ + pd->resetNameScope( nameFrame ); + + /* Make labels that are referenced into entry points. */ + for ( int i = 0; i < labels.length(); i++ ) { + pd->enterNameScope( false, 1 ); + + /* Will always be found. */ + NameInst *name = pd->curNameInst; + + /* If the name is referenced then set the entry point. */ + if ( name->numRefs > 0 ) + rtnVal->setEntry( name->id, rtnVal->startState ); + } + + pd->popNameScope( nameFrame ); + } + + if ( priorOrd != 0 ) + delete[] priorOrd; + if ( actionOrd != 0 ) + delete[] actionOrd; + return rtnVal; +} + +void FactorWithAug::makeNameTree( ParseData *pd ) +{ + /* Add the labels to the tree of instantiated names. Each label + * makes a new scope. */ + NameInst *prevNameInst = pd->curNameInst; + for ( int i = 0; i < labels.length(); i++ ) + pd->curNameInst = pd->addNameInst( labels[i].loc, labels[i].data, true ); + + /* Recurse, then pop the names. */ + factorWithRep->makeNameTree( pd ); + pd->curNameInst = prevNameInst; +} + + +void FactorWithAug::resolveNameRefs( ParseData *pd ) +{ + /* Enter into the name scope created by any labels. */ + NameFrame nameFrame = pd->enterNameScope( false, labels.length() ); + + /* Note action references. */ + for ( int i = 0; i < actions.length(); i++ ) + actions[i].action->actionRefs.append( pd->localNameScope ); + + /* Recurse first. IMPORTANT: we must do the exact same traversal as when + * the tree is constructed. */ + factorWithRep->resolveNameRefs( pd ); + + /* Resolve epsilon transitions. */ + for ( int ep = 0; ep < epsilonLinks.length(); ep++ ) { + /* Get the link. */ + EpsilonLink &link = epsilonLinks[ep]; + NameInst *resolvedName = 0; + + if ( link.target.length() == 1 && strcmp( link.target.data[0], "final" ) == 0 ) { + /* Epsilon drawn to an implicit final state. An implicit final is + * only available in join operations. */ + resolvedName = pd->localNameScope->final; + } + else { + /* Do an search for the name. */ + NameSet resolved; + pd->resolveFrom( resolved, pd->localNameScope, link.target, 0 ); + if ( resolved.length() > 0 ) { + /* Take the first one. */ + resolvedName = resolved[0]; + if ( resolved.length() > 1 ) { + /* Complain about the multiple references. */ + error(link.loc) << "state reference " << link.target << + " resolves to multiple entry points" << endl; + errorStateLabels( resolved ); + } + } + } + + /* This is tricky, we stuff resolved epsilon transitions into one long + * vector in the parse data structure. Since the name resolution and + * graph generation both do identical walks of the parse tree we + * should always find the link resolutions in the right place. */ + pd->epsilonResolvedLinks.append( resolvedName ); + + if ( resolvedName != 0 ) { + /* Found the name, bump of the reference count on it. */ + resolvedName->numRefs += 1; + } + else { + /* Complain, no recovery action, the epsilon op will ignore any + * epsilon transitions whose names did not resolve. */ + error(link.loc) << "could not resolve label " << link.target << endl; + } + } + + if ( labels.length() > 0 ) + pd->popNameScope( nameFrame ); +} + + +/* Clean up after a factor with repetition node. */ +FactorWithRep::~FactorWithRep() +{ + switch ( type ) { + case StarType: case StarStarType: case OptionalType: case PlusType: + case ExactType: case MaxType: case MinType: case RangeType: + delete factorWithRep; + break; + case FactorWithNegType: + delete factorWithNeg; + break; + } +} + +/* Evaluate a factor with repetition node. */ +FsmAp *FactorWithRep::walk( ParseData *pd ) +{ + FsmAp *retFsm = 0; + + switch ( type ) { + case StarType: { + /* Evaluate the FactorWithRep. */ + retFsm = factorWithRep->walk( pd ); + if ( retFsm->startState->isFinState() ) { + warning(loc) << "applying kleene star to a machine that " + "accepts zero length word" << endl; + } + + /* Shift over the start action orders then do the kleene star. */ + pd->curActionOrd += retFsm->shiftStartActionOrder( pd->curActionOrd ); + retFsm->starOp( ); + afterOpMinimize( retFsm ); + break; + } + case StarStarType: { + /* Evaluate the FactorWithRep. */ + retFsm = factorWithRep->walk( pd ); + if ( retFsm->startState->isFinState() ) { + warning(loc) << "applying kleene star to a machine that " + "accepts zero length word" << endl; + } + + /* Set up the prior descs. All gets priority one, whereas leaving gets + * priority zero. Make a unique key so that these priorities don't + * interfere with any priorities set by the user. */ + priorDescs[0].key = pd->nextPriorKey++; + priorDescs[0].priority = 1; + retFsm->allTransPrior( pd->curPriorOrd++, &priorDescs[0] ); + + /* Leaveing gets priority 0. Use same unique key. */ + priorDescs[1].key = priorDescs[0].key; + priorDescs[1].priority = 0; + retFsm->leaveFsmPrior( pd->curPriorOrd++, &priorDescs[1] ); + + /* Shift over the start action orders then do the kleene star. */ + pd->curActionOrd += retFsm->shiftStartActionOrder( pd->curActionOrd ); + retFsm->starOp( ); + afterOpMinimize( retFsm ); + break; + } + case OptionalType: { + /* Make the null fsm. */ + FsmAp *nu = new FsmAp(); + nu->lambdaFsm( ); + + /* Evaluate the FactorWithRep. */ + retFsm = factorWithRep->walk( pd ); + + /* Perform the question operator. */ + retFsm->unionOp( nu ); + afterOpMinimize( retFsm ); + break; + } + case PlusType: { + /* Evaluate the FactorWithRep. */ + retFsm = factorWithRep->walk( pd ); + if ( retFsm->startState->isFinState() ) { + warning(loc) << "applying plus operator to a machine that " + "accpets zero length word" << endl; + } + + /* Need a duplicated for the star end. */ + FsmAp *dup = new FsmAp( *retFsm ); + + /* The start func orders need to be shifted before doing the star. */ + pd->curActionOrd += dup->shiftStartActionOrder( pd->curActionOrd ); + + /* Star the duplicate. */ + dup->starOp( ); + afterOpMinimize( dup ); + + retFsm->concatOp( dup ); + afterOpMinimize( retFsm ); + break; + } + case ExactType: { + /* Get an int from the repetition amount. */ + if ( lowerRep == 0 ) { + /* No copies. Don't need to evaluate the factorWithRep. + * This Defeats the purpose so give a warning. */ + warning(loc) << "exactly zero repetitions results " + "in the null machine" << endl; + + retFsm = new FsmAp(); + retFsm->lambdaFsm(); + } + else { + /* Evaluate the first FactorWithRep. */ + retFsm = factorWithRep->walk( pd ); + if ( retFsm->startState->isFinState() ) { + warning(loc) << "applying repetition to a machine that " + "accepts zero length word" << endl; + } + + /* The start func orders need to be shifted before doing the + * repetition. */ + pd->curActionOrd += retFsm->shiftStartActionOrder( pd->curActionOrd ); + + /* Do the repetition on the machine. Already guarded against n == 0 */ + retFsm->repeatOp( lowerRep ); + afterOpMinimize( retFsm ); + } + break; + } + case MaxType: { + /* Get an int from the repetition amount. */ + if ( upperRep == 0 ) { + /* No copies. Don't need to evaluate the factorWithRep. + * This Defeats the purpose so give a warning. */ + warning(loc) << "max zero repetitions results " + "in the null machine" << endl; + + retFsm = new FsmAp(); + retFsm->lambdaFsm(); + } + else { + /* Evaluate the first FactorWithRep. */ + retFsm = factorWithRep->walk( pd ); + if ( retFsm->startState->isFinState() ) { + warning(loc) << "applying max repetition to a machine that " + "accepts zero length word" << endl; + } + + /* The start func orders need to be shifted before doing the + * repetition. */ + pd->curActionOrd += retFsm->shiftStartActionOrder( pd->curActionOrd ); + + /* Do the repetition on the machine. Already guarded against n == 0 */ + retFsm->optionalRepeatOp( upperRep ); + afterOpMinimize( retFsm ); + } + break; + } + case MinType: { + /* Evaluate the repeated machine. */ + retFsm = factorWithRep->walk( pd ); + if ( retFsm->startState->isFinState() ) { + warning(loc) << "applying min repetition to a machine that " + "accepts zero length word" << endl; + } + + /* The start func orders need to be shifted before doing the repetition + * and the kleene star. */ + pd->curActionOrd += retFsm->shiftStartActionOrder( pd->curActionOrd ); + + if ( lowerRep == 0 ) { + /* Acts just like a star op on the machine to return. */ + retFsm->starOp( ); + afterOpMinimize( retFsm ); + } + else { + /* Take a duplicate for the plus. */ + FsmAp *dup = new FsmAp( *retFsm ); + + /* Do repetition on the first half. */ + retFsm->repeatOp( lowerRep ); + afterOpMinimize( retFsm ); + + /* Star the duplicate. */ + dup->starOp( ); + afterOpMinimize( dup ); + + /* Tak on the kleene star. */ + retFsm->concatOp( dup ); + afterOpMinimize( retFsm ); + } + break; + } + case RangeType: { + /* Check for bogus range. */ + if ( upperRep - lowerRep < 0 ) { + error(loc) << "invalid range repetition" << endl; + + /* Return null machine as recovery. */ + retFsm = new FsmAp(); + retFsm->lambdaFsm(); + } + else if ( lowerRep == 0 && upperRep == 0 ) { + /* No copies. Don't need to evaluate the factorWithRep. This + * defeats the purpose so give a warning. */ + warning(loc) << "zero to zero repetitions results " + "in the null machine" << endl; + + retFsm = new FsmAp(); + retFsm->lambdaFsm(); + } + else { + /* Now need to evaluate the repeated machine. */ + retFsm = factorWithRep->walk( pd ); + if ( retFsm->startState->isFinState() ) { + warning(loc) << "applying range repetition to a machine that " + "accepts zero length word" << endl; + } + + /* The start func orders need to be shifted before doing both kinds + * of repetition. */ + pd->curActionOrd += retFsm->shiftStartActionOrder( pd->curActionOrd ); + + if ( lowerRep == 0 ) { + /* Just doing max repetition. Already guarded against n == 0. */ + retFsm->optionalRepeatOp( upperRep ); + afterOpMinimize( retFsm ); + } + else if ( lowerRep == upperRep ) { + /* Just doing exact repetition. Already guarded against n == 0. */ + retFsm->repeatOp( lowerRep ); + afterOpMinimize( retFsm ); + } + else { + /* This is the case that 0 < lowerRep < upperRep. Take a + * duplicate for the optional repeat. */ + FsmAp *dup = new FsmAp( *retFsm ); + + /* Do repetition on the first half. */ + retFsm->repeatOp( lowerRep ); + afterOpMinimize( retFsm ); + + /* Do optional repetition on the second half. */ + dup->optionalRepeatOp( upperRep - lowerRep ); + afterOpMinimize( dup ); + + /* Tak on the duplicate machine. */ + retFsm->concatOp( dup ); + afterOpMinimize( retFsm ); + } + } + break; + } + case FactorWithNegType: { + /* Evaluate the Factor. Pass it up. */ + retFsm = factorWithNeg->walk( pd ); + break; + }} + return retFsm; +} + +void FactorWithRep::makeNameTree( ParseData *pd ) +{ + switch ( type ) { + case StarType: + case StarStarType: + case OptionalType: + case PlusType: + case ExactType: + case MaxType: + case MinType: + case RangeType: + factorWithRep->makeNameTree( pd ); + break; + case FactorWithNegType: + factorWithNeg->makeNameTree( pd ); + break; + } +} + +void FactorWithRep::resolveNameRefs( ParseData *pd ) +{ + switch ( type ) { + case StarType: + case StarStarType: + case OptionalType: + case PlusType: + case ExactType: + case MaxType: + case MinType: + case RangeType: + factorWithRep->resolveNameRefs( pd ); + break; + case FactorWithNegType: + factorWithNeg->resolveNameRefs( pd ); + break; + } +} + +/* Clean up after a factor with negation node. */ +FactorWithNeg::~FactorWithNeg() +{ + switch ( type ) { + case NegateType: + case CharNegateType: + delete factorWithNeg; + break; + case FactorType: + delete factor; + break; + } +} + +/* Evaluate a factor with negation node. */ +FsmAp *FactorWithNeg::walk( ParseData *pd ) +{ + FsmAp *retFsm = 0; + + switch ( type ) { + case NegateType: { + /* Evaluate the factorWithNeg. */ + FsmAp *toNegate = factorWithNeg->walk( pd ); + + /* Negation is subtract from dot-star. */ + retFsm = dotStarFsm( pd ); + retFsm->subtractOp( toNegate ); + afterOpMinimize( retFsm ); + break; + } + case CharNegateType: { + /* Evaluate the factorWithNeg. */ + FsmAp *toNegate = factorWithNeg->walk( pd ); + + /* CharNegation is subtract from dot. */ + retFsm = dotFsm( pd ); + retFsm->subtractOp( toNegate ); + afterOpMinimize( retFsm ); + break; + } + case FactorType: { + /* Evaluate the Factor. Pass it up. */ + retFsm = factor->walk( pd ); + break; + }} + return retFsm; +} + +void FactorWithNeg::makeNameTree( ParseData *pd ) +{ + switch ( type ) { + case NegateType: + case CharNegateType: + factorWithNeg->makeNameTree( pd ); + break; + case FactorType: + factor->makeNameTree( pd ); + break; + } +} + +void FactorWithNeg::resolveNameRefs( ParseData *pd ) +{ + switch ( type ) { + case NegateType: + case CharNegateType: + factorWithNeg->resolveNameRefs( pd ); + break; + case FactorType: + factor->resolveNameRefs( pd ); + break; + } +} + +/* Clean up after a factor node. */ +Factor::~Factor() +{ + switch ( type ) { + case LiteralType: + delete literal; + break; + case RangeType: + delete range; + break; + case OrExprType: + delete reItem; + break; + case RegExprType: + delete regExpr; + break; + case ReferenceType: + break; + case ParenType: + delete join; + break; + case LongestMatchType: + delete longestMatch; + break; + } +} + +/* Evaluate a factor node. */ +FsmAp *Factor::walk( ParseData *pd ) +{ + FsmAp *rtnVal = 0; + switch ( type ) { + case LiteralType: + rtnVal = literal->walk( pd ); + break; + case RangeType: + rtnVal = range->walk( pd ); + break; + case OrExprType: + rtnVal = reItem->walk( pd, 0 ); + break; + case RegExprType: + rtnVal = regExpr->walk( pd, 0 ); + break; + case ReferenceType: + rtnVal = varDef->walk( pd ); + break; + case ParenType: + rtnVal = join->walk( pd ); + break; + case LongestMatchType: + rtnVal = longestMatch->walk( pd ); + break; + } + + return rtnVal; +} + +void Factor::makeNameTree( ParseData *pd ) +{ + switch ( type ) { + case LiteralType: + case RangeType: + case OrExprType: + case RegExprType: + break; + case ReferenceType: + varDef->makeNameTree( loc, pd ); + break; + case ParenType: + join->makeNameTree( pd ); + break; + case LongestMatchType: + longestMatch->makeNameTree( pd ); + break; + } +} + +void Factor::resolveNameRefs( ParseData *pd ) +{ + switch ( type ) { + case LiteralType: + case RangeType: + case OrExprType: + case RegExprType: + break; + case ReferenceType: + varDef->resolveNameRefs( pd ); + break; + case ParenType: + join->resolveNameRefs( pd ); + break; + case LongestMatchType: + longestMatch->resolveNameRefs( pd ); + break; + } +} + +/* Clean up a range object. Must delete the two literals. */ +Range::~Range() +{ + delete lowerLit; + delete upperLit; +} + +/* Evaluate a range. Gets the lower an upper key and makes an fsm range. */ +FsmAp *Range::walk( ParseData *pd ) +{ + /* Construct and verify the suitability of the lower end of the range. */ + FsmAp *lowerFsm = lowerLit->walk( pd ); + if ( !lowerFsm->checkSingleCharMachine() ) { + error(lowerLit->token.loc) << + "bad range lower end, must be a single character" << endl; + } + + /* Construct and verify the upper end. */ + FsmAp *upperFsm = upperLit->walk( pd ); + if ( !upperFsm->checkSingleCharMachine() ) { + error(upperLit->token.loc) << + "bad range upper end, must be a single character" << endl; + } + + /* Grab the keys from the machines, then delete them. */ + Key lowKey = lowerFsm->startState->outList.head->lowKey; + Key highKey = upperFsm->startState->outList.head->lowKey; + delete lowerFsm; + delete upperFsm; + + /* Validate the range. */ + if ( lowKey > highKey ) { + /* Recover by setting upper to lower; */ + error(lowerLit->token.loc) << "lower end of range is greater then upper end" << endl; + highKey = lowKey; + } + + /* Return the range now that it is validated. */ + FsmAp *retFsm = new FsmAp(); + retFsm->rangeFsm( lowKey, highKey ); + return retFsm; +} + +/* Evaluate a literal object. */ +FsmAp *Literal::walk( ParseData *pd ) +{ + /* FsmAp to return, is the alphabet signed. */ + FsmAp *rtnVal = 0; + + switch ( type ) { + case Number: { + /* Make the fsm key in int format. */ + Key fsmKey = makeFsmKeyNum( token.data, token.loc, pd ); + /* Make the new machine. */ + rtnVal = new FsmAp(); + rtnVal->concatFsm( fsmKey ); + break; + } + case LitString: { + /* Make the array of keys in int format. */ + Token interp; + bool caseInsensitive; + token.prepareLitString( interp, caseInsensitive ); + Key *arr = new Key[interp.length]; + makeFsmKeyArray( arr, interp.data, interp.length, pd ); + + /* Make the new machine. */ + rtnVal = new FsmAp(); + if ( caseInsensitive ) + rtnVal->concatFsmCI( arr, interp.length ); + else + rtnVal->concatFsm( arr, interp.length ); + delete[] interp.data; + delete[] arr; + break; + }} + return rtnVal; +} + +/* Clean up after a regular expression object. */ +RegExpr::~RegExpr() +{ + switch ( type ) { + case RecurseItem: + delete regExpr; + delete item; + break; + case Empty: + break; + } +} + +/* Evaluate a regular expression object. */ +FsmAp *RegExpr::walk( ParseData *pd, RegExpr *rootRegex ) +{ + /* This is the root regex, pass down a pointer to this. */ + if ( rootRegex == 0 ) + rootRegex = this; + + FsmAp *rtnVal = 0; + switch ( type ) { + case RecurseItem: { + /* Walk both items. */ + rtnVal = regExpr->walk( pd, rootRegex ); + FsmAp *fsm2 = item->walk( pd, rootRegex ); + rtnVal->concatOp( fsm2 ); + break; + } + case Empty: { + rtnVal = new FsmAp(); + rtnVal->lambdaFsm(); + break; + } + } + return rtnVal; +} + +/* Clean up after an item in a regular expression. */ +ReItem::~ReItem() +{ + switch ( type ) { + case Data: + case Dot: + break; + case OrBlock: + case NegOrBlock: + delete orBlock; + break; + } +} + +/* Evaluate a regular expression object. */ +FsmAp *ReItem::walk( ParseData *pd, RegExpr *rootRegex ) +{ + /* The fsm to return, is the alphabet signed? */ + FsmAp *rtnVal = 0; + + switch ( type ) { + case Data: { + /* Move the data into an integer array and make a concat fsm. */ + Key *arr = new Key[token.length]; + makeFsmKeyArray( arr, token.data, token.length, pd ); + + /* Make the concat fsm. */ + rtnVal = new FsmAp(); + if ( rootRegex != 0 && rootRegex->caseInsensitive ) + rtnVal->concatFsmCI( arr, token.length ); + else + rtnVal->concatFsm( arr, token.length ); + delete[] arr; + break; + } + case Dot: { + /* Make the dot fsm. */ + rtnVal = dotFsm( pd ); + break; + } + case OrBlock: { + /* Get the or block and minmize it. */ + rtnVal = orBlock->walk( pd, rootRegex ); + if ( rtnVal == 0 ) { + rtnVal = new FsmAp(); + rtnVal->lambdaFsm(); + } + rtnVal->minimizePartition2(); + break; + } + case NegOrBlock: { + /* Get the or block and minimize it. */ + FsmAp *fsm = orBlock->walk( pd, rootRegex ); + fsm->minimizePartition2(); + + /* Make a dot fsm and subtract from it. */ + rtnVal = dotFsm( pd ); + rtnVal->subtractOp( fsm ); + rtnVal->minimizePartition2(); + break; + } + } + + /* If the item is followed by a star, then apply the star op. */ + if ( star ) { + if ( rtnVal->startState->isFinState() ) { + warning(loc) << "applying kleene star to a machine that " + "accpets zero length word" << endl; + } + + rtnVal->starOp(); + rtnVal->minimizePartition2(); + } + return rtnVal; +} + +/* Clean up after an or block of a regular expression. */ +ReOrBlock::~ReOrBlock() +{ + switch ( type ) { + case RecurseItem: + delete orBlock; + delete item; + break; + case Empty: + break; + } +} + + +/* Evaluate an or block of a regular expression. */ +FsmAp *ReOrBlock::walk( ParseData *pd, RegExpr *rootRegex ) +{ + FsmAp *rtnVal = 0; + switch ( type ) { + case RecurseItem: { + /* Evaluate the two fsm. */ + FsmAp *fsm1 = orBlock->walk( pd, rootRegex ); + FsmAp *fsm2 = item->walk( pd, rootRegex ); + if ( fsm1 == 0 ) + rtnVal = fsm2; + else { + fsm1->unionOp( fsm2 ); + rtnVal = fsm1; + } + break; + } + case Empty: { + rtnVal = 0; + break; + } + } + return rtnVal;; +} + +/* Evaluate an or block item of a regular expression. */ +FsmAp *ReOrItem::walk( ParseData *pd, RegExpr *rootRegex ) +{ + /* The return value, is the alphabet signed? */ + FsmAp *rtnVal = 0; + switch ( type ) { + case Data: { + /* Make the or machine. */ + rtnVal = new FsmAp(); + + /* Put the or data into an array of ints. Note that we find unique + * keys. Duplicates are silently ignored. The alternative would be to + * issue warning or an error but since we can't with [a0-9a] or 'a' | + * 'a' don't bother here. */ + KeySet keySet; + makeFsmUniqueKeyArray( keySet, token.data, token.length, + rootRegex != 0 ? rootRegex->caseInsensitive : false, pd ); + + /* Run the or operator. */ + rtnVal->orFsm( keySet.data, keySet.length() ); + break; + } + case Range: { + /* Make the upper and lower keys. */ + Key lowKey = makeFsmKeyChar( lower, pd ); + Key highKey = makeFsmKeyChar( upper, pd ); + + /* Validate the range. */ + if ( lowKey > highKey ) { + /* Recover by setting upper to lower; */ + error(loc) << "lower end of range is greater then upper end" << endl; + highKey = lowKey; + } + + /* Make the range machine. */ + rtnVal = new FsmAp(); + rtnVal->rangeFsm( lowKey, highKey ); + + if ( rootRegex != 0 && rootRegex->caseInsensitive ) { + if ( lowKey <= 'Z' && 'A' <= highKey ) { + Key otherLow = lowKey < 'A' ? Key('A') : lowKey; + Key otherHigh = 'Z' < highKey ? Key('Z') : highKey; + + otherLow = 'a' + ( otherLow - 'A' ); + otherHigh = 'a' + ( otherHigh - 'A' ); + + FsmAp *otherRange = new FsmAp(); + otherRange->rangeFsm( otherLow, otherHigh ); + rtnVal->unionOp( otherRange ); + rtnVal->minimizePartition2(); + } + else if ( lowKey <= 'z' && 'a' <= highKey ) { + Key otherLow = lowKey < 'a' ? Key('a') : lowKey; + Key otherHigh = 'z' < highKey ? Key('z') : highKey; + + otherLow = 'A' + ( otherLow - 'a' ); + otherHigh = 'A' + ( otherHigh - 'a' ); + + FsmAp *otherRange = new FsmAp(); + otherRange->rangeFsm( otherLow, otherHigh ); + rtnVal->unionOp( otherRange ); + rtnVal->minimizePartition2(); + } + } + + break; + }} + return rtnVal; +} diff --git a/contrib/tools/ragel5/ragel/parsetree.h b/contrib/tools/ragel5/ragel/parsetree.h new file mode 100644 index 00000000000..4f398683a97 --- /dev/null +++ b/contrib/tools/ragel5/ragel/parsetree.h @@ -0,0 +1,755 @@ +/* + * Copyright 2001-2006 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PARSETREE_H +#define _PARSETREE_H + +#include "ragel.h" +#include "avlmap.h" +#include "bstmap.h" +#include "vector.h" +#include "dlist.h" + +struct NameInst; + +/* Types of builtin machines. */ +enum BuiltinMachine +{ + BT_Any, + BT_Ascii, + BT_Extend, + BT_Alpha, + BT_Digit, + BT_Alnum, + BT_Lower, + BT_Upper, + BT_Cntrl, + BT_Graph, + BT_Print, + BT_Punct, + BT_Space, + BT_Xdigit, + BT_Lambda, + BT_Empty +}; + + +struct ParseData; + +/* Leaf type. */ +struct Literal; + +/* Tree nodes. */ + +struct Term; +struct FactorWithAug; +struct FactorWithRep; +struct FactorWithNeg; +struct Factor; +struct Expression; +struct Join; +struct JoinOrLm; +struct LongestMatch; +struct LongestMatchPart; +struct LmPartList; +struct Range; + +/* Type of augmentation. Describes locations in the machine. */ +enum AugType +{ + /* Transition actions/priorities. */ + at_start, + at_all, + at_finish, + at_leave, + + /* Global error actions. */ + at_start_gbl_error, + at_all_gbl_error, + at_final_gbl_error, + at_not_start_gbl_error, + at_not_final_gbl_error, + at_middle_gbl_error, + + /* Local error actions. */ + at_start_local_error, + at_all_local_error, + at_final_local_error, + at_not_start_local_error, + at_not_final_local_error, + at_middle_local_error, + + /* To State Action embedding. */ + at_start_to_state, + at_all_to_state, + at_final_to_state, + at_not_start_to_state, + at_not_final_to_state, + at_middle_to_state, + + /* From State Action embedding. */ + at_start_from_state, + at_all_from_state, + at_final_from_state, + at_not_start_from_state, + at_not_final_from_state, + at_middle_from_state, + + /* EOF Action embedding. */ + at_start_eof, + at_all_eof, + at_final_eof, + at_not_start_eof, + at_not_final_eof, + at_middle_eof +}; + +/* IMPORTANT: These must follow the same order as the state augs in AugType + * since we will be using this to compose AugType. */ +enum StateAugType +{ + sat_start = 0, + sat_all, + sat_final, + sat_not_start, + sat_not_final, + sat_middle +}; + +struct Action; +struct PriorDesc; +struct RegExpr; +struct ReItem; +struct ReOrBlock; +struct ReOrItem; +struct ExplicitMachine; +struct InlineItem; +struct InlineList; + +/* Reference to a named state. */ +typedef Vector<char*> NameRef; +typedef Vector<NameRef*> NameRefList; +typedef Vector<NameInst*> NameTargList; + +/* Structure for storing location of epsilon transitons. */ +struct EpsilonLink +{ + EpsilonLink( const InputLoc &loc, NameRef &target ) + : loc(loc), target(target) { } + + InputLoc loc; + NameRef target; +}; + +struct Label +{ + Label( const InputLoc &loc, char *data ) + : loc(loc), data(data) { } + + InputLoc loc; + char *data; +}; + +/* Structrue represents an action assigned to some FactorWithAug node. The + * factor with aug will keep an array of these. */ +struct ParserAction +{ + ParserAction( const InputLoc &loc, AugType type, int localErrKey, Action *action ) + : loc(loc), type(type), localErrKey(localErrKey), action(action) { } + + InputLoc loc; + AugType type; + int localErrKey; + Action *action; +}; + +struct Token +{ + char *data; + int length; + InputLoc loc; + + void prepareLitString( Token &result, bool &caseInsensitive ); + void append( const Token &other ); + void set(const char *str, int len ); +}; + +/* Store the value and type of a priority augmentation. */ +struct PriorityAug +{ + PriorityAug( AugType type, int priorKey, int priorValue ) : + type(type), priorKey(priorKey), priorValue(priorValue) { } + + AugType type; + int priorKey; + int priorValue; +}; + +/* + * A Variable Definition + */ +struct VarDef +{ + VarDef(const char *name, JoinOrLm *joinOrLm ) + : name(name), joinOrLm(joinOrLm), isExport(false) { } + + /* Parse tree traversal. */ + FsmAp *walk( ParseData *pd ); + void makeNameTree( const InputLoc &loc, ParseData *pd ); + void resolveNameRefs( ParseData *pd ); + + const char *name; + JoinOrLm *joinOrLm; + bool isExport; +}; + + +/* + * LongestMatch + * + * Wherever possible the item match will execute on the character. If not + * possible the item match will execute on a lookahead character and either + * hold the current char (if one away) or backup. + * + * How to handle the problem of backing up over a buffer break? + * + * Don't want to use pending out transitions for embedding item match because + * the role of item match action is different: it may sometimes match on the + * final transition, or may match on a lookahead character. + * + * Don't want to invent a new operator just for this. So just trail action + * after machine, this means we can only use literal actions. + * + * The item action may + * + * What states of the machine will be final. The item actions that wrap around + * on the last character will go straight to the start state. + * + * Some transitions will be lookahead transitions, they will hold the current + * character. Crossing them with regular transitions must be restricted + * because it does not make sense. The transition cannot simultaneously hold + * and consume the current character. + */ +struct LongestMatchPart +{ + LongestMatchPart( Join *join, Action *action, + InputLoc &semiLoc, int longestMatchId ) + : + join(join), action(action), semiLoc(semiLoc), + longestMatchId(longestMatchId), inLmSelect(false) { } + + InputLoc getLoc(); + + Join *join; + Action *action; + InputLoc semiLoc; + + Action *setActId; + Action *actOnLast; + Action *actOnNext; + Action *actLagBehind; + int longestMatchId; + bool inLmSelect; + LongestMatch *longestMatch; + + LongestMatchPart *prev, *next; +}; + +/* Declare a new type so that ptreetypes.h need not include dlist.h. */ +struct LmPartList : DList<LongestMatchPart> {}; + +struct LongestMatch +{ + /* Construct with a list of joins */ + LongestMatch( const InputLoc &loc, LmPartList *longestMatchList ) : + loc(loc), longestMatchList(longestMatchList), name(0), + lmSwitchHandlesError(false) { } + + /* Tree traversal. */ + FsmAp *walk( ParseData *pd ); + void makeNameTree( ParseData *pd ); + void resolveNameRefs( ParseData *pd ); + void runLonestMatch( ParseData *pd, FsmAp *graph ); + Action *newAction( ParseData *pd, const InputLoc &loc, const char *name, + InlineList *inlineList ); + void makeActions( ParseData *pd ); + void findName( ParseData *pd ); + void restart( FsmAp *graph, TransAp *trans ); + + InputLoc loc; + LmPartList *longestMatchList; + const char *name; + + Action *lmActSelect; + bool lmSwitchHandlesError; + + LongestMatch *next, *prev; +}; + + +/* List of Expressions. */ +typedef DList<Expression> ExprList; + +struct JoinOrLm +{ + enum Type { + JoinType, + LongestMatchType + }; + + JoinOrLm( Join *join ) : + join(join), type(JoinType) {} + JoinOrLm( LongestMatch *longestMatch ) : + longestMatch(longestMatch), type(LongestMatchType) {} + + FsmAp *walk( ParseData *pd ); + void makeNameTree( ParseData *pd ); + void resolveNameRefs( ParseData *pd ); + + Join *join; + LongestMatch *longestMatch; + Type type; +}; + +/* + * Join + */ +struct Join +{ + /* Construct with the first expression. */ + Join( Expression *expr ); + Join( const InputLoc &loc, Expression *expr ); + + /* Tree traversal. */ + FsmAp *walk( ParseData *pd ); + FsmAp *walkJoin( ParseData *pd ); + void makeNameTree( ParseData *pd ); + void resolveNameRefs( ParseData *pd ); + + /* Data. */ + InputLoc loc; + ExprList exprList; +}; + +/* + * Expression + */ +struct Expression +{ + enum Type { + OrType, + IntersectType, + SubtractType, + StrongSubtractType, + TermType, + BuiltinType + }; + + /* Construct with an expression on the left and a term on the right. */ + Expression( Expression *expression, Term *term, Type type ) : + expression(expression), term(term), + builtin(builtin), type(type), prev(this), next(this) { } + + /* Construct with only a term. */ + Expression( Term *term ) : + expression(0), term(term), builtin(builtin), + type(TermType) , prev(this), next(this) { } + + /* Construct with a builtin type. */ + Expression( BuiltinMachine builtin ) : + expression(0), term(0), builtin(builtin), + type(BuiltinType), prev(this), next(this) { } + + ~Expression(); + + /* Tree traversal. */ + FsmAp *walk( ParseData *pd, bool lastInSeq = true ); + void makeNameTree( ParseData *pd ); + void resolveNameRefs( ParseData *pd ); + + /* Node data. */ + Expression *expression; + Term *term; + BuiltinMachine builtin; + Type type; + + Expression *prev, *next; +}; + +/* + * Term + */ +struct Term +{ + enum Type { + ConcatType, + RightStartType, + RightFinishType, + LeftType, + FactorWithAugType + }; + + Term( Term *term, FactorWithAug *factorWithAug ) : + term(term), factorWithAug(factorWithAug), type(ConcatType) { } + + Term( Term *term, FactorWithAug *factorWithAug, Type type ) : + term(term), factorWithAug(factorWithAug), type(type) { } + + Term( FactorWithAug *factorWithAug ) : + term(0), factorWithAug(factorWithAug), type(FactorWithAugType) { } + + ~Term(); + + FsmAp *walk( ParseData *pd, bool lastInSeq = true ); + void makeNameTree( ParseData *pd ); + void resolveNameRefs( ParseData *pd ); + + Term *term; + FactorWithAug *factorWithAug; + Type type; + + /* Priority descriptor for RightFinish type. */ + PriorDesc priorDescs[2]; +}; + + +/* Third level of precedence. Augmenting nodes with actions and priorities. */ +struct FactorWithAug +{ + FactorWithAug( FactorWithRep *factorWithRep ) : + priorDescs(0), factorWithRep(factorWithRep) { } + ~FactorWithAug(); + + /* Tree traversal. */ + FsmAp *walk( ParseData *pd ); + void makeNameTree( ParseData *pd ); + void resolveNameRefs( ParseData *pd ); + + void assignActions( ParseData *pd, FsmAp *graph, int *actionOrd ); + void assignPriorities( FsmAp *graph, int *priorOrd ); + + void assignConditions( FsmAp *graph ); + + /* Actions and priorities assigned to the factor node. */ + Vector<ParserAction> actions; + Vector<PriorityAug> priorityAugs; + PriorDesc *priorDescs; + Vector<Label> labels; + Vector<EpsilonLink> epsilonLinks; + Vector<ParserAction> conditions; + + FactorWithRep *factorWithRep; +}; + +/* Fourth level of precedence. Trailing unary operators. Provide kleen star, + * optional and plus. */ +struct FactorWithRep +{ + enum Type { + StarType, + StarStarType, + OptionalType, + PlusType, + ExactType, + MaxType, + MinType, + RangeType, + FactorWithNegType + }; + + FactorWithRep( const InputLoc &loc, FactorWithRep *factorWithRep, + int lowerRep, int upperRep, Type type ) : + loc(loc), factorWithRep(factorWithRep), + factorWithNeg(0), lowerRep(lowerRep), + upperRep(upperRep), type(type) { } + + FactorWithRep( FactorWithNeg *factorWithNeg ) + : factorWithNeg(factorWithNeg), type(FactorWithNegType) { } + + ~FactorWithRep(); + + /* Tree traversal. */ + FsmAp *walk( ParseData *pd ); + void makeNameTree( ParseData *pd ); + void resolveNameRefs( ParseData *pd ); + + InputLoc loc; + FactorWithRep *factorWithRep; + FactorWithNeg *factorWithNeg; + int lowerRep, upperRep; + Type type; + + /* Priority descriptor for StarStar type. */ + PriorDesc priorDescs[2]; +}; + +/* Fifth level of precedence. Provides Negation. */ +struct FactorWithNeg +{ + enum Type { + NegateType, + CharNegateType, + FactorType + }; + + FactorWithNeg( const InputLoc &loc, FactorWithNeg *factorWithNeg, Type type) : + loc(loc), factorWithNeg(factorWithNeg), factor(0), type(type) { } + + FactorWithNeg( Factor *factor ) : + factorWithNeg(0), factor(factor), type(FactorType) { } + + ~FactorWithNeg(); + + /* Tree traversal. */ + FsmAp *walk( ParseData *pd ); + void makeNameTree( ParseData *pd ); + void resolveNameRefs( ParseData *pd ); + + InputLoc loc; + FactorWithNeg *factorWithNeg; + Factor *factor; + Type type; +}; + +/* + * Factor + */ +struct Factor +{ + /* Language elements a factor node can be. */ + enum Type { + LiteralType, + RangeType, + OrExprType, + RegExprType, + ReferenceType, + ParenType, + LongestMatchType, + }; + + /* Construct with a literal fsm. */ + Factor( Literal *literal ) : + literal(literal), type(LiteralType) { } + + /* Construct with a range. */ + Factor( Range *range ) : + range(range), type(RangeType) { } + + /* Construct with the or part of a regular expression. */ + Factor( ReItem *reItem ) : + reItem(reItem), type(OrExprType) { } + + /* Construct with a regular expression. */ + Factor( RegExpr *regExpr ) : + regExpr(regExpr), type(RegExprType) { } + + /* Construct with a reference to a var def. */ + Factor( const InputLoc &loc, VarDef *varDef ) : + loc(loc), varDef(varDef), type(ReferenceType) {} + + /* Construct with a parenthesized join. */ + Factor( Join *join ) : + join(join), type(ParenType) {} + + /* Construct with a longest match operator. */ + Factor( LongestMatch *longestMatch ) : + longestMatch(longestMatch), type(LongestMatchType) {} + + /* Cleanup. */ + ~Factor(); + + /* Tree traversal. */ + FsmAp *walk( ParseData *pd ); + void makeNameTree( ParseData *pd ); + void resolveNameRefs( ParseData *pd ); + + InputLoc loc; + Literal *literal; + Range *range; + ReItem *reItem; + RegExpr *regExpr; + VarDef *varDef; + Join *join; + LongestMatch *longestMatch; + int lower, upper; + Type type; +}; + +/* A range machine. Only ever composed of two literals. */ +struct Range +{ + Range( Literal *lowerLit, Literal *upperLit ) + : lowerLit(lowerLit), upperLit(upperLit) { } + + ~Range(); + FsmAp *walk( ParseData *pd ); + + Literal *lowerLit; + Literal *upperLit; +}; + +/* Some literal machine. Can be a number or literal string. */ +struct Literal +{ + enum LiteralType { Number, LitString }; + + Literal( const Token &token, LiteralType type ) + : token(token), type(type) { } + + FsmAp *walk( ParseData *pd ); + + Token token; + LiteralType type; +}; + +/* Regular expression. */ +struct RegExpr +{ + enum RegExpType { RecurseItem, Empty }; + + /* Constructors. */ + RegExpr() : + type(Empty), caseInsensitive(false) { } + RegExpr(RegExpr *regExpr, ReItem *item) : + regExpr(regExpr), item(item), + type(RecurseItem), caseInsensitive(false) { } + + ~RegExpr(); + FsmAp *walk( ParseData *pd, RegExpr *rootRegex ); + + RegExpr *regExpr; + ReItem *item; + RegExpType type; + bool caseInsensitive; +}; + +/* An item in a regular expression. */ +struct ReItem +{ + enum ReItemType { Data, Dot, OrBlock, NegOrBlock }; + + ReItem( const InputLoc &loc, const Token &token ) + : loc(loc), token(token), star(false), type(Data) { } + ReItem( const InputLoc &loc, ReItemType type ) + : loc(loc), star(false), type(type) { } + ReItem( const InputLoc &loc, ReOrBlock *orBlock, ReItemType type ) + : loc(loc), orBlock(orBlock), star(false), type(type) { } + + ~ReItem(); + FsmAp *walk( ParseData *pd, RegExpr *rootRegex ); + + InputLoc loc; + Token token; + ReOrBlock *orBlock; + bool star; + ReItemType type; +}; + +/* An or block item. */ +struct ReOrBlock +{ + enum ReOrBlockType { RecurseItem, Empty }; + + /* Constructors. */ + ReOrBlock() + : type(Empty) { } + ReOrBlock(ReOrBlock *orBlock, ReOrItem *item) + : orBlock(orBlock), item(item), type(RecurseItem) { } + + ~ReOrBlock(); + FsmAp *walk( ParseData *pd, RegExpr *rootRegex ); + + ReOrBlock *orBlock; + ReOrItem *item; + ReOrBlockType type; +}; + +/* An item in an or block. */ +struct ReOrItem +{ + enum ReOrItemType { Data, Range }; + + ReOrItem( const InputLoc &loc, const Token &token ) + : loc(loc), token(token), type(Data) {} + ReOrItem( const InputLoc &loc, char lower, char upper ) + : loc(loc), lower(lower), upper(upper), type(Range) { } + + FsmAp *walk( ParseData *pd, RegExpr *rootRegex ); + + InputLoc loc; + Token token; + char lower; + char upper; + ReOrItemType type; +}; + + +/* + * Inline code tree + */ +struct InlineList; +struct InlineItem +{ + enum Type + { + Text, Goto, Call, Next, GotoExpr, CallExpr, NextExpr, Ret, PChar, + Char, Hold, Curs, Targs, Entry, Exec, LmSwitch, LmSetActId, + LmSetTokEnd, LmOnLast, LmOnNext, LmOnLagBehind, LmInitAct, + LmInitTokStart, LmSetTokStart, Break + }; + + InlineItem( const InputLoc &loc, char *data, Type type ) : + loc(loc), data(data), nameRef(0), children(0), type(type) { } + + InlineItem( const InputLoc &loc, NameRef *nameRef, Type type ) : + loc(loc), data(0), nameRef(nameRef), children(0), type(type) { } + + InlineItem( const InputLoc &loc, LongestMatch *longestMatch, + LongestMatchPart *longestMatchPart, Type type ) : loc(loc), data(0), + nameRef(0), children(0), longestMatch(longestMatch), + longestMatchPart(longestMatchPart), type(type) { } + + InlineItem( const InputLoc &loc, NameInst *nameTarg, Type type ) : + loc(loc), data(0), nameRef(0), nameTarg(nameTarg), children(0), + type(type) { } + + InlineItem( const InputLoc &loc, Type type ) : + loc(loc), data(0), nameRef(0), children(0), type(type) { } + + InputLoc loc; + char *data; + NameRef *nameRef; + NameInst *nameTarg; + InlineList *children; + LongestMatch *longestMatch; + LongestMatchPart *longestMatchPart; + Type type; + + InlineItem *prev, *next; +}; + +/* Normally this would be atypedef, but that would entail including DList from + * ptreetypes, which should be just typedef forwards. */ +struct InlineList : public DList<InlineItem> { }; + + + +#endif /* _PARSETREE_H */ diff --git a/contrib/tools/ragel5/ragel/ragel.h b/contrib/tools/ragel5/ragel/ragel.h new file mode 100644 index 00000000000..736369c0ce3 --- /dev/null +++ b/contrib/tools/ragel5/ragel/ragel.h @@ -0,0 +1,74 @@ +/* + * Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _RAGEL_H +#define _RAGEL_H + +#include <stdio.h> +#include <iostream> +#include <fstream> +#include <string> +#include "config.h" + +#define PROGNAME "ragel" + +/* To what degree are machine minimized. */ +enum MinimizeLevel { + MinimizeApprox, + MinimizeStable, + MinimizePartition1, + MinimizePartition2 +}; + +enum MinimizeOpt { + MinimizeNone, + MinimizeEnd, + MinimizeMostOps, + MinimizeEveryOp +}; + +/* Options. */ +extern MinimizeLevel minimizeLevel; +extern MinimizeOpt minimizeOpt; +extern char *machineSpec, *machineName; +extern bool printStatistics; + +extern int gblErrorCount; +extern char mainMachine[]; + +/* Location in an input file. */ +struct InputLoc +{ + const char *fileName; + int line; + int col; +}; + +/* Error reporting. */ +std::ostream &error(); +std::ostream &error( const InputLoc &loc ); +std::ostream &warning( const InputLoc &loc ); + +void terminateAllParsers( ); +void writeMachines( std::ostream &out, std::string hostData, const char *inputFileName ); +void xmlEscapeHost( std::ostream &out, char *data, int len ); + +#endif /* _RAGEL_H */ diff --git a/contrib/tools/ragel5/ragel/rlparse.cpp b/contrib/tools/ragel5/ragel/rlparse.cpp new file mode 100644 index 00000000000..cd6fbde218a --- /dev/null +++ b/contrib/tools/ragel5/ragel/rlparse.cpp @@ -0,0 +1,6088 @@ +/* Automatically generated by Kelbt from "rlparse.kl". + * + * Parts of this file are copied from Kelbt source covered by the GNU + * GPL. As a special exception, you may use the parts of this file copied + * from Kelbt source without restriction. The remainder is derived from + * "rlparse.kl" and inherits the copyright status of that file. + */ + +#line 1 "rlparse.kl" +/* + * Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "rlparse.h" +#include "ragel.h" +#include <iostream> +#include <errno.h> + +#include <stdlib.h> +//#include <malloc.h> + +using std::cout; +using std::cerr; +using std::endl; + +ParserDict parserDict; + +#line 93 "rlparse.kh" +#line 96 "rlparse.kh" +#line 126 "rlparse.kh" +#line 1370 "rlparse.kl" + + +#line 50 "rlparse.cpp" +struct Parser_Lel_action_ref +{ +#line 682 "rlparse.kl" + + Action *action; + + +#line 57 "rlparse.cpp" +}; + +struct Parser_Lel_aug_type +{ +#line 475 "rlparse.kl" + + InputLoc loc; + AugType augType; + + +#line 68 "rlparse.cpp" +}; + +struct Parser_Lel_expression +{ +#line 297 "rlparse.kl" + + Expression *expression; + + +#line 78 "rlparse.cpp" +}; + +struct Parser_Lel_factor +{ +#line 907 "rlparse.kl" + + Factor *factor; + + +#line 88 "rlparse.cpp" +}; + +struct Parser_Lel_factor_rep_num +{ +#line 861 "rlparse.kl" + + int rep; + + +#line 98 "rlparse.cpp" +}; + +struct Parser_Lel_factor_with_aug +{ +#line 392 "rlparse.kl" + + FactorWithAug *factorWithAug; + + +#line 108 "rlparse.cpp" +}; + +struct Parser_Lel_factor_with_ep +{ +#line 376 "rlparse.kl" + + FactorWithAug *factorWithAug; + + +#line 118 "rlparse.cpp" +}; + +struct Parser_Lel_factor_with_label +{ +#line 360 "rlparse.kl" + + FactorWithAug *factorWithAug; + + +#line 128 "rlparse.cpp" +}; + +struct Parser_Lel_factor_with_neg +{ +#line 887 "rlparse.kl" + + FactorWithNeg *factorWithNeg; + + +#line 138 "rlparse.cpp" +}; + +struct Parser_Lel_factor_with_rep +{ +#line 811 "rlparse.kl" + + FactorWithRep *factorWithRep; + + +#line 148 "rlparse.cpp" +}; + +struct Parser_Lel_inline_item +{ +#line 1160 "rlparse.kl" + + InlineItem *inlineItem; + + +#line 158 "rlparse.cpp" +}; + +struct Parser_Lel_inline_list +{ +#line 1139 "rlparse.kl" + + InlineList *inlineList; + + +#line 168 "rlparse.cpp" +}; + +struct Parser_Lel_join +{ +#line 281 "rlparse.kl" + + Join *join; + + +#line 178 "rlparse.cpp" +}; + +struct Parser_Lel_join_or_lm +{ +#line 204 "rlparse.kl" + + JoinOrLm *joinOrLm; + + +#line 188 "rlparse.cpp" +}; + +struct Parser_Lel_lm_part_list +{ +#line 224 "rlparse.kl" + + LmPartList *lmPartList; + + +#line 198 "rlparse.cpp" +}; + +struct Parser_Lel_local_err_name +{ +#line 790 "rlparse.kl" + + int error_name; + + +#line 208 "rlparse.cpp" +}; + +struct Parser_Lel_longest_match_part +{ +#line 243 "rlparse.kl" + + LongestMatchPart *lmPart; + + +#line 218 "rlparse.cpp" +}; + +struct Parser_Lel_opt_export +{ +#line 64 "rlparse.kl" + + bool isSet; + + +#line 228 "rlparse.cpp" +}; + +struct Parser_Lel_opt_lm_part_action +{ +#line 262 "rlparse.kl" + + Action *action; + + +#line 238 "rlparse.cpp" +}; + +struct Parser_Lel_priority_aug +{ +#line 741 "rlparse.kl" + + int priorityNum; + + +#line 248 "rlparse.cpp" +}; + +struct Parser_Lel_priority_name +{ +#line 723 "rlparse.kl" + + int priorityName; + + +#line 258 "rlparse.cpp" +}; + +struct Parser_Lel_range_lit +{ +#line 975 "rlparse.kl" + + Literal *literal; + + +#line 268 "rlparse.cpp" +}; + +struct Parser_Lel_regular_expr +{ +#line 1013 "rlparse.kl" + + RegExpr *regExpr; + + +#line 278 "rlparse.cpp" +}; + +struct Parser_Lel_regular_expr_char +{ +#line 1062 "rlparse.kl" + + ReItem *reItem; + + +#line 288 "rlparse.cpp" +}; + +struct Parser_Lel_regular_expr_item +{ +#line 1046 "rlparse.kl" + + ReItem *reItem; + + +#line 298 "rlparse.cpp" +}; + +struct Parser_Lel_regular_expr_or_char +{ +#line 1121 "rlparse.kl" + + ReOrItem *reOrItem; + + +#line 308 "rlparse.cpp" +}; + +struct Parser_Lel_regular_expr_or_data +{ +#line 1088 "rlparse.kl" + + ReOrBlock *reOrBlock; + + +#line 318 "rlparse.cpp" +}; + +struct Parser_Lel_term +{ +#line 329 "rlparse.kl" + + Term *term; + + +#line 328 "rlparse.cpp" +}; + +struct Parser_Lel_token_type +{ +#line 104 "rlparse.kl" + + Token token; + + +#line 338 "rlparse.cpp" +}; + +union Parser_UserData +{ + struct Parser_Lel_action_ref action_ref; + struct Parser_Lel_aug_type aug_type; + struct Parser_Lel_expression expression; + struct Parser_Lel_factor factor; + struct Parser_Lel_factor_rep_num factor_rep_num; + struct Parser_Lel_factor_with_aug factor_with_aug; + struct Parser_Lel_factor_with_ep factor_with_ep; + struct Parser_Lel_factor_with_label factor_with_label; + struct Parser_Lel_factor_with_neg factor_with_neg; + struct Parser_Lel_factor_with_rep factor_with_rep; + struct Parser_Lel_inline_item inline_item; + struct Parser_Lel_inline_list inline_list; + struct Parser_Lel_join join; + struct Parser_Lel_join_or_lm join_or_lm; + struct Parser_Lel_lm_part_list lm_part_list; + struct Parser_Lel_local_err_name local_err_name; + struct Parser_Lel_longest_match_part longest_match_part; + struct Parser_Lel_opt_export opt_export; + struct Parser_Lel_opt_lm_part_action opt_lm_part_action; + struct Parser_Lel_priority_aug priority_aug; + struct Parser_Lel_priority_name priority_name; + struct Parser_Lel_range_lit range_lit; + struct Parser_Lel_regular_expr regular_expr; + struct Parser_Lel_regular_expr_char regular_expr_char; + struct Parser_Lel_regular_expr_item regular_expr_item; + struct Parser_Lel_regular_expr_or_char regular_expr_or_char; + struct Parser_Lel_regular_expr_or_data regular_expr_or_data; + struct Parser_Lel_term term; + struct Parser_Lel_token_type token_type; + struct Token token; +}; + +struct Parser_LangEl +{ + char *file; + int line; + int type; + int reduction; + int state; + union Parser_UserData user; + unsigned int retry; + struct Parser_LangEl *next, *child; +}; + +#line 388 "rlparse.cpp" +unsigned int Parser_startState = 0; + +short Parser_indicies[] = { + 151, -1, -1, -1, -1, -1, 151, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 151, 151, 151, 151, -1, -1, + -1, -1, -1, -1, 151, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 151, 151, -1, 151, 1, 0, 393, + 153, -1, -1, -1, -1, -1, 153, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 153, 153, 153, 153, -1, -1, + -1, -1, -1, -1, 153, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 153, 153, -1, 149, -1, -1, 2, + 157, -1, -1, -1, -1, -1, 150, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 4, 5, 6, 7, -1, -1, + -1, -1, -1, -1, 154, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 9, 8, -1, -1, -1, -1, -1, + 152, 384, 385, 386, 387, 388, 389, 390, + 391, 392, 10, 3, 161, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 24, 11, 12, 14, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 318, 320, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 13, 356, 356, 356, -1, 356, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 356, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 356, + -1, -1, -1, -1, -1, -1, 356, 356, + -1, -1, -1, -1, -1, -1, -1, -1, + 356, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 356, 356, 356, + 356, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 356, + 356, -1, -1, -1, 356, 356, 356, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 20, 356, 356, 356, -1, 356, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 356, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 356, -1, -1, + -1, -1, -1, -1, 356, 356, -1, -1, + -1, -1, -1, -1, -1, -1, 356, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 356, 356, 356, 356, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 356, 356, -1, + -1, -1, 356, 356, 356, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 22, 170, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 170, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 21, 23, -1, -1, -1, -1, -1, + -1, -1, -1, 155, 25, 164, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 26, 14, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 318, 320, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 27, 319, + 368, 369, 370, -1, 367, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 166, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 366, -1, -1, -1, + -1, -1, -1, 364, 365, -1, -1, -1, + -1, -1, -1, -1, -1, 371, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 360, 361, 362, 363, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 372, 373, -1, -1, + -1, 374, 375, 28, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 357, -1, 359, -1, 355, 358, + 29, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 169, 368, + 369, 370, -1, 367, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 167, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 366, -1, -1, -1, -1, + -1, -1, 364, 365, -1, -1, -1, -1, + -1, -1, -1, -1, 371, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 372, 373, -1, -1, -1, + 374, 375, 28, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 357, -1, 359, -1, 355, 358, 153, + -1, -1, -1, -1, -1, -1, 153, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 153, 153, 153, 153, -1, -1, -1, -1, + -1, -1, 153, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 153, + 153, -1, -1, -1, -1, 30, 31, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 32, 334, 334, 334, -1, 334, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 334, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 334, -1, -1, -1, -1, -1, -1, 334, + -1, -1, -1, -1, -1, -1, 334, 334, + -1, -1, -1, -1, -1, -1, -1, -1, + 334, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 334, 334, 334, + 334, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 33, 163, + 165, 34, 356, 356, 356, -1, 356, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 356, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 356, -1, + -1, -1, -1, -1, -1, 356, 356, -1, + -1, -1, -1, -1, -1, -1, -1, 356, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 356, 356, 356, 356, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 356, 356, + -1, -1, -1, 356, 356, 356, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 35, + 158, -1, -1, -1, -1, -1, -1, 157, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 4, 5, 6, 7, -1, -1, -1, + -1, -1, -1, 154, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 9, 8, -1, -1, -1, -1, -1, 152, + 384, 385, 386, 387, 388, 389, 390, 391, + 392, 10, 3, 44, -1, -1, -1, -1, + -1, -1, 52, -1, -1, -1, -1, 14, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 45, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 39, 46, + -1, -1, -1, -1, -1, 318, 320, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 50, 48, 49, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 36, -1, -1, 47, -1, + -1, -1, -1, -1, -1, -1, 37, 38, + 193, 41, -1, 42, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 43, -1, + -1, -1, 300, 304, -1, -1, 51, 44, + -1, -1, -1, -1, -1, -1, 52, -1, + -1, -1, -1, 14, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 45, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 39, 46, -1, -1, -1, -1, + -1, 318, 320, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 55, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 50, 48, 49, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 54, + 53, -1, 47, -1, -1, -1, -1, -1, + -1, -1, 37, 38, 193, 41, -1, 42, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 43, -1, -1, -1, 300, 304, + -1, -1, 51, 340, 341, 342, -1, 338, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 339, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 162, -1, -1, -1, -1, -1, -1, 366, + -1, -1, -1, -1, -1, -1, 364, 365, + -1, -1, -1, -1, -1, -1, -1, -1, + 343, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 62, 57, 56, 372, + 373, 58, 60, 61, 374, 375, 28, 59, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 333, 337, 335, 336, 344, + 381, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 380, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 63, -1, -1, -1, -1, 64, 368, + 369, 370, -1, 367, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 168, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 366, -1, -1, -1, -1, + -1, -1, 364, 365, -1, -1, -1, -1, + -1, -1, -1, -1, 371, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 372, 373, -1, -1, -1, + 374, 375, 28, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 357, -1, 359, -1, 355, 358, 70, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 159, 72, + -1, -1, 182, -1, -1, 182, 73, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 182, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 182, 71, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 182, -1, -1, -1, + 74, 44, -1, -1, -1, -1, 187, -1, + 52, 187, -1, -1, 187, 19, 75, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 187, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 45, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 187, 187, -1, -1, -1, + -1, -1, -1, -1, 39, 46, -1, -1, + -1, -1, -1, 318, 320, -1, -1, 76, + 77, 78, -1, 187, -1, -1, -1, 187, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 50, 48, 49, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 188, 41, + -1, 42, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, + 300, 304, -1, -1, 51, 307, -1, -1, + 307, 307, 307, -1, 307, 307, 307, 307, + 307, 307, 307, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 66, 307, + 307, -1, 307, 307, 307, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 307, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 307, + 307, -1, -1, -1, -1, -1, -1, -1, + 307, 307, -1, -1, -1, -1, -1, 307, + 307, -1, -1, 307, 307, 307, 307, 307, + 307, -1, -1, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 307, 195, + -1, -1, -1, -1, 195, -1, 195, 195, + -1, -1, 195, 195, 195, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 195, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 195, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 195, 195, -1, -1, -1, -1, -1, + -1, -1, 195, 195, -1, -1, -1, -1, + -1, 195, 195, -1, -1, 195, 195, 195, + 79, 195, -1, -1, -1, 195, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 195, 195, 195, 197, -1, -1, 89, 88, + 197, -1, 197, 197, -1, -1, 197, 197, + 197, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 197, 91, -1, + 90, -1, 87, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 197, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 197, 197, -1, + -1, -1, -1, -1, -1, -1, 197, 197, + -1, -1, -1, -1, -1, 197, 197, -1, + -1, 197, 197, 197, 197, 197, -1, -1, + -1, 197, 213, 215, 217, 92, 256, 260, + 262, 264, 258, 266, 268, 272, 274, 276, + 270, 278, 244, 248, 250, 252, 246, 254, + 220, 224, 226, 228, 222, 230, 232, 236, + 238, 240, 234, 242, 197, 197, 197, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 219, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 80, -1, -1, 81, + 82, 83, 84, 85, 86, 208, -1, -1, + 208, 208, 208, -1, 208, 208, 292, 295, + 208, 208, 208, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 208, + 208, -1, 208, 294, 208, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 208, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 93, + 208, -1, -1, -1, -1, -1, -1, -1, + 208, 208, -1, -1, -1, -1, -1, 208, + 208, -1, -1, 208, 208, 208, 208, 208, + 293, -1, -1, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, + 208, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 208, 44, + -1, -1, -1, -1, -1, -1, 52, -1, + -1, -1, -1, 14, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 45, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 308, 46, -1, -1, -1, -1, + -1, 318, 320, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 50, 48, 49, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 47, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 302, 304, + -1, -1, 51, 44, -1, -1, -1, -1, + -1, -1, 52, -1, -1, -1, -1, 14, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 45, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 308, 46, + -1, -1, -1, -1, -1, 318, 320, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 50, 48, 49, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 47, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 303, 304, -1, -1, 51, 305, + -1, -1, 305, 305, 305, -1, 305, 305, + 305, 305, 305, 305, 305, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 305, 305, -1, 305, 305, 305, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 305, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 305, 305, -1, -1, -1, -1, -1, + -1, -1, 305, 305, -1, -1, -1, -1, + -1, 305, 305, -1, 314, 305, 305, 305, + 305, 305, 305, -1, -1, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 305, 306, -1, -1, 306, 306, 306, -1, + 306, 306, 306, 306, 306, 306, 306, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 306, 306, -1, 306, 306, + 306, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 306, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 306, 306, -1, -1, -1, + -1, -1, -1, -1, 306, 306, -1, -1, + -1, -1, -1, 306, 306, -1, 316, 306, + 306, 306, 306, 306, 306, -1, -1, 306, + 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 306, 306, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 306, 330, -1, -1, -1, 330, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 68, 330, -1, -1, -1, 330, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 69, 322, + 322, 322, -1, 322, -1, -1, 322, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 67, 94, 44, -1, -1, -1, -1, -1, + -1, 52, -1, -1, -1, -1, 14, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 45, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 39, 46, -1, + -1, -1, -1, -1, 318, 320, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 50, 48, 49, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 65, -1, -1, 47, -1, -1, + -1, -1, -1, -1, -1, 37, 38, 193, + 41, -1, 42, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 43, -1, -1, + -1, 300, 304, -1, -1, 51, 160, 70, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 171, 44, + -1, -1, -1, -1, -1, -1, 52, -1, + -1, -1, -1, 14, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 45, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 40, 46, -1, -1, -1, -1, + -1, 318, 320, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 50, 48, 49, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 4, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 154, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 176, -1, 175, -1, -1, + -1, -1, -1, -1, 156, 97, -1, 96, + -1, -1, 47, -1, -1, 95, 174, -1, + -1, -1, 37, 38, 193, 41, -1, 42, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 43, -1, -1, -1, 300, 304, + -1, -1, 51, 345, 356, 356, 356, -1, + 356, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 356, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 356, -1, -1, -1, -1, -1, -1, 356, + 356, -1, -1, -1, -1, -1, -1, -1, + -1, 356, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 356, 356, + 356, 356, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 356, 356, -1, -1, -1, 356, 356, 356, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 98, 100, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 381, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 380, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 99, -1, -1, + -1, -1, 64, 104, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 381, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 380, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 103, -1, + -1, -1, -1, 64, 102, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 381, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 380, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 101, + -1, -1, -1, -1, 64, 353, 354, 376, + 383, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 105, 313, -1, + -1, 70, 44, -1, -1, -1, -1, -1, + -1, 52, -1, -1, -1, -1, 14, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 45, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 39, 46, -1, + -1, -1, -1, -1, 318, 320, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 50, 48, 49, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 47, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 194, + 41, -1, 42, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 43, -1, -1, + -1, 300, 304, -1, -1, 51, 311, 107, + 108, -1, 327, -1, -1, 328, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 321, 106, 309, -1, -1, -1, 109, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 329, 310, -1, + -1, -1, 109, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 329, 44, -1, -1, -1, -1, -1, -1, + 52, -1, -1, -1, -1, 14, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 45, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 39, 46, -1, -1, + -1, -1, -1, 318, 320, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 50, 48, 49, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, 110, 38, 193, 41, + -1, 42, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, + 300, 304, -1, -1, 51, 44, -1, -1, + -1, -1, -1, -1, 52, -1, -1, -1, + -1, 14, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 45, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 39, 46, -1, -1, -1, -1, -1, 318, + 320, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 50, 48, + 49, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 47, -1, -1, -1, -1, -1, -1, -1, + -1, 113, 193, 41, -1, 42, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 43, -1, -1, -1, 300, 304, -1, -1, + 51, 44, -1, -1, -1, -1, -1, -1, + 52, -1, -1, -1, -1, 14, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 45, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 39, 46, -1, -1, + -1, -1, -1, 318, 320, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 50, 48, 49, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, -1, 111, 193, 41, + -1, 42, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, + 300, 304, -1, -1, 51, 44, -1, -1, + -1, -1, -1, -1, 52, -1, -1, -1, + -1, 14, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 45, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 39, 46, -1, -1, -1, -1, -1, 318, + 320, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 50, 48, + 49, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 47, -1, -1, -1, -1, -1, -1, -1, + -1, 112, 193, 41, -1, 42, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 43, -1, -1, -1, 300, 304, -1, -1, + 51, 44, -1, -1, -1, -1, -1, -1, + 52, -1, -1, -1, -1, 14, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 45, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 39, 46, -1, -1, + -1, -1, -1, 318, 320, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 50, 48, 49, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, -1, 114, 193, 41, + -1, 42, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, + 300, 304, -1, -1, 51, 44, -1, -1, + -1, -1, -1, -1, 52, -1, -1, -1, + -1, 14, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 45, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 39, 46, -1, -1, -1, -1, -1, 318, + 320, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 50, 48, + 49, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 47, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 189, 41, -1, 42, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 43, -1, -1, -1, 300, 304, -1, -1, + 51, 44, -1, -1, -1, -1, -1, -1, + 52, -1, -1, -1, -1, 14, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 45, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 39, 46, -1, -1, + -1, -1, -1, 318, 320, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 50, 48, 49, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 190, 41, + -1, 42, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, + 300, 304, -1, -1, 51, 44, -1, -1, + -1, -1, -1, -1, 52, -1, -1, -1, + -1, 14, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 45, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 39, 46, -1, -1, -1, -1, -1, 318, + 320, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 50, 48, + 49, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 47, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 191, 41, -1, 42, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 43, -1, -1, -1, 300, 304, -1, -1, + 51, 44, -1, -1, -1, -1, -1, -1, + 52, -1, -1, -1, -1, 14, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 45, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 39, 46, -1, -1, + -1, -1, -1, 318, 320, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 50, 48, 49, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 192, 41, + -1, 42, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, + 300, 304, -1, -1, 51, 378, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 196, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 115, 116, -1, -1, 118, -1, 119, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 117, -1, -1, + -1, -1, -1, -1, -1, -1, 284, -1, + -1, -1, -1, -1, -1, 288, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 198, 282, -1, -1, + -1, -1, -1, -1, -1, 199, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 280, + 287, 120, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 117, -1, -1, -1, + -1, -1, -1, -1, -1, 284, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 201, 282, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 280, 120, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 117, -1, -1, -1, -1, -1, + -1, -1, -1, 284, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 202, 282, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 280, 120, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 117, -1, -1, -1, -1, -1, -1, -1, + -1, 284, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 203, + 282, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 280, 120, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 117, -1, + -1, -1, -1, -1, -1, -1, -1, 284, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 204, 282, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 280, 120, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 117, -1, -1, -1, + -1, -1, -1, -1, -1, 284, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 205, 282, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 280, 121, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 117, -1, -1, -1, -1, -1, + -1, -1, -1, 284, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 206, 282, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 280, 209, -1, -1, + 209, -1, 209, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 209, -1, -1, -1, -1, -1, -1, -1, + -1, 209, -1, -1, -1, -1, -1, -1, + 209, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 253, 265, 277, 229, 241, 210, -1, -1, + 210, -1, 210, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 210, -1, -1, -1, -1, -1, -1, -1, + -1, 210, -1, -1, -1, -1, -1, -1, + 210, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 218, + 251, 263, 275, 227, 239, 211, -1, -1, + 211, -1, 211, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 211, -1, -1, -1, -1, -1, -1, -1, + -1, 211, -1, -1, -1, -1, -1, -1, + 211, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 216, + 249, 261, 273, 225, 237, 212, -1, -1, + 212, -1, 212, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 212, -1, -1, -1, -1, -1, -1, -1, + -1, 212, -1, -1, -1, -1, -1, -1, + 212, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 214, + 245, 257, 269, 221, 233, 247, 259, 271, + 223, 235, 255, 267, 279, 231, 243, 123, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 301, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 122, 14, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 315, -1, -1, -1, -1, + -1, 318, 320, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 317, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 312, 44, -1, -1, -1, -1, + -1, -1, 52, -1, 127, -1, -1, 14, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 45, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 40, 46, + -1, -1, -1, -1, -1, 318, 320, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 50, 48, 49, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 4, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 154, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 176, + -1, 175, -1, -1, -1, -1, -1, -1, + 156, 97, -1, 96, -1, -1, 47, -1, + -1, -1, 173, -1, -1, -1, 37, 38, + 193, 41, -1, 42, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 43, -1, + -1, -1, 300, 304, -1, -1, 51, 70, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 180, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 117, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 126, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 125, -1, 179, 161, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 124, 368, 369, 370, -1, + 367, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 346, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 366, -1, -1, -1, -1, -1, -1, 364, + 365, -1, -1, -1, -1, -1, -1, -1, + -1, 371, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 360, 361, + 362, 363, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 372, 373, -1, -1, -1, 374, 375, 28, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 357, -1, + 359, -1, 355, 358, 347, 356, 356, 356, + -1, 356, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 356, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 356, -1, -1, -1, -1, -1, -1, + 356, 356, -1, -1, -1, -1, -1, -1, + -1, -1, 356, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 356, + 356, 356, 356, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 356, 356, -1, -1, -1, 356, 356, + 356, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 128, 351, 356, 356, 356, -1, + 356, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 356, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 356, -1, -1, -1, -1, -1, -1, 356, + 356, -1, -1, -1, -1, -1, -1, -1, + -1, 356, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 356, 356, + 356, 356, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 356, 356, -1, -1, -1, 356, 356, 356, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 129, 349, 356, 356, 356, -1, 356, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 356, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 356, + -1, -1, -1, -1, -1, -1, 356, 356, + -1, -1, -1, -1, -1, -1, -1, -1, + 356, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 356, 356, 356, + 356, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 356, + 356, -1, -1, -1, 356, 356, 356, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 130, 379, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 379, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 131, 324, 324, + 324, -1, 324, 323, -1, 324, 330, -1, + -1, -1, 330, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 132, 330, -1, -1, -1, + 330, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 133, 331, -1, -1, 134, 331, 72, + -1, -1, 181, -1, -1, 181, 73, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 181, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 181, 71, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 181, -1, -1, -1, + 74, 44, -1, -1, -1, -1, 184, -1, + 52, 184, -1, -1, 184, 16, 75, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 184, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 45, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 184, 184, -1, -1, -1, + -1, -1, -1, -1, 39, 46, -1, -1, + -1, -1, -1, 318, 320, -1, -1, 76, + 77, 78, -1, 184, -1, -1, -1, 184, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 50, 48, 49, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 188, 41, + -1, 42, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, + 300, 304, -1, -1, 51, 44, -1, -1, + -1, -1, 185, -1, 52, 185, -1, -1, + 185, 17, 75, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 185, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 45, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 185, + 185, -1, -1, -1, -1, -1, -1, -1, + 39, 46, -1, -1, -1, -1, -1, 318, + 320, -1, -1, 76, 77, 78, -1, 185, + -1, -1, -1, 185, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 50, 48, + 49, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 47, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 188, 41, -1, 42, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 43, -1, -1, -1, 300, 304, -1, -1, + 51, 44, -1, -1, -1, -1, 183, -1, + 52, 183, -1, -1, 183, 15, 75, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 183, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 45, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 183, 183, -1, -1, -1, + -1, -1, -1, -1, 39, 46, -1, -1, + -1, -1, -1, 318, 320, -1, -1, 76, + 77, 78, -1, 183, -1, -1, -1, 183, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 50, 48, 49, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 188, 41, + -1, 42, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, + 300, 304, -1, -1, 51, 44, -1, -1, + -1, -1, 186, -1, 52, 186, -1, -1, + 186, 18, 75, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 186, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 45, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 186, + 186, -1, -1, -1, -1, -1, -1, -1, + 39, 46, -1, -1, -1, -1, -1, 318, + 320, -1, -1, 76, 77, 78, -1, 186, + -1, -1, -1, 186, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 50, 48, + 49, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 47, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 188, 41, -1, 42, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 43, -1, -1, -1, 300, 304, -1, -1, + 51, 383, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 135, 138, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 136, + -1, -1, -1, -1, -1, -1, -1, -1, + 137, 334, 334, 334, -1, 334, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 334, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 334, -1, + -1, -1, -1, -1, -1, 334, -1, -1, + -1, -1, -1, -1, 334, 334, -1, -1, + -1, -1, -1, -1, -1, -1, 334, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 334, 334, 334, 334, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 139, 289, 290, 284, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 137, 141, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 140, -1, 137, 143, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 296, 301, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 142, 31, 177, 120, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 117, + -1, -1, -1, -1, -1, -1, -1, -1, + 284, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 178, 282, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 280, 172, 368, 369, 370, -1, 367, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 348, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 366, + -1, -1, -1, -1, -1, -1, 364, 365, + -1, -1, -1, -1, -1, -1, -1, -1, + 371, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 372, + 373, -1, -1, -1, 374, 375, 28, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 357, -1, 359, + -1, 355, 358, 368, 369, 370, -1, 367, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 352, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 366, + -1, -1, -1, -1, -1, -1, 364, 365, + -1, -1, -1, -1, -1, -1, -1, -1, + 371, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 372, + 373, -1, -1, -1, 374, 375, 28, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 357, -1, 359, + -1, 355, 358, 368, 369, 370, -1, 367, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 350, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 366, + -1, -1, -1, -1, -1, -1, 364, 365, + -1, -1, -1, -1, -1, -1, -1, -1, + 371, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 372, + 373, -1, -1, -1, 374, 375, 28, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 357, -1, 359, + -1, 355, 358, 382, 325, -1, -1, -1, + 109, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 329, 326, + -1, -1, -1, 109, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 329, 332, 377, -1, -1, -1, -1, + 377, -1, 377, 377, -1, -1, 377, 377, + 377, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 377, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 377, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 377, 377, -1, + -1, -1, -1, -1, -1, -1, 377, 377, + -1, -1, -1, -1, -1, 377, 377, -1, + -1, 377, 377, 377, 377, 377, -1, 131, + -1, 377, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 377, 377, 377, 144, + 281, 283, -1, -1, 286, 340, 341, 342, + -1, 338, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 285, -1, -1, -1, -1, -1, + -1, 366, -1, -1, -1, -1, -1, -1, + 364, 365, -1, -1, -1, -1, -1, -1, + -1, -1, 343, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 360, + 361, 362, 363, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 62, 57, + 56, 372, 373, 58, 60, 61, 374, 375, + 28, 59, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 333, 337, 335, + 336, 344, 145, 283, -1, -1, 291, 297, + 298, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 301, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 146, 118, -1, 119, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 288, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 147, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 287, 120, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 117, -1, -1, -1, -1, -1, + -1, -1, -1, 284, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 148, 282, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 280, 299, 200, 207, + +}; + +unsigned short Parser_keys[] = { + 132, 226, 224, 224, 132, 227, 132, 239, + 132, 240, 132, 132, 132, 132, 45, 244, + 40, 245, 40, 245, 132, 246, 123, 132, + 123, 123, 59, 132, 45, 244, 139, 139, + 40, 287, 132, 194, 40, 287, 125, 227, + 61, 137, 40, 243, 59, 59, 59, 59, + 40, 40, 40, 245, 125, 239, 33, 276, + 33, 276, 40, 284, 132, 290, 40, 287, + 44, 59, 38, 151, 33, 276, 33, 202, + 33, 188, 33, 266, 33, 202, 33, 276, + 33, 276, 33, 202, 33, 202, 189, 274, + 189, 274, 186, 275, 142, 142, 33, 276, + 59, 59, 44, 59, 33, 276, 59, 59, + 40, 245, 42, 290, 42, 290, 42, 290, + 59, 59, 59, 59, 41, 41, 132, 289, + 41, 44, 33, 276, 186, 278, 189, 279, + 189, 279, 33, 276, 33, 276, 33, 276, + 33, 276, 33, 276, 33, 276, 33, 276, + 33, 276, 33, 276, 132, 288, 40, 270, + 40, 269, 40, 269, 40, 269, 40, 269, + 40, 269, 40, 269, 40, 207, 40, 207, + 40, 207, 40, 207, 203, 207, 203, 207, + 44, 271, 45, 276, 33, 276, 44, 251, + 132, 240, 40, 287, 59, 59, 40, 245, + 59, 59, 40, 245, 59, 59, 40, 245, + 41, 149, 186, 193, 189, 274, 189, 274, + 189, 193, 38, 151, 33, 276, 33, 276, + 33, 276, 33, 276, 132, 289, 132, 269, + 40, 243, 139, 139, 139, 139, 132, 269, + 132, 269, 44, 125, 139, 271, 61, 61, + 59, 59, 40, 269, 124, 124, 40, 287, + 40, 287, 40, 287, 132, 132, 189, 279, + 189, 279, 193, 193, 33, 188, 44, 44, + 41, 41, 41, 44, 40, 284, 44, 44, + 41, 44, 125, 125, 125, 271, 43, 270, + 40, 269, 125, 125, 41, 41, 41, 41, + 0, 0 +}; + +unsigned int Parser_offsets[] = { + 0, 95, 96, 192, 300, 409, 410, 411, + 611, 817, 1023, 1138, 1148, 1149, 1223, 1423, + 1424, 1672, 1735, 1983, 2086, 2163, 2367, 2368, + 2369, 2370, 2576, 2691, 2935, 3179, 3424, 3583, + 3831, 3847, 3961, 4205, 4375, 4531, 4765, 4935, + 5179, 5423, 5593, 5763, 5849, 5935, 6025, 6026, + 6270, 6271, 6287, 6531, 6532, 6738, 6987, 7236, + 7485, 7486, 7487, 7488, 7646, 7650, 7894, 7987, + 8078, 8169, 8413, 8657, 8901, 9145, 9389, 9633, + 9877, 10121, 10365, 10522, 10753, 10983, 11213, 11443, + 11673, 11903, 12133, 12301, 12469, 12637, 12805, 12810, + 12815, 13043, 13275, 13519, 13727, 13836, 14084, 14085, + 14291, 14292, 14498, 14499, 14705, 14814, 14822, 14908, + 14994, 14999, 15113, 15357, 15601, 15845, 16089, 16247, + 16385, 16589, 16590, 16591, 16729, 16867, 16949, 17082, + 17083, 17084, 17314, 17315, 17563, 17811, 18059, 18060, + 18151, 18242, 18243, 18399, 18400, 18401, 18405, 18650, + 18651, 18655, 18656, 18803, 19031, 19261, 19262, 19263, + 19264 +}; + +unsigned short Parser_targs[] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 15, + 15, 15, 15, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144 +}; + +unsigned int Parser_actInds[] = { + 0, 2, 4, 6, 8, 10, 12, 14, + 16, 18, 20, 22, 24, 26, 28, 30, + 33, 36, 39, 42, 45, 47, 49, 51, + 53, 55, 57, 59, 61, 63, 65, 67, + 69, 71, 73, 75, 77, 79, 81, 83, + 85, 88, 90, 92, 94, 96, 98, 100, + 102, 104, 106, 108, 110, 112, 114, 116, + 118, 120, 122, 124, 126, 128, 130, 132, + 134, 136, 138, 140, 142, 144, 146, 148, + 150, 152, 154, 156, 158, 160, 162, 164, + 166, 168, 170, 172, 174, 176, 178, 180, + 182, 184, 186, 188, 190, 192, 195, 197, + 199, 201, 203, 205, 207, 209, 211, 213, + 215, 217, 219, 221, 223, 225, 227, 229, + 231, 233, 235, 237, 239, 241, 243, 245, + 247, 249, 251, 253, 255, 257, 259, 261, + 263, 265, 267, 269, 271, 273, 275, 277, + 279, 281, 283, 285, 287, 289, 291, 293, + 295, 297, 299, 301, 303, 305, 307, 309, + 311, 313, 315, 317, 319, 321, 323, 325, + 327, 329, 331, 333, 335, 337, 339, 341, + 343, 345, 347, 349, 351, 353, 355, 357, + 359, 361, 363, 365, 367, 369, 371, 373, + 375, 377, 379, 381, 383, 385, 387, 389, + 391, 393, 395, 397, 399, 401, 403, 405, + 407, 409, 411, 413, 415, 417, 419, 421, + 423, 425, 427, 429, 431, 433, 435, 437, + 439, 441, 443, 445, 447, 449, 451, 453, + 455, 457, 459, 461, 463, 465, 467, 469, + 471, 473, 475, 477, 479, 481, 483, 485, + 487, 489, 491, 493, 495, 497, 499, 501, + 503, 505, 507, 509, 511, 513, 515, 517, + 519, 521, 523, 525, 527, 529, 531, 533, + 535, 537, 539, 541, 543, 545, 547, 549, + 551, 553, 555, 557, 559, 561, 563, 565, + 567, 569, 571, 573, 575, 577, 579, 581, + 583, 585, 587, 589, 591, 593, 595, 597, + 599, 601, 603, 605, 607, 609, 611, 613, + 615, 617, 619, 621, 623, 625, 627, 629, + 631, 633, 635, 637, 639, 641, 643, 645, + 647, 649, 651, 653, 655, 657, 659, 661, + 663, 665, 667, 669, 671, 673, 675, 677, + 679, 681, 683, 685, 687, 689, 691, 693, + 695, 697, 699, 701, 703, 705, 707, 709, + 711, 713, 715, 717, 719, 721, 723, 725, + 727, 729, 731, 733, 735, 737, 739, 741, + 743, 745, 747, 749, 751, 753, 755, 757, + 759, 761, 763, 765, 767, 769, 771, 773, + 775, 777, 779, 781, 783, 785, 787, 789, + 791, 793 +}; + +unsigned int Parser_actions[] = { + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 170, 1, + 0, 174, 1, 0, 178, 1, 0, 182, + 1, 0, 186, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 66, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 270, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 2, 0, 7, 0, 10, 0, 15, + 0, 18, 0, 59, 0, 62, 0, 63, + 0, 66, 0, 71, 0, 75, 0, 79, + 0, 83, 0, 87, 0, 91, 0, 95, + 0, 99, 0, 103, 0, 107, 0, 111, + 0, 115, 0, 118, 0, 122, 0, 127, + 0, 131, 0, 135, 0, 139, 0, 143, + 0, 147, 0, 151, 0, 155, 0, 158, + 0, 162, 0, 166, 0, 170, 0, 174, + 0, 178, 0, 182, 0, 186, 0, 191, + 0, 195, 0, 199, 0, 203, 0, 207, + 0, 211, 0, 215, 0, 218, 0, 223, + 0, 226, 0, 231, 0, 235, 0, 239, + 0, 243, 0, 247, 0, 251, 0, 255, + 0, 259, 0, 263, 0, 267, 0, 270, + 0, 274, 0, 278, 0, 282, 0, 286, + 0, 291, 0, 295, 0, 299, 0, 303, + 0, 307, 0, 311, 0, 315, 0, 319, + 0, 323, 0, 327, 0, 331, 0, 335, + 0, 339, 0, 343, 0, 347, 0, 351, + 0, 355, 0, 359, 0, 363, 0, 367, + 0, 371, 0, 375, 0, 379, 0, 383, + 0, 387, 0, 391, 0, 395, 0, 399, + 0, 403, 0, 407, 0, 411, 0, 415, + 0, 419, 0, 423, 0, 427, 0, 431, + 0, 435, 0, 439, 0, 443, 0, 447, + 0, 451, 0, 455, 0, 459, 0, 463, + 0, 467, 0, 471, 0, 475, 0, 479, + 0, 483, 0, 487, 0, 491, 0, 495, + 0, 499, 0, 503, 0, 507, 0, 511, + 0, 515, 0, 519, 0, 523, 0, 527, + 0, 531, 0, 535, 0, 539, 0, 543, + 0, 547, 0, 551, 0, 555, 0, 559, + 0, 563, 0, 567, 0, 570, 0, 571, + 0, 575, 0, 578, 0, 583, 0, 587, + 0, 591, 0, 595, 0, 598, 0, 603, + 0, 607, 0, 611, 0, 615, 0, 619, + 0, 623, 0, 627, 0, 631, 0, 635, + 0, 639, 0, 643, 0, 647, 0, 651, + 0, 654, 0, 658, 0, 662, 0, 663, + 0, 667, 0, 671, 0, 675, 0, 679, + 0, 683, 0, 686, 0, 687, 0, 690, + 0, 691, 0, 695, 0, 699, 0, 703, + 0, 707, 0, 710, 0, 715, 0, 718, + 0, 723, 0, 727, 0, 731, 0, 735, + 0, 739, 0, 742, 0, 746, 0, 751, + 0, 755, 0, 758, 0, 763, 0, 767, + 0, 771, 0, 775, 0, 779, 0, 783, + 0, 787, 0, 791, 0, 795, 0, 799, + 0, 803, 0, 807, 0, 811, 0, 815, + 0, 819, 0, 823, 0, 827, 0, 831, + 0, 835, 0, 839, 0, 843, 0, 846, + 0, 851, 0, 855, 0, 859, 0, 863, + 0, 867, 0, 871, 0, 875, 0, 879, + 0, 883, 0, 887, 0, 891, 0, 895, + 0, 899, 0, 903, 0, 907, 0, 911, + 0, 915, 0, 919, 0, 923, 0, 927, + 0, 930, 0, 934, 0, 938, 0, 943, + 0, 946, 0, 951, 0, 955, 0, 23, + 0, 27, 0, 31, 0, 35, 0, 39, + 0, 43, 0, 47, 0, 51, 0, 55, + 0, 1, 0 +}; + +int Parser_commitLen[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2 +}; + +unsigned int Parser_fssProdIdIndex[] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239 +}; + +char Parser_fssProdLengths[] = { + 1, 3, 0, 2, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 4, 5, 5, 1, 5, 4, 3, + 4, 3, 3, 5, 2, 0, 1, 4, + 2, 1, 1, 1, 3, 2, 1, 0, + 3, 1, 3, 3, 3, 3, 1, 2, + 3, 3, 3, 3, 1, 3, 1, 3, + 1, 3, 3, 7, 3, 3, 3, 3, + 3, 3, 7, 1, 1, 1, 1, 1, + 1, 2, 1, 2, 1, 2, 1, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 3, 1, 1, 3, + 1, 1, 1, 2, 2, 1, 2, 2, + 2, 2, 4, 5, 5, 6, 1, 1, + 2, 2, 1, 1, 1, 1, 3, 3, + 3, 3, 3, 1, 1, 1, 2, 1, + 2, 0, 2, 1, 3, 3, 1, 1, + 2, 0, 1, 3, 2, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 3, 4, 3, 4, 3, 4, + 2, 2, 2, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 4, + 2, 0, 2, 1, 0, 3, 1, 1 +}; + +unsigned short Parser_prodLhsIds[] = { + 226, 225, 225, 227, 227, 228, 228, 228, + 228, 228, 228, 228, 228, 228, 238, 239, + 239, 237, 229, 230, 240, 231, 232, 232, + 233, 234, 235, 236, 246, 246, 242, 242, + 247, 247, 248, 248, 248, 249, 249, 249, + 241, 241, 252, 252, 252, 252, 252, 253, + 253, 253, 253, 253, 253, 254, 254, 255, + 255, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 258, 258, 258, 258, + 261, 261, 261, 261, 261, 261, 261, 262, + 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 263, 263, 263, 263, 263, + 263, 263, 263, 263, 263, 263, 263, 264, + 264, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 265, 265, 265, 265, 265, + 265, 265, 265, 265, 265, 265, 265, 266, + 266, 266, 266, 266, 266, 266, 266, 266, + 266, 266, 266, 250, 250, 250, 269, 251, + 260, 259, 270, 270, 270, 267, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 271, + 272, 272, 272, 273, 273, 273, 273, 273, + 273, 273, 273, 276, 276, 244, 244, 244, + 275, 275, 277, 277, 278, 278, 278, 278, + 274, 274, 279, 279, 243, 243, 280, 280, + 280, 283, 283, 283, 283, 283, 283, 281, + 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 245, 245, 286, 286, 286, 282, + 282, 282, 282, 282, 282, 282, 287, 287, + 287, 287, 287, 284, 284, 284, 284, 284, + 256, 288, 285, 290, 290, 289, 289, 291 +}; + +const char *Parser_prodNames[] = { + "start-1", + "section_list-1", + "section_list-2", + "statement_list-1", + "statement_list-2", + "statement-1", + "statement-2", + "statement-3", + "statement-4", + "statement-5", + "statement-6", + "statement-7", + "statement-8", + "statement-9", + "export_open-1", + "opt_export-1", + "opt_export-2", + "export_block-1", + "assignment-1", + "instantiation-1", + "machine_name-1", + "action_spec-1", + "alphtype_spec-1", + "alphtype_spec-2", + "range_spec-1", + "getkey_spec-1", + "access_spec-1", + "variable_spec-1", + "opt_whitespace-1", + "opt_whitespace-2", + "join_or_lm-1", + "join_or_lm-2", + "lm_part_list-1", + "lm_part_list-2", + "longest_match_part-1", + "longest_match_part-2", + "longest_match_part-3", + "opt_lm_part_action-1", + "opt_lm_part_action-2", + "opt_lm_part_action-3", + "join-1", + "join-2", + "expression-1", + "expression-2", + "expression-3", + "expression-4", + "expression-5", + "term-1", + "term-2", + "term-3", + "term-4", + "term-5", + "term-6", + "factor_with_label-1", + "factor_with_label-2", + "factor_with_ep-1", + "factor_with_ep-2", + "factor_with_aug-1", + "factor_with_aug-2", + "factor_with_aug-3", + "factor_with_aug-4", + "factor_with_aug-5", + "factor_with_aug-6", + "factor_with_aug-7", + "factor_with_aug-8", + "factor_with_aug-9", + "factor_with_aug-10", + "factor_with_aug-11", + "aug_type_base-1", + "aug_type_base-2", + "aug_type_base-3", + "aug_type_base-4", + "aug_type_cond-1", + "aug_type_cond-2", + "aug_type_cond-3", + "aug_type_cond-4", + "aug_type_cond-5", + "aug_type_cond-6", + "aug_type_cond-7", + "aug_type_to_state-1", + "aug_type_to_state-2", + "aug_type_to_state-3", + "aug_type_to_state-4", + "aug_type_to_state-5", + "aug_type_to_state-6", + "aug_type_to_state-7", + "aug_type_to_state-8", + "aug_type_to_state-9", + "aug_type_to_state-10", + "aug_type_to_state-11", + "aug_type_to_state-12", + "aug_type_from_state-1", + "aug_type_from_state-2", + "aug_type_from_state-3", + "aug_type_from_state-4", + "aug_type_from_state-5", + "aug_type_from_state-6", + "aug_type_from_state-7", + "aug_type_from_state-8", + "aug_type_from_state-9", + "aug_type_from_state-10", + "aug_type_from_state-11", + "aug_type_from_state-12", + "aug_type_eof-1", + "aug_type_eof-2", + "aug_type_eof-3", + "aug_type_eof-4", + "aug_type_eof-5", + "aug_type_eof-6", + "aug_type_eof-7", + "aug_type_eof-8", + "aug_type_eof-9", + "aug_type_eof-10", + "aug_type_eof-11", + "aug_type_eof-12", + "aug_type_gbl_error-1", + "aug_type_gbl_error-2", + "aug_type_gbl_error-3", + "aug_type_gbl_error-4", + "aug_type_gbl_error-5", + "aug_type_gbl_error-6", + "aug_type_gbl_error-7", + "aug_type_gbl_error-8", + "aug_type_gbl_error-9", + "aug_type_gbl_error-10", + "aug_type_gbl_error-11", + "aug_type_gbl_error-12", + "aug_type_local_error-1", + "aug_type_local_error-2", + "aug_type_local_error-3", + "aug_type_local_error-4", + "aug_type_local_error-5", + "aug_type_local_error-6", + "aug_type_local_error-7", + "aug_type_local_error-8", + "aug_type_local_error-9", + "aug_type_local_error-10", + "aug_type_local_error-11", + "aug_type_local_error-12", + "action_embed-1", + "action_embed-2", + "action_embed-3", + "action_embed_word-1", + "action_embed_block-1", + "priority_name-1", + "priority_aug-1", + "priority_aug_num-1", + "priority_aug_num-2", + "priority_aug_num-3", + "local_err_name-1", + "factor_with_rep-1", + "factor_with_rep-2", + "factor_with_rep-3", + "factor_with_rep-4", + "factor_with_rep-5", + "factor_with_rep-6", + "factor_with_rep-7", + "factor_with_rep-8", + "factor_with_rep-9", + "factor_rep_num-1", + "factor_with_neg-1", + "factor_with_neg-2", + "factor_with_neg-3", + "factor-1", + "factor-2", + "factor-3", + "factor-4", + "factor-5", + "factor-6", + "factor-7", + "factor-8", + "range_lit-1", + "range_lit-2", + "alphabet_num-1", + "alphabet_num-2", + "alphabet_num-3", + "regular_expr-1", + "regular_expr-2", + "regular_expr_item-1", + "regular_expr_item-2", + "regular_expr_char-1", + "regular_expr_char-2", + "regular_expr_char-3", + "regular_expr_char-4", + "regular_expr_or_data-1", + "regular_expr_or_data-2", + "regular_expr_or_char-1", + "regular_expr_or_char-2", + "inline_block-1", + "inline_block-2", + "inline_block_item-1", + "inline_block_item-2", + "inline_block_item-3", + "inline_block_symbol-1", + "inline_block_symbol-2", + "inline_block_symbol-3", + "inline_block_symbol-4", + "inline_block_symbol-5", + "inline_block_symbol-6", + "inline_block_interpret-1", + "inline_block_interpret-2", + "inline_block_interpret-3", + "inline_block_interpret-4", + "inline_block_interpret-5", + "inline_block_interpret-6", + "inline_block_interpret-7", + "inline_block_interpret-8", + "inline_block_interpret-9", + "inline_block_interpret-10", + "inline_block_interpret-11", + "inline_expr-1", + "inline_expr-2", + "inline_expr_item-1", + "inline_expr_item-2", + "inline_expr_item-3", + "inline_expr_any-1", + "inline_expr_any-2", + "inline_expr_any-3", + "inline_expr_any-4", + "inline_expr_any-5", + "inline_expr_any-6", + "inline_expr_any-7", + "inline_expr_symbol-1", + "inline_expr_symbol-2", + "inline_expr_symbol-3", + "inline_expr_symbol-4", + "inline_expr_symbol-5", + "inline_expr_interpret-1", + "inline_expr_interpret-2", + "inline_expr_interpret-3", + "inline_expr_interpret-4", + "inline_expr_interpret-5", + "local_state_ref-1", + "no_name_sep-1", + "state_ref-1", + "opt_name_sep-1", + "opt_name_sep-2", + "state_ref_names-1", + "state_ref_names-2", + "_start-1" +}; + +const char *Parser_lelNames[] = { + "D-0", + "D-1", + "D-2", + "D-3", + "D-4", + "D-5", + "D-6", + "D-7", + "D-8", + "D-9", + "D-10", + "D-11", + "D-12", + "D-13", + "D-14", + "D-15", + "D-16", + "D-17", + "D-18", + "D-19", + "D-20", + "D-21", + "D-22", + "D-23", + "D-24", + "D-25", + "D-26", + "D-27", + "D-28", + "D-29", + "D-30", + "D-31", + "D-32", + "!", + "\"", + "#", + "$", + "%", + "&", + "'", + "(", + ")", + "*", + "+", + ",", + "-", + ".", + "/", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + ":", + ";", + "<", + "=", + ">", + "?", + "@", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "[", + "\\", + "]", + "^", + "_", + "`", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "{", + "|", + "}", + "~", + "D-127", + "KW_Machine", + "KW_Include", + "KW_Import", + "KW_Write", + "TK_Word", + "TK_Literal", + "TK_Number", + "TK_Inline", + "TK_Reference", + "TK_ColonEquals", + "TK_EndSection", + "TK_UInt", + "TK_Hex", + "TK_BaseClause", + "TK_DotDot", + "TK_ColonGt", + "TK_ColonGtGt", + "TK_LtColon", + "TK_Arrow", + "TK_DoubleArrow", + "TK_StarStar", + "TK_NameSep", + "TK_BarStar", + "TK_DashDash", + "TK_StartCond", + "TK_AllCond", + "TK_LeavingCond", + "TK_Middle", + "TK_StartGblError", + "TK_AllGblError", + "TK_FinalGblError", + "TK_NotFinalGblError", + "TK_NotStartGblError", + "TK_MiddleGblError", + "TK_StartLocalError", + "TK_AllLocalError", + "TK_FinalLocalError", + "TK_NotFinalLocalError", + "TK_NotStartLocalError", + "TK_MiddleLocalError", + "TK_StartEOF", + "TK_AllEOF", + "TK_FinalEOF", + "TK_NotFinalEOF", + "TK_NotStartEOF", + "TK_MiddleEOF", + "TK_StartToState", + "TK_AllToState", + "TK_FinalToState", + "TK_NotFinalToState", + "TK_NotStartToState", + "TK_MiddleToState", + "TK_StartFromState", + "TK_AllFromState", + "TK_FinalFromState", + "TK_NotFinalFromState", + "TK_NotStartFromState", + "TK_MiddleFromState", + "RE_Slash", + "RE_SqOpen", + "RE_SqOpenNeg", + "RE_SqClose", + "RE_Dot", + "RE_Star", + "RE_Dash", + "RE_Char", + "IL_WhiteSpace", + "IL_Comment", + "IL_Literal", + "IL_Symbol", + "KW_Action", + "KW_AlphType", + "KW_Range", + "KW_GetKey", + "KW_When", + "KW_Eof", + "KW_Err", + "KW_Lerr", + "KW_To", + "KW_From", + "KW_Export", + "KW_Break", + "KW_Exec", + "KW_Hold", + "KW_PChar", + "KW_Char", + "KW_Goto", + "KW_Call", + "KW_Ret", + "KW_CurState", + "KW_TargState", + "KW_Entry", + "KW_Next", + "KW_Variable", + "KW_Access", + "TK_Semi", + "_eof", + "section_list", + "start", + "statement_list", + "statement", + "assignment", + "instantiation", + "action_spec", + "alphtype_spec", + "range_spec", + "getkey_spec", + "access_spec", + "variable_spec", + "export_block", + "export_open", + "opt_export", + "machine_name", + "join", + "join_or_lm", + "inline_block", + "alphabet_num", + "inline_expr", + "opt_whitespace", + "lm_part_list", + "longest_match_part", + "opt_lm_part_action", + "action_embed", + "action_embed_block", + "expression", + "term", + "factor_with_label", + "factor_with_ep", + "local_state_ref", + "factor_with_aug", + "aug_type_base", + "priority_aug", + "priority_name", + "aug_type_cond", + "aug_type_to_state", + "aug_type_from_state", + "aug_type_eof", + "aug_type_gbl_error", + "aug_type_local_error", + "local_err_name", + "factor_with_rep", + "action_embed_word", + "priority_aug_num", + "factor_rep_num", + "factor_with_neg", + "factor", + "regular_expr_or_data", + "regular_expr", + "range_lit", + "regular_expr_item", + "regular_expr_char", + "regular_expr_or_char", + "inline_block_item", + "inline_block_interpret", + "inline_expr_any", + "inline_block_symbol", + "inline_expr_interpret", + "state_ref", + "inline_expr_item", + "inline_expr_symbol", + "no_name_sep", + "state_ref_names", + "opt_name_sep", + "_start" +}; + +#line 1375 "rlparse.kl" + + +void Parser::init() +{ + #line 3769 "rlparse.cpp" + curs = Parser_startState; + pool = 0; + freshEl = (struct Parser_LangEl*) malloc( sizeof(struct Parser_LangEl)*8128); + #ifdef LOG_ACTIONS + cerr << "allocating 8128 LangEls" << endl; + #endif + stackTop = freshEl; + stackTop->type = 0; + stackTop->state = -1; + stackTop->next = 0; + stackTop->child = 0; + freshPos = 1; + lastFinal = stackTop; + numRetry = 0; + numNodes = 0; + errCount = 0; +#line 1380 "rlparse.kl" +} + +int Parser::parseLangEl( int type, const Token *token ) +{ + #line 3791 "rlparse.cpp" +#define reject() induceReject = 1 + + int pos, targState; + unsigned int *action; + int rhsLen; + struct Parser_LangEl *rhs[32]; + struct Parser_LangEl *lel; + struct Parser_LangEl *input; + char induceReject; + + if ( curs < 0 ) + return 0; + + if ( pool == 0 ) { + if ( freshPos == 8128 ) { + freshEl = (struct Parser_LangEl*) malloc( + sizeof(struct Parser_LangEl)*8128); + #ifdef LOG_ACTIONS + cerr << "allocating 8128 LangEls" << endl; + #endif + freshPos = 0; + } + input = freshEl + freshPos++; + } + else { + input = pool; + pool = pool->next; + } + numNodes += 1; + input->type = type; + input->user.token = *token; + input->next = 0; + input->retry = 0; + input->child = 0; + +again: + if ( input == 0 ) + goto _out; + + lel = input; + if ( lel->type < Parser_keys[curs<<1] || lel->type > Parser_keys[(curs<<1)+1] ) + goto parseError; + + pos = Parser_indicies[Parser_offsets[curs] + (lel->type - Parser_keys[curs<<1])]; + if ( pos < 0 ) + goto parseError; + + induceReject = 0; + targState = Parser_targs[pos]; + action = Parser_actions + Parser_actInds[pos]; + if ( lel->retry & 0x0000ffff ) + action += (lel->retry & 0x0000ffff); + + if ( *action & 0x1 ) { + #ifdef LOG_ACTIONS + cerr << "shifted: " << Parser_lelNames[lel->type]; + #endif + input = input->next; + lel->state = curs; + lel->next = stackTop; + stackTop = lel; + + if ( action[1] == 0 ) + lel->retry &= 0xffff0000; + else { + lel->retry += 1; + numRetry += 1; + #ifdef LOG_ACTIONS + cerr << " retry: " << stackTop; + #endif + } + #ifdef LOG_ACTIONS + cerr << endl; + #endif + } + + if ( Parser_commitLen[pos] != 0 ) { + struct Parser_LangEl *commitHead = stackTop; + int absCommitLen = Parser_commitLen[pos]; + + #ifdef LOG_ACTIONS + cerr << "running commit of length: " << Parser_commitLen[pos] << endl; + #endif + + if ( absCommitLen < 0 ) { + commitHead = commitHead->next; + absCommitLen = -1 * absCommitLen; + } + { + struct Parser_LangEl *lel = commitHead; + struct Parser_LangEl **cmStack = (struct Parser_LangEl**) malloc( sizeof(struct Parser_LangEl) * numNodes); + int n = absCommitLen, depth = 0, sp = 0; + +commit_head: + if ( lel->retry > 0 ) { + if ( lel->retry & 0x0000ffff ) + numRetry -= 1; + if ( lel->retry & 0xffff0000 ) + numRetry -= 1; + lel->retry = 0; + } + + /* If depth is > 0 then move over lel freely, otherwise, make + * sure that we have not already done n steps down the line. */ + if ( lel->next != 0 && ( depth > 0 || n > 1 ) ) { + cmStack[sp++] = lel; + lel = lel->next; + + /* If we are at the top level count the steps down the line. */ + if ( depth == 0 ) + n -= 1; + goto commit_head; + } + +commit_reverse: + if ( lel->child != 0 ) { + cmStack[sp++] = lel; + lel = lel->child; + + /* When we move down we need to increment the depth. */ + depth += 1; + goto commit_head; + } + +commit_upwards: + if ( sp > 0 ) { + /* Figure out which place to return to. */ + if ( cmStack[sp-1]->next == lel ) { + lel = cmStack[--sp]; + goto commit_reverse; + } + else { + /* Going back up, adjust the depth. */ + lel = cmStack[--sp]; + depth -= 1; + goto commit_upwards; + } + } + free( cmStack ); + } + if ( numRetry == 0 ) { + #ifdef LOG_ACTIONS + cerr << "number of retries is zero, " + "executing final actions" << endl; + #endif + { + struct Parser_LangEl *lel = commitHead; + struct Parser_LangEl **cmStack = (struct Parser_LangEl**) malloc( sizeof( struct Parser_LangEl) * numNodes); + int sp = 0; + char doExec = 0; + +final_head: + if ( lel == lastFinal ) { + doExec = 1; + goto hit_final; + } + + if ( lel->next != 0 ) { + cmStack[sp++] = lel; + lel = lel->next; + goto final_head; + } + +final_reverse: + + if ( lel->child != 0 ) { + cmStack[sp++] = lel; + lel = lel->child; + goto final_head; + } + +final_upwards: + + if ( doExec ) { +{ + if ( lel->type < 225 ) { + } + else { + struct Parser_LangEl *redLel = lel; + if ( redLel->child != 0 ) { + int r = Parser_fssProdLengths[redLel->reduction] - 1; + struct Parser_LangEl *rhsEl = redLel->child; + while ( rhsEl != 0 ) { + rhs[r--] = rhsEl; + rhsEl = rhsEl->next; + } + } +switch ( lel->reduction ) { +case 14: { +#line 59 "rlparse.kl" + + exportContext.append( true ); + + +#line 3985 "rlparse.cpp" +} break; +case 15: { +#line 68 "rlparse.kl" + (&redLel->user.opt_export)->isSet = true; + +#line 3991 "rlparse.cpp" +} break; +case 16: { +#line 69 "rlparse.kl" + (&redLel->user.opt_export)->isSet = false; + +#line 3997 "rlparse.cpp" +} break; +case 17: { +#line 72 "rlparse.kl" + + exportContext.remove( exportContext.length()-1 ); + + +#line 4005 "rlparse.cpp" +} break; +case 18: { +#line 77 "rlparse.kl" + + /* Main machine must be an instance. */ + bool isInstance = false; + if ( strcmp((&rhs[1]->user.token_type)->token.data, mainMachine) == 0 ) { + warning((&rhs[1]->user.token_type)->token.loc) << + "main machine will be implicitly instantiated" << endl; + isInstance = true; + } + + /* Generic creation of machine for instantiation and assignment. */ + JoinOrLm *joinOrLm = new JoinOrLm( (&rhs[3]->user.join)->join ); + tryMachineDef( (&rhs[1]->user.token_type)->token.loc, (&rhs[1]->user.token_type)->token.data, joinOrLm, isInstance ); + + if ( (&rhs[0]->user.opt_export)->isSet ) + exportContext.remove( exportContext.length()-1 ); + + +#line 4026 "rlparse.cpp" +} break; +case 19: { +#line 95 "rlparse.kl" + + /* Generic creation of machine for instantiation and assignment. */ + tryMachineDef( (&rhs[1]->user.token_type)->token.loc, (&rhs[1]->user.token_type)->token.data, (&rhs[3]->user.join_or_lm)->joinOrLm, true ); + + if ( (&rhs[0]->user.opt_export)->isSet ) + exportContext.remove( exportContext.length()-1 ); + + +#line 4038 "rlparse.cpp" +} break; +case 20: { +#line 111 "rlparse.kl" + + /* Make/get the priority key. The name may have already been referenced + * and therefore exist. */ + PriorDictEl *priorDictEl; + if ( pd->priorDict.insert( (&rhs[0]->user.token)->data, pd->nextPriorKey, &priorDictEl ) ) + pd->nextPriorKey += 1; + pd->curDefPriorKey = priorDictEl->value; + + /* Make/get the local error key. */ + LocalErrDictEl *localErrDictEl; + if ( pd->localErrDict.insert( (&rhs[0]->user.token)->data, pd->nextLocalErrKey, &localErrDictEl ) ) + pd->nextLocalErrKey += 1; + pd->curDefLocalErrKey = localErrDictEl->value; + + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + + +#line 4059 "rlparse.cpp" +} break; +case 21: { +#line 129 "rlparse.kl" + + if ( pd->actionDict.find( (&rhs[1]->user.token)->data ) ) { + /* Recover by just ignoring the duplicate. */ + error((&rhs[1]->user.token)->loc) << "action \"" << (&rhs[1]->user.token)->data << "\" already defined" << endl; + } + else { + //cerr << "NEW ACTION " << $2->data << " " << $4->inlineList << endl; + /* Add the action to the list of actions. */ + Action *newAction = new Action( (&rhs[2]->user.token)->loc, (&rhs[1]->user.token)->data, + (&rhs[3]->user.inline_list)->inlineList, pd->nextCondId++ ); + + /* Insert to list and dict. */ + pd->actionList.append( newAction ); + pd->actionDict.insert( newAction ); + } + + +#line 4080 "rlparse.cpp" +} break; +case 22: { +#line 149 "rlparse.kl" + + if ( ! pd->setAlphType( (&rhs[1]->user.token)->data, (&rhs[2]->user.token)->data ) ) { + // Recover by ignoring the alphtype statement. + error((&rhs[1]->user.token)->loc) << "\"" << (&rhs[1]->user.token)->data << + " " << (&rhs[2]->user.token)->data << "\" is not a valid alphabet type" << endl; + } + + +#line 4092 "rlparse.cpp" +} break; +case 23: { +#line 158 "rlparse.kl" + + if ( ! pd->setAlphType( (&rhs[1]->user.token)->data ) ) { + // Recover by ignoring the alphtype statement. + error((&rhs[1]->user.token)->loc) << "\"" << (&rhs[1]->user.token)->data << + "\" is not a valid alphabet type" << endl; + } + + +#line 4104 "rlparse.cpp" +} break; +case 24: { +#line 168 "rlparse.kl" + + // Save the upper and lower ends of the range and emit the line number. + pd->lowerNum = (&rhs[1]->user.token_type)->token.data; + pd->upperNum = (&rhs[2]->user.token_type)->token.data; + pd->rangeLowLoc = (&rhs[1]->user.token_type)->token.loc; + pd->rangeHighLoc = (&rhs[2]->user.token_type)->token.loc; + + +#line 4116 "rlparse.cpp" +} break; +case 25: { +#line 177 "rlparse.kl" + + pd->getKeyExpr = (&rhs[1]->user.inline_list)->inlineList; + + +#line 4124 "rlparse.cpp" +} break; +case 26: { +#line 182 "rlparse.kl" + + pd->accessExpr = (&rhs[1]->user.inline_list)->inlineList; + + +#line 4132 "rlparse.cpp" +} break; +case 27: { +#line 187 "rlparse.kl" + + /* FIXME: Need to implement the rest of this. */ + if ( strcmp( (&rhs[2]->user.token)->data, "curstate" ) == 0 ) + pd->curStateExpr = (&rhs[3]->user.inline_list)->inlineList; + else { + error((&rhs[2]->user.token)->loc) << "sorry, unimplementd" << endl; + } + + +#line 4145 "rlparse.cpp" +} break; +case 30: { +#line 209 "rlparse.kl" + + (&redLel->user.join_or_lm)->joinOrLm = new JoinOrLm( (&rhs[0]->user.join)->join ); + + +#line 4153 "rlparse.cpp" +} break; +case 31: { +#line 213 "rlparse.kl" + + /* Create a new factor going to a longest match structure. Record + * in the parse data that we have a longest match. */ + LongestMatch *lm = new LongestMatch( (&rhs[0]->user.token)->loc, (&rhs[1]->user.lm_part_list)->lmPartList ); + pd->lmList.append( lm ); + for ( LmPartList::Iter lmp = *((&rhs[1]->user.lm_part_list)->lmPartList); lmp.lte(); lmp++ ) + lmp->longestMatch = lm; + (&redLel->user.join_or_lm)->joinOrLm = new JoinOrLm( lm ); + + +#line 4167 "rlparse.cpp" +} break; +case 32: { +#line 229 "rlparse.kl" + + if ( (&rhs[1]->user.longest_match_part)->lmPart != 0 ) + (&rhs[0]->user.lm_part_list)->lmPartList->append( (&rhs[1]->user.longest_match_part)->lmPart ); + (&redLel->user.lm_part_list)->lmPartList = (&rhs[0]->user.lm_part_list)->lmPartList; + + +#line 4177 "rlparse.cpp" +} break; +case 33: { +#line 235 "rlparse.kl" + + /* Create a new list with the part. */ + (&redLel->user.lm_part_list)->lmPartList = new LmPartList; + if ( (&rhs[0]->user.longest_match_part)->lmPart != 0 ) + (&redLel->user.lm_part_list)->lmPartList->append( (&rhs[0]->user.longest_match_part)->lmPart ); + + +#line 4188 "rlparse.cpp" +} break; +case 34: { +#line 248 "rlparse.kl" + (&redLel->user.longest_match_part)->lmPart = 0; + +#line 4194 "rlparse.cpp" +} break; +case 35: { +#line 250 "rlparse.kl" + (&redLel->user.longest_match_part)->lmPart = 0; + +#line 4200 "rlparse.cpp" +} break; +case 36: { +#line 252 "rlparse.kl" + + (&redLel->user.longest_match_part)->lmPart = 0; + Action *action = (&rhs[1]->user.opt_lm_part_action)->action; + if ( action != 0 ) + action->isLmAction = true; + (&redLel->user.longest_match_part)->lmPart = new LongestMatchPart( (&rhs[0]->user.join)->join, action, + (&rhs[2]->user.token)->loc, pd->nextLongestMatchId++ ); + + +#line 4213 "rlparse.cpp" +} break; +case 37: { +#line 267 "rlparse.kl" + + (&redLel->user.opt_lm_part_action)->action = (&rhs[1]->user.action_ref)->action; + + +#line 4221 "rlparse.cpp" +} break; +case 38: { +#line 271 "rlparse.kl" + + (&redLel->user.opt_lm_part_action)->action = (&rhs[0]->user.action_ref)->action; + + +#line 4229 "rlparse.cpp" +} break; +case 39: { +#line 275 "rlparse.kl" + + (&redLel->user.opt_lm_part_action)->action = 0; + + +#line 4237 "rlparse.cpp" +} break; +case 40: { +#line 286 "rlparse.kl" + + /* Append the expression to the list and return it. */ + (&rhs[0]->user.join)->join->exprList.append( (&rhs[2]->user.expression)->expression ); + (&redLel->user.join)->join = (&rhs[0]->user.join)->join; + + +#line 4247 "rlparse.cpp" +} break; +case 41: { +#line 292 "rlparse.kl" + + (&redLel->user.join)->join = new Join( (&rhs[0]->user.expression)->expression ); + + +#line 4255 "rlparse.cpp" +} break; +case 42: { +#line 302 "rlparse.kl" + + (&redLel->user.expression)->expression = new Expression( (&rhs[0]->user.expression)->expression, + (&rhs[2]->user.term)->term, Expression::OrType ); + + +#line 4264 "rlparse.cpp" +} break; +case 43: { +#line 307 "rlparse.kl" + + (&redLel->user.expression)->expression = new Expression( (&rhs[0]->user.expression)->expression, + (&rhs[2]->user.term)->term, Expression::IntersectType ); + + +#line 4273 "rlparse.cpp" +} break; +case 44: { +#line 314 "rlparse.kl" + + (&redLel->user.expression)->expression = new Expression( (&rhs[0]->user.expression)->expression, + (&rhs[2]->user.term)->term, Expression::SubtractType ); + + +#line 4282 "rlparse.cpp" +} break; +case 45: { +#line 319 "rlparse.kl" + + (&redLel->user.expression)->expression = new Expression( (&rhs[0]->user.expression)->expression, + (&rhs[2]->user.term)->term, Expression::StrongSubtractType ); + + +#line 4291 "rlparse.cpp" +} break; +case 46: { +#line 324 "rlparse.kl" + + (&redLel->user.expression)->expression = new Expression( (&rhs[0]->user.term)->term ); + + +#line 4299 "rlparse.cpp" +} break; +case 47: { +#line 334 "rlparse.kl" + + (&redLel->user.term)->term = new Term( (&rhs[0]->user.term)->term, (&rhs[1]->user.factor_with_label)->factorWithAug ); + + +#line 4307 "rlparse.cpp" +} break; +case 48: { +#line 338 "rlparse.kl" + + (&redLel->user.term)->term = new Term( (&rhs[0]->user.term)->term, (&rhs[2]->user.factor_with_label)->factorWithAug ); + + +#line 4315 "rlparse.cpp" +} break; +case 49: { +#line 342 "rlparse.kl" + + (&redLel->user.term)->term = new Term( (&rhs[0]->user.term)->term, (&rhs[2]->user.factor_with_label)->factorWithAug, Term::RightStartType ); + + +#line 4323 "rlparse.cpp" +} break; +case 50: { +#line 346 "rlparse.kl" + + (&redLel->user.term)->term = new Term( (&rhs[0]->user.term)->term, (&rhs[2]->user.factor_with_label)->factorWithAug, Term::RightFinishType ); + + +#line 4331 "rlparse.cpp" +} break; +case 51: { +#line 350 "rlparse.kl" + + (&redLel->user.term)->term = new Term( (&rhs[0]->user.term)->term, + (&rhs[2]->user.factor_with_label)->factorWithAug, Term::LeftType ); + + +#line 4340 "rlparse.cpp" +} break; +case 52: { +#line 355 "rlparse.kl" + + (&redLel->user.term)->term = new Term( (&rhs[0]->user.factor_with_label)->factorWithAug ); + + +#line 4348 "rlparse.cpp" +} break; +case 53: { +#line 365 "rlparse.kl" + + /* Add the label to the list and pass the factor up. */ + (&rhs[2]->user.factor_with_label)->factorWithAug->labels.prepend( Label((&rhs[0]->user.token)->loc, (&rhs[0]->user.token)->data) ); + (&redLel->user.factor_with_label)->factorWithAug = (&rhs[2]->user.factor_with_label)->factorWithAug; + + +#line 4358 "rlparse.cpp" +} break; +case 54: { +#line 371 "rlparse.kl" + + (&redLel->user.factor_with_label)->factorWithAug = (&rhs[0]->user.factor_with_ep)->factorWithAug; + + +#line 4366 "rlparse.cpp" +} break; +case 55: { +#line 381 "rlparse.kl" + + /* Add the target to the list and return the factor object. */ + (&rhs[0]->user.factor_with_ep)->factorWithAug->epsilonLinks.append( EpsilonLink( (&rhs[1]->user.token)->loc, nameRef ) ); + (&redLel->user.factor_with_ep)->factorWithAug = (&rhs[0]->user.factor_with_ep)->factorWithAug; + + +#line 4376 "rlparse.cpp" +} break; +case 56: { +#line 387 "rlparse.kl" + + (&redLel->user.factor_with_ep)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4384 "rlparse.cpp" +} break; +case 57: { +#line 397 "rlparse.kl" + + /* Append the action to the factorWithAug, record the refernce from + * factorWithAug to the action and pass up the factorWithAug. */ + (&rhs[0]->user.factor_with_aug)->factorWithAug->actions.append( + ParserAction( (&rhs[1]->user.aug_type)->loc, (&rhs[1]->user.aug_type)->augType, 0, (&rhs[2]->user.action_ref)->action ) ); + (&redLel->user.factor_with_aug)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4396 "rlparse.cpp" +} break; +case 58: { +#line 405 "rlparse.kl" + + /* Append the named priority to the factorWithAug and pass it up. */ + (&rhs[0]->user.factor_with_aug)->factorWithAug->priorityAugs.append( + PriorityAug( (&rhs[1]->user.aug_type)->augType, pd->curDefPriorKey, (&rhs[2]->user.priority_aug)->priorityNum ) ); + (&redLel->user.factor_with_aug)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4407 "rlparse.cpp" +} break; +case 59: { +#line 412 "rlparse.kl" + + /* Append the priority using a default name. */ + (&rhs[0]->user.factor_with_aug)->factorWithAug->priorityAugs.append( + PriorityAug( (&rhs[1]->user.aug_type)->augType, (&rhs[3]->user.priority_name)->priorityName, (&rhs[5]->user.priority_aug)->priorityNum ) ); + (&redLel->user.factor_with_aug)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4418 "rlparse.cpp" +} break; +case 60: { +#line 419 "rlparse.kl" + + (&rhs[0]->user.factor_with_aug)->factorWithAug->conditions.append( ParserAction( (&rhs[1]->user.aug_type)->loc, + (&rhs[1]->user.aug_type)->augType, 0, (&rhs[2]->user.action_ref)->action ) ); + (&redLel->user.factor_with_aug)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4428 "rlparse.cpp" +} break; +case 61: { +#line 425 "rlparse.kl" + + /* Append the action, pass it up. */ + (&rhs[0]->user.factor_with_aug)->factorWithAug->actions.append( ParserAction( (&rhs[1]->user.aug_type)->loc, + (&rhs[1]->user.aug_type)->augType, 0, (&rhs[2]->user.action_ref)->action ) ); + (&redLel->user.factor_with_aug)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4439 "rlparse.cpp" +} break; +case 62: { +#line 432 "rlparse.kl" + + /* Append the action, pass it up. */ + (&rhs[0]->user.factor_with_aug)->factorWithAug->actions.append( ParserAction( (&rhs[1]->user.aug_type)->loc, + (&rhs[1]->user.aug_type)->augType, 0, (&rhs[2]->user.action_ref)->action ) ); + (&redLel->user.factor_with_aug)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4450 "rlparse.cpp" +} break; +case 63: { +#line 439 "rlparse.kl" + + /* Append the action, pass it up. */ + (&rhs[0]->user.factor_with_aug)->factorWithAug->actions.append( ParserAction( (&rhs[1]->user.aug_type)->loc, + (&rhs[1]->user.aug_type)->augType, 0, (&rhs[2]->user.action_ref)->action ) ); + (&redLel->user.factor_with_aug)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4461 "rlparse.cpp" +} break; +case 64: { +#line 446 "rlparse.kl" + + /* Append the action to the factorWithAug, record the refernce from + * factorWithAug to the action and pass up the factorWithAug. */ + (&rhs[0]->user.factor_with_aug)->factorWithAug->actions.append( ParserAction( (&rhs[1]->user.aug_type)->loc, + (&rhs[1]->user.aug_type)->augType, pd->curDefLocalErrKey, (&rhs[2]->user.action_ref)->action ) ); + (&redLel->user.factor_with_aug)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4473 "rlparse.cpp" +} break; +case 65: { +#line 454 "rlparse.kl" + + /* Append the action to the factorWithAug, record the refernce from + * factorWithAug to the action and pass up the factorWithAug. */ + (&rhs[0]->user.factor_with_aug)->factorWithAug->actions.append( ParserAction( (&rhs[1]->user.aug_type)->loc, + (&rhs[1]->user.aug_type)->augType, pd->curDefLocalErrKey, (&rhs[2]->user.action_ref)->action ) ); + (&redLel->user.factor_with_aug)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4485 "rlparse.cpp" +} break; +case 66: { +#line 462 "rlparse.kl" + + /* Append the action to the factorWithAug, record the refernce from + * factorWithAug to the action and pass up the factorWithAug. */ + (&rhs[0]->user.factor_with_aug)->factorWithAug->actions.append( ParserAction( (&rhs[1]->user.aug_type)->loc, + (&rhs[1]->user.aug_type)->augType, (&rhs[3]->user.local_err_name)->error_name, (&rhs[5]->user.action_ref)->action ) ); + (&redLel->user.factor_with_aug)->factorWithAug = (&rhs[0]->user.factor_with_aug)->factorWithAug; + + +#line 4497 "rlparse.cpp" +} break; +case 67: { +#line 470 "rlparse.kl" + + (&redLel->user.factor_with_aug)->factorWithAug = new FactorWithAug( (&rhs[0]->user.factor_with_rep)->factorWithRep ); + + +#line 4505 "rlparse.cpp" +} break; +case 68: { +#line 483 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_finish; + +#line 4511 "rlparse.cpp" +} break; +case 69: { +#line 484 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_leave; + +#line 4517 "rlparse.cpp" +} break; +case 70: { +#line 485 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all; + +#line 4523 "rlparse.cpp" +} break; +case 71: { +#line 486 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start; + +#line 4529 "rlparse.cpp" +} break; +case 72: { +#line 491 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start; + +#line 4535 "rlparse.cpp" +} break; +case 73: { +#line 492 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start; + +#line 4541 "rlparse.cpp" +} break; +case 74: { +#line 493 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all; + +#line 4547 "rlparse.cpp" +} break; +case 75: { +#line 494 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all; + +#line 4553 "rlparse.cpp" +} break; +case 76: { +#line 495 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_leave; + +#line 4559 "rlparse.cpp" +} break; +case 77: { +#line 496 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_leave; + +#line 4565 "rlparse.cpp" +} break; +case 78: { +#line 497 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all; + +#line 4571 "rlparse.cpp" +} break; +case 79: { +#line 506 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start_to_state; + +#line 4577 "rlparse.cpp" +} break; +case 80: { +#line 508 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start_to_state; + +#line 4583 "rlparse.cpp" +} break; +case 81: { +#line 511 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_start_to_state; + +#line 4589 "rlparse.cpp" +} break; +case 82: { +#line 513 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_start_to_state; + +#line 4595 "rlparse.cpp" +} break; +case 83: { +#line 516 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all_to_state; + +#line 4601 "rlparse.cpp" +} break; +case 84: { +#line 518 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all_to_state; + +#line 4607 "rlparse.cpp" +} break; +case 85: { +#line 521 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_final_to_state; + +#line 4613 "rlparse.cpp" +} break; +case 86: { +#line 523 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_final_to_state; + +#line 4619 "rlparse.cpp" +} break; +case 87: { +#line 526 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_final_to_state; + +#line 4625 "rlparse.cpp" +} break; +case 88: { +#line 528 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_final_to_state; + +#line 4631 "rlparse.cpp" +} break; +case 89: { +#line 531 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_middle_to_state; + +#line 4637 "rlparse.cpp" +} break; +case 90: { +#line 533 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_middle_to_state; + +#line 4643 "rlparse.cpp" +} break; +case 91: { +#line 542 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start_from_state; + +#line 4649 "rlparse.cpp" +} break; +case 92: { +#line 544 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start_from_state; + +#line 4655 "rlparse.cpp" +} break; +case 93: { +#line 547 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_start_from_state; + +#line 4661 "rlparse.cpp" +} break; +case 94: { +#line 549 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_start_from_state; + +#line 4667 "rlparse.cpp" +} break; +case 95: { +#line 552 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all_from_state; + +#line 4673 "rlparse.cpp" +} break; +case 96: { +#line 554 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all_from_state; + +#line 4679 "rlparse.cpp" +} break; +case 97: { +#line 557 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_final_from_state; + +#line 4685 "rlparse.cpp" +} break; +case 98: { +#line 559 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_final_from_state; + +#line 4691 "rlparse.cpp" +} break; +case 99: { +#line 562 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_final_from_state; + +#line 4697 "rlparse.cpp" +} break; +case 100: { +#line 564 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_final_from_state; + +#line 4703 "rlparse.cpp" +} break; +case 101: { +#line 567 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_middle_from_state; + +#line 4709 "rlparse.cpp" +} break; +case 102: { +#line 569 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_middle_from_state; + +#line 4715 "rlparse.cpp" +} break; +case 103: { +#line 578 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start_eof; + +#line 4721 "rlparse.cpp" +} break; +case 104: { +#line 580 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start_eof; + +#line 4727 "rlparse.cpp" +} break; +case 105: { +#line 583 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_start_eof; + +#line 4733 "rlparse.cpp" +} break; +case 106: { +#line 585 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_start_eof; + +#line 4739 "rlparse.cpp" +} break; +case 107: { +#line 588 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all_eof; + +#line 4745 "rlparse.cpp" +} break; +case 108: { +#line 590 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all_eof; + +#line 4751 "rlparse.cpp" +} break; +case 109: { +#line 593 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_final_eof; + +#line 4757 "rlparse.cpp" +} break; +case 110: { +#line 595 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_final_eof; + +#line 4763 "rlparse.cpp" +} break; +case 111: { +#line 598 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_final_eof; + +#line 4769 "rlparse.cpp" +} break; +case 112: { +#line 600 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_final_eof; + +#line 4775 "rlparse.cpp" +} break; +case 113: { +#line 603 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_middle_eof; + +#line 4781 "rlparse.cpp" +} break; +case 114: { +#line 605 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_middle_eof; + +#line 4787 "rlparse.cpp" +} break; +case 115: { +#line 614 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start_gbl_error; + +#line 4793 "rlparse.cpp" +} break; +case 116: { +#line 616 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start_gbl_error; + +#line 4799 "rlparse.cpp" +} break; +case 117: { +#line 619 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_start_gbl_error; + +#line 4805 "rlparse.cpp" +} break; +case 118: { +#line 621 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_start_gbl_error; + +#line 4811 "rlparse.cpp" +} break; +case 119: { +#line 624 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all_gbl_error; + +#line 4817 "rlparse.cpp" +} break; +case 120: { +#line 626 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all_gbl_error; + +#line 4823 "rlparse.cpp" +} break; +case 121: { +#line 629 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_final_gbl_error; + +#line 4829 "rlparse.cpp" +} break; +case 122: { +#line 631 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_final_gbl_error; + +#line 4835 "rlparse.cpp" +} break; +case 123: { +#line 634 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_final_gbl_error; + +#line 4841 "rlparse.cpp" +} break; +case 124: { +#line 636 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_final_gbl_error; + +#line 4847 "rlparse.cpp" +} break; +case 125: { +#line 639 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_middle_gbl_error; + +#line 4853 "rlparse.cpp" +} break; +case 126: { +#line 641 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_middle_gbl_error; + +#line 4859 "rlparse.cpp" +} break; +case 127: { +#line 651 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start_local_error; + +#line 4865 "rlparse.cpp" +} break; +case 128: { +#line 653 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_start_local_error; + +#line 4871 "rlparse.cpp" +} break; +case 129: { +#line 656 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_start_local_error; + +#line 4877 "rlparse.cpp" +} break; +case 130: { +#line 658 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_start_local_error; + +#line 4883 "rlparse.cpp" +} break; +case 131: { +#line 661 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all_local_error; + +#line 4889 "rlparse.cpp" +} break; +case 132: { +#line 663 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_all_local_error; + +#line 4895 "rlparse.cpp" +} break; +case 133: { +#line 666 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_final_local_error; + +#line 4901 "rlparse.cpp" +} break; +case 134: { +#line 668 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_final_local_error; + +#line 4907 "rlparse.cpp" +} break; +case 135: { +#line 671 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_final_local_error; + +#line 4913 "rlparse.cpp" +} break; +case 136: { +#line 673 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_not_final_local_error; + +#line 4919 "rlparse.cpp" +} break; +case 137: { +#line 676 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_middle_local_error; + +#line 4925 "rlparse.cpp" +} break; +case 138: { +#line 678 "rlparse.kl" + (&redLel->user.aug_type)->loc = (&rhs[0]->user.token)->loc; (&redLel->user.aug_type)->augType = at_middle_local_error; + +#line 4931 "rlparse.cpp" +} break; +case 139: { +#line 691 "rlparse.kl" + (&redLel->user.action_ref)->action = (&rhs[0]->user.action_ref)->action; + +#line 4937 "rlparse.cpp" +} break; +case 140: { +#line 692 "rlparse.kl" + (&redLel->user.action_ref)->action = (&rhs[1]->user.action_ref)->action; + +#line 4943 "rlparse.cpp" +} break; +case 141: { +#line 693 "rlparse.kl" + (&redLel->user.action_ref)->action = (&rhs[0]->user.action_ref)->action; + +#line 4949 "rlparse.cpp" +} break; +case 142: { +#line 698 "rlparse.kl" + + /* Set the name in the actionDict. */ + Action *action = pd->actionDict.find( (&rhs[0]->user.token)->data ); + if ( action != 0 ) { + /* Pass up the action element */ + (&redLel->user.action_ref)->action = action; + } + else { + /* Will recover by returning null as the action. */ + error((&rhs[0]->user.token)->loc) << "action lookup of \"" << (&rhs[0]->user.token)->data << "\" failed" << endl; + (&redLel->user.action_ref)->action = 0; + } + + +#line 4967 "rlparse.cpp" +} break; +case 143: { +#line 715 "rlparse.kl" + + /* Create the action, add it to the list and pass up. */ + Action *newAction = new Action( (&rhs[0]->user.token)->loc, 0, (&rhs[1]->user.inline_list)->inlineList, pd->nextCondId++ ); + pd->actionList.append( newAction ); + (&redLel->user.action_ref)->action = newAction; + + +#line 4978 "rlparse.cpp" +} break; +case 144: { +#line 730 "rlparse.kl" + + // Lookup/create the priority key. + PriorDictEl *priorDictEl; + if ( pd->priorDict.insert( (&rhs[0]->user.token)->data, pd->nextPriorKey, &priorDictEl ) ) + pd->nextPriorKey += 1; + + // Use the inserted/found priority key. + (&redLel->user.priority_name)->priorityName = priorDictEl->value; + + +#line 4992 "rlparse.cpp" +} break; +case 145: { +#line 747 "rlparse.kl" + + // Convert the priority number to a long. Check for overflow. + errno = 0; + //cerr << "PRIOR AUG: " << $1->token.data << endl; + long aug = strtol( (&rhs[0]->user.token_type)->token.data, 0, 10 ); + if ( errno == ERANGE && aug == LONG_MAX ) { + /* Priority number too large. Recover by setting the priority to 0. */ + error((&rhs[0]->user.token_type)->token.loc) << "priority number " << (&rhs[0]->user.token_type)->token.data << + " overflows" << endl; + (&redLel->user.priority_aug)->priorityNum = 0; + } + else if ( errno == ERANGE && aug == LONG_MIN ) { + /* Priority number too large in the neg. Recover by using 0. */ + error((&rhs[0]->user.token_type)->token.loc) << "priority number " << (&rhs[0]->user.token_type)->token.data << + " underflows" << endl; + (&redLel->user.priority_aug)->priorityNum = 0; + } + else { + /* No overflow or underflow. */ + (&redLel->user.priority_aug)->priorityNum = aug; + } + + +#line 5019 "rlparse.cpp" +} break; +case 146: { +#line 773 "rlparse.kl" + + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + + +#line 5027 "rlparse.cpp" +} break; +case 147: { +#line 777 "rlparse.kl" + + (&redLel->user.token_type)->token.set( "+", 1 ); + (&redLel->user.token_type)->token.loc = (&rhs[0]->user.token)->loc; + (&redLel->user.token_type)->token.append( *(&rhs[1]->user.token) ); + + +#line 5037 "rlparse.cpp" +} break; +case 148: { +#line 783 "rlparse.kl" + + (&redLel->user.token_type)->token.set( "-", 1 ); + (&redLel->user.token_type)->token.loc = (&rhs[0]->user.token)->loc; + (&redLel->user.token_type)->token.append( *(&rhs[1]->user.token) ); + + +#line 5047 "rlparse.cpp" +} break; +case 149: { +#line 795 "rlparse.kl" + + /* Lookup/create the priority key. */ + LocalErrDictEl *localErrDictEl; + if ( pd->localErrDict.insert( (&rhs[0]->user.token)->data, pd->nextLocalErrKey, &localErrDictEl ) ) + pd->nextLocalErrKey += 1; + + /* Use the inserted/found priority key. */ + (&redLel->user.local_err_name)->error_name = localErrDictEl->value; + + +#line 5061 "rlparse.cpp" +} break; +case 150: { +#line 816 "rlparse.kl" + + (&redLel->user.factor_with_rep)->factorWithRep = new FactorWithRep( (&rhs[1]->user.token)->loc, (&rhs[0]->user.factor_with_rep)->factorWithRep, + 0, 0, FactorWithRep::StarType ); + + +#line 5070 "rlparse.cpp" +} break; +case 151: { +#line 821 "rlparse.kl" + + (&redLel->user.factor_with_rep)->factorWithRep = new FactorWithRep( (&rhs[1]->user.token)->loc, (&rhs[0]->user.factor_with_rep)->factorWithRep, + 0, 0, FactorWithRep::StarStarType ); + + +#line 5079 "rlparse.cpp" +} break; +case 152: { +#line 826 "rlparse.kl" + + (&redLel->user.factor_with_rep)->factorWithRep = new FactorWithRep( (&rhs[1]->user.token)->loc, (&rhs[0]->user.factor_with_rep)->factorWithRep, + 0, 0, FactorWithRep::OptionalType ); + + +#line 5088 "rlparse.cpp" +} break; +case 153: { +#line 831 "rlparse.kl" + + (&redLel->user.factor_with_rep)->factorWithRep = new FactorWithRep( (&rhs[1]->user.token)->loc, (&rhs[0]->user.factor_with_rep)->factorWithRep, + 0, 0, FactorWithRep::PlusType ); + + +#line 5097 "rlparse.cpp" +} break; +case 154: { +#line 836 "rlparse.kl" + + (&redLel->user.factor_with_rep)->factorWithRep = new FactorWithRep( (&rhs[1]->user.token)->loc, (&rhs[0]->user.factor_with_rep)->factorWithRep, + (&rhs[2]->user.factor_rep_num)->rep, 0, FactorWithRep::ExactType ); + + +#line 5106 "rlparse.cpp" +} break; +case 155: { +#line 841 "rlparse.kl" + + (&redLel->user.factor_with_rep)->factorWithRep = new FactorWithRep( (&rhs[1]->user.token)->loc, (&rhs[0]->user.factor_with_rep)->factorWithRep, + 0, (&rhs[3]->user.factor_rep_num)->rep, FactorWithRep::MaxType ); + + +#line 5115 "rlparse.cpp" +} break; +case 156: { +#line 846 "rlparse.kl" + + (&redLel->user.factor_with_rep)->factorWithRep = new FactorWithRep( (&rhs[1]->user.token)->loc, (&rhs[0]->user.factor_with_rep)->factorWithRep, + (&rhs[2]->user.factor_rep_num)->rep, 0, FactorWithRep::MinType ); + + +#line 5124 "rlparse.cpp" +} break; +case 157: { +#line 851 "rlparse.kl" + + (&redLel->user.factor_with_rep)->factorWithRep = new FactorWithRep( (&rhs[1]->user.token)->loc, (&rhs[0]->user.factor_with_rep)->factorWithRep, + (&rhs[2]->user.factor_rep_num)->rep, (&rhs[4]->user.factor_rep_num)->rep, FactorWithRep::RangeType ); + + +#line 5133 "rlparse.cpp" +} break; +case 158: { +#line 856 "rlparse.kl" + + (&redLel->user.factor_with_rep)->factorWithRep = new FactorWithRep( (&rhs[0]->user.factor_with_neg)->factorWithNeg ); + + +#line 5141 "rlparse.cpp" +} break; +case 159: { +#line 866 "rlparse.kl" + + // Convert the priority number to a long. Check for overflow. + errno = 0; + long rep = strtol( (&rhs[0]->user.token)->data, 0, 10 ); + if ( errno == ERANGE && rep == LONG_MAX ) { + // Repetition too large. Recover by returing repetition 1. */ + error((&rhs[0]->user.token)->loc) << "repetition number " << (&rhs[0]->user.token)->data << " overflows" << endl; + (&redLel->user.factor_rep_num)->rep = 1; + } + else { + // Cannot be negative, so no overflow. + (&redLel->user.factor_rep_num)->rep = rep; + } + + +#line 5160 "rlparse.cpp" +} break; +case 160: { +#line 892 "rlparse.kl" + + (&redLel->user.factor_with_neg)->factorWithNeg = new FactorWithNeg( (&rhs[0]->user.token)->loc, + (&rhs[1]->user.factor_with_neg)->factorWithNeg, FactorWithNeg::NegateType ); + + +#line 5169 "rlparse.cpp" +} break; +case 161: { +#line 897 "rlparse.kl" + + (&redLel->user.factor_with_neg)->factorWithNeg = new FactorWithNeg( (&rhs[0]->user.token)->loc, + (&rhs[1]->user.factor_with_neg)->factorWithNeg, FactorWithNeg::CharNegateType ); + + +#line 5178 "rlparse.cpp" +} break; +case 162: { +#line 902 "rlparse.kl" + + (&redLel->user.factor_with_neg)->factorWithNeg = new FactorWithNeg( (&rhs[0]->user.factor)->factor ); + + +#line 5186 "rlparse.cpp" +} break; +case 163: { +#line 912 "rlparse.kl" + + /* Create a new factor node going to a concat literal. */ + (&redLel->user.factor)->factor = new Factor( new Literal( *(&rhs[0]->user.token), Literal::LitString ) ); + + +#line 5195 "rlparse.cpp" +} break; +case 164: { +#line 917 "rlparse.kl" + + /* Create a new factor node going to a literal number. */ + (&redLel->user.factor)->factor = new Factor( new Literal( (&rhs[0]->user.token_type)->token, Literal::Number ) ); + + +#line 5204 "rlparse.cpp" +} break; +case 165: { +#line 922 "rlparse.kl" + + /* Find the named graph. */ + GraphDictEl *gdNode = pd->graphDict.find( (&rhs[0]->user.token)->data ); + if ( gdNode == 0 ) { + /* Recover by returning null as the factor node. */ + error((&rhs[0]->user.token)->loc) << "graph lookup of \"" << (&rhs[0]->user.token)->data << "\" failed" << endl; + (&redLel->user.factor)->factor = 0; + } + else if ( gdNode->isInstance ) { + /* Recover by retuning null as the factor node. */ + error((&rhs[0]->user.token)->loc) << "references to graph instantiations not allowed " + "in expressions" << endl; + (&redLel->user.factor)->factor = 0; + } + else { + /* Create a factor node that is a lookup of an expression. */ + (&redLel->user.factor)->factor = new Factor( (&rhs[0]->user.token)->loc, gdNode->value ); + } + + +#line 5228 "rlparse.cpp" +} break; +case 166: { +#line 942 "rlparse.kl" + + /* Create a new factor node going to an OR expression. */ + (&redLel->user.factor)->factor = new Factor( new ReItem( (&rhs[0]->user.token)->loc, (&rhs[1]->user.regular_expr_or_data)->reOrBlock, ReItem::OrBlock ) ); + + +#line 5237 "rlparse.cpp" +} break; +case 167: { +#line 947 "rlparse.kl" + + /* Create a new factor node going to a negated OR expression. */ + (&redLel->user.factor)->factor = new Factor( new ReItem( (&rhs[0]->user.token)->loc, (&rhs[1]->user.regular_expr_or_data)->reOrBlock, ReItem::NegOrBlock ) ); + + +#line 5246 "rlparse.cpp" +} break; +case 168: { +#line 952 "rlparse.kl" + + if ( (&rhs[2]->user.token)->length > 1 ) { + for ( char *p = (&rhs[2]->user.token)->data; *p != 0; p++ ) { + if ( *p == 'i' ) + (&rhs[1]->user.regular_expr)->regExpr->caseInsensitive = true; + } + } + + /* Create a new factor node going to a regular exp. */ + (&redLel->user.factor)->factor = new Factor( (&rhs[1]->user.regular_expr)->regExpr ); + + +#line 5262 "rlparse.cpp" +} break; +case 169: { +#line 964 "rlparse.kl" + + /* Create a new factor node going to a range. */ + (&redLel->user.factor)->factor = new Factor( new Range( (&rhs[0]->user.range_lit)->literal, (&rhs[2]->user.range_lit)->literal ) ); + + +#line 5271 "rlparse.cpp" +} break; +case 170: { +#line 969 "rlparse.kl" + + /* Create a new factor going to a parenthesized join. */ + (&redLel->user.factor)->factor = new Factor( (&rhs[1]->user.join)->join ); + + +#line 5280 "rlparse.cpp" +} break; +case 171: { +#line 981 "rlparse.kl" + + /* Range literas must have only one char. We restrict this in the parse tree. */ + (&redLel->user.range_lit)->literal = new Literal( *(&rhs[0]->user.token), Literal::LitString ); + + +#line 5289 "rlparse.cpp" +} break; +case 172: { +#line 986 "rlparse.kl" + + /* Create a new literal number. */ + (&redLel->user.range_lit)->literal = new Literal( (&rhs[0]->user.token_type)->token, Literal::Number ); + + +#line 5298 "rlparse.cpp" +} break; +case 173: { +#line 995 "rlparse.kl" + + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + + +#line 5306 "rlparse.cpp" +} break; +case 174: { +#line 999 "rlparse.kl" + + (&redLel->user.token_type)->token.set( "-", 1 ); + (&redLel->user.token_type)->token.loc = (&rhs[0]->user.token)->loc; + (&redLel->user.token_type)->token.append( *(&rhs[1]->user.token) ); + + +#line 5316 "rlparse.cpp" +} break; +case 175: { +#line 1005 "rlparse.kl" + + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + + +#line 5324 "rlparse.cpp" +} break; +case 176: { +#line 1020 "rlparse.kl" + + /* An optimization to lessen the tree size. If a non-starred char is + * directly under the left side on the right and the right side is + * another non-starred char then paste them together and return the + * left side. Otherwise just put the two under a new reg exp node. */ + if ( (&rhs[1]->user.regular_expr_item)->reItem->type == ReItem::Data && !(&rhs[1]->user.regular_expr_item)->reItem->star && + (&rhs[0]->user.regular_expr)->regExpr->type == RegExpr::RecurseItem && + (&rhs[0]->user.regular_expr)->regExpr->item->type == ReItem::Data && !(&rhs[0]->user.regular_expr)->regExpr->item->star ) + { + /* Append the right side to the right side of the left and toss the + * right side. */ + (&rhs[0]->user.regular_expr)->regExpr->item->token.append( (&rhs[1]->user.regular_expr_item)->reItem->token ); + delete (&rhs[1]->user.regular_expr_item)->reItem; + (&redLel->user.regular_expr)->regExpr = (&rhs[0]->user.regular_expr)->regExpr; + } + else { + (&redLel->user.regular_expr)->regExpr = new RegExpr( (&rhs[0]->user.regular_expr)->regExpr, (&rhs[1]->user.regular_expr_item)->reItem ); + } + + +#line 5348 "rlparse.cpp" +} break; +case 177: { +#line 1040 "rlparse.kl" + + /* Can't optimize the tree. */ + (&redLel->user.regular_expr)->regExpr = new RegExpr(); + + +#line 5357 "rlparse.cpp" +} break; +case 178: { +#line 1052 "rlparse.kl" + + (&rhs[0]->user.regular_expr_char)->reItem->star = true; + (&redLel->user.regular_expr_item)->reItem = (&rhs[0]->user.regular_expr_char)->reItem; + + +#line 5366 "rlparse.cpp" +} break; +case 179: { +#line 1057 "rlparse.kl" + + (&redLel->user.regular_expr_item)->reItem = (&rhs[0]->user.regular_expr_char)->reItem; + + +#line 5374 "rlparse.cpp" +} break; +case 180: { +#line 1069 "rlparse.kl" + + (&redLel->user.regular_expr_char)->reItem = new ReItem( (&rhs[0]->user.token)->loc, (&rhs[1]->user.regular_expr_or_data)->reOrBlock, ReItem::OrBlock ); + + +#line 5382 "rlparse.cpp" +} break; +case 181: { +#line 1073 "rlparse.kl" + + (&redLel->user.regular_expr_char)->reItem = new ReItem( (&rhs[0]->user.token)->loc, (&rhs[1]->user.regular_expr_or_data)->reOrBlock, ReItem::NegOrBlock ); + + +#line 5390 "rlparse.cpp" +} break; +case 182: { +#line 1077 "rlparse.kl" + + (&redLel->user.regular_expr_char)->reItem = new ReItem( (&rhs[0]->user.token)->loc, ReItem::Dot ); + + +#line 5398 "rlparse.cpp" +} break; +case 183: { +#line 1081 "rlparse.kl" + + (&redLel->user.regular_expr_char)->reItem = new ReItem( (&rhs[0]->user.token)->loc, *(&rhs[0]->user.token) ); + + +#line 5406 "rlparse.cpp" +} break; +case 184: { +#line 1093 "rlparse.kl" + + /* An optimization to lessen the tree size. If an or char is directly + * under the left side on the right and the right side is another or + * char then paste them together and return the left side. Otherwise + * just put the two under a new or data node. */ + if ( (&rhs[1]->user.regular_expr_or_char)->reOrItem->type == ReOrItem::Data && + (&rhs[0]->user.regular_expr_or_data)->reOrBlock->type == ReOrBlock::RecurseItem && + (&rhs[0]->user.regular_expr_or_data)->reOrBlock->item->type == ReOrItem::Data ) + { + /* Append the right side to right side of the left and toss the + * right side. */ + (&rhs[0]->user.regular_expr_or_data)->reOrBlock->item->token.append( (&rhs[1]->user.regular_expr_or_char)->reOrItem->token ); + delete (&rhs[1]->user.regular_expr_or_char)->reOrItem; + (&redLel->user.regular_expr_or_data)->reOrBlock = (&rhs[0]->user.regular_expr_or_data)->reOrBlock; + } + else { + /* Can't optimize, put the left and right under a new node. */ + (&redLel->user.regular_expr_or_data)->reOrBlock = new ReOrBlock( (&rhs[0]->user.regular_expr_or_data)->reOrBlock, (&rhs[1]->user.regular_expr_or_char)->reOrItem ); + } + + +#line 5431 "rlparse.cpp" +} break; +case 185: { +#line 1114 "rlparse.kl" + + (&redLel->user.regular_expr_or_data)->reOrBlock = new ReOrBlock(); + + +#line 5439 "rlparse.cpp" +} break; +case 186: { +#line 1126 "rlparse.kl" + + (&redLel->user.regular_expr_or_char)->reOrItem = new ReOrItem( (&rhs[0]->user.token)->loc, *(&rhs[0]->user.token) ); + + +#line 5447 "rlparse.cpp" +} break; +case 187: { +#line 1130 "rlparse.kl" + + (&redLel->user.regular_expr_or_char)->reOrItem = new ReOrItem( (&rhs[1]->user.token)->loc, (&rhs[0]->user.token)->data[0], (&rhs[2]->user.token)->data[0] ); + + +#line 5455 "rlparse.cpp" +} break; +case 188: { +#line 1147 "rlparse.kl" + + /* Append the item to the list, return the list. */ + (&redLel->user.inline_list)->inlineList = (&rhs[0]->user.inline_list)->inlineList; + (&redLel->user.inline_list)->inlineList->append( (&rhs[1]->user.inline_item)->inlineItem ); + + +#line 5465 "rlparse.cpp" +} break; +case 189: { +#line 1154 "rlparse.kl" + + /* Start with empty list. */ + (&redLel->user.inline_list)->inlineList = new InlineList; + + +#line 5474 "rlparse.cpp" +} break; +case 190: { +#line 1169 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token_type)->token.loc, (&rhs[0]->user.token_type)->token.data, InlineItem::Text ); + + +#line 5482 "rlparse.cpp" +} break; +case 191: { +#line 1175 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token_type)->token.loc, (&rhs[0]->user.token_type)->token.data, InlineItem::Text ); + + +#line 5490 "rlparse.cpp" +} break; +case 192: { +#line 1181 "rlparse.kl" + + /* Pass the inline item up. */ + (&redLel->user.inline_item)->inlineItem = (&rhs[0]->user.inline_item)->inlineItem; + + +#line 5499 "rlparse.cpp" +} break; +case 193: { +#line 1188 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5505 "rlparse.cpp" +} break; +case 194: { +#line 1189 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5511 "rlparse.cpp" +} break; +case 195: { +#line 1190 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5517 "rlparse.cpp" +} break; +case 196: { +#line 1191 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5523 "rlparse.cpp" +} break; +case 197: { +#line 1192 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5529 "rlparse.cpp" +} break; +case 198: { +#line 1193 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5535 "rlparse.cpp" +} break; +case 199: { +#line 1197 "rlparse.kl" + + /* Pass up interpreted items of inline expressions. */ + (&redLel->user.inline_item)->inlineItem = (&rhs[0]->user.inline_item)->inlineItem; + + +#line 5544 "rlparse.cpp" +} break; +case 200: { +#line 1202 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::Hold ); + + +#line 5552 "rlparse.cpp" +} break; +case 201: { +#line 1206 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::Exec ); + (&redLel->user.inline_item)->inlineItem->children = (&rhs[1]->user.inline_list)->inlineList; + + +#line 5561 "rlparse.cpp" +} break; +case 202: { +#line 1211 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, + new NameRef(nameRef), InlineItem::Goto ); + + +#line 5570 "rlparse.cpp" +} break; +case 203: { +#line 1216 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::GotoExpr ); + (&redLel->user.inline_item)->inlineItem->children = (&rhs[2]->user.inline_list)->inlineList; + + +#line 5579 "rlparse.cpp" +} break; +case 204: { +#line 1221 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, new NameRef(nameRef), InlineItem::Next ); + + +#line 5587 "rlparse.cpp" +} break; +case 205: { +#line 1225 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::NextExpr ); + (&redLel->user.inline_item)->inlineItem->children = (&rhs[2]->user.inline_list)->inlineList; + + +#line 5596 "rlparse.cpp" +} break; +case 206: { +#line 1230 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, new NameRef(nameRef), InlineItem::Call ); + + +#line 5604 "rlparse.cpp" +} break; +case 207: { +#line 1234 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::CallExpr ); + (&redLel->user.inline_item)->inlineItem->children = (&rhs[2]->user.inline_list)->inlineList; + + +#line 5613 "rlparse.cpp" +} break; +case 208: { +#line 1239 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::Ret ); + + +#line 5621 "rlparse.cpp" +} break; +case 209: { +#line 1243 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::Break ); + + +#line 5629 "rlparse.cpp" +} break; +case 210: { +#line 1251 "rlparse.kl" + + (&redLel->user.inline_list)->inlineList = (&rhs[0]->user.inline_list)->inlineList; + (&redLel->user.inline_list)->inlineList->append( (&rhs[1]->user.inline_item)->inlineItem ); + + +#line 5638 "rlparse.cpp" +} break; +case 211: { +#line 1256 "rlparse.kl" + + /* Init the list used for this expr. */ + (&redLel->user.inline_list)->inlineList = new InlineList; + + +#line 5647 "rlparse.cpp" +} break; +case 212: { +#line 1265 "rlparse.kl" + + /* Return a text segment. */ + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token_type)->token.loc, (&rhs[0]->user.token_type)->token.data, InlineItem::Text ); + + +#line 5656 "rlparse.cpp" +} break; +case 213: { +#line 1271 "rlparse.kl" + + /* Return a text segment, must heap alloc the text. */ + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token_type)->token.loc, (&rhs[0]->user.token_type)->token.data, InlineItem::Text ); + + +#line 5665 "rlparse.cpp" +} break; +case 214: { +#line 1277 "rlparse.kl" + + /* Pass the inline item up. */ + (&redLel->user.inline_item)->inlineItem = (&rhs[0]->user.inline_item)->inlineItem; + + +#line 5674 "rlparse.cpp" +} break; +case 227: { +#line 1307 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::PChar ); + + +#line 5682 "rlparse.cpp" +} break; +case 228: { +#line 1312 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::Char ); + + +#line 5690 "rlparse.cpp" +} break; +case 229: { +#line 1317 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::Curs ); + + +#line 5698 "rlparse.cpp" +} break; +case 230: { +#line 1322 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, InlineItem::Targs ); + + +#line 5706 "rlparse.cpp" +} break; +case 231: { +#line 1327 "rlparse.kl" + + (&redLel->user.inline_item)->inlineItem = new InlineItem( (&rhs[0]->user.token)->loc, + new NameRef(nameRef), InlineItem::Entry ); + + +#line 5715 "rlparse.cpp" +} break; +case 233: { +#line 1338 "rlparse.kl" + + nameRef.empty(); + + +#line 5723 "rlparse.cpp" +} break; +case 235: { +#line 1348 "rlparse.kl" + + /* Insert an initial null pointer val to indicate the existence of the + * initial name seperator. */ + nameRef.setAs( 0 ); + + +#line 5733 "rlparse.cpp" +} break; +case 236: { +#line 1354 "rlparse.kl" + + nameRef.empty(); + + +#line 5741 "rlparse.cpp" +} break; +case 237: { +#line 1361 "rlparse.kl" + + nameRef.append( (&rhs[2]->user.token)->data ); + + +#line 5749 "rlparse.cpp" +} break; +case 238: { +#line 1366 "rlparse.kl" + + nameRef.append( (&rhs[0]->user.token)->data ); + + +#line 5757 "rlparse.cpp" +} break; +} + } +} + + if ( lel->child != 0 ) { + struct Parser_LangEl *first = lel->child; + struct Parser_LangEl *child = lel->child; + numNodes -= 1; + lel->child = 0; + while ( child->next != 0 ) { + child = child->next; + numNodes -= 1; + } + child->next = pool; + pool = first; + } + } + +hit_final: + if ( sp > 0 ) { + /* Figure out which place to return to. */ + if ( cmStack[sp-1]->next == lel ) { + lel = cmStack[--sp]; + goto final_reverse; + } + else { + lel = cmStack[--sp]; + goto final_upwards; + } + } + + lastFinal = lel; + free( cmStack ); + } + } + } + + if ( *action & 0x2 ) { + int fssRed = *action >> 2; + int reduction = Parser_fssProdIdIndex[fssRed]; + struct Parser_LangEl *redLel; + if ( pool == 0 ) { + if ( freshPos == 8128 ) { + freshEl = (struct Parser_LangEl*) malloc( + sizeof(struct Parser_LangEl)*8128); + #ifdef LOG_ACTIONS + cerr << "allocating 8128 LangEls" << endl; + #endif + freshPos = 0; + } + redLel = freshEl + freshPos++; + } + else { + redLel = pool; + pool = pool->next; + } + numNodes += 1; + redLel->type = Parser_prodLhsIds[reduction]; + redLel->reduction = reduction; + redLel->child = 0; + redLel->next = 0; + redLel->retry = (lel->retry << 16); + lel->retry &= 0xffff0000; + + rhsLen = Parser_fssProdLengths[fssRed]; + if ( rhsLen > 0 ) { + int r; + for ( r = rhsLen-1; r > 0; r-- ) { + rhs[r] = stackTop; + stackTop = stackTop->next; + } + rhs[0] = stackTop; + stackTop = stackTop->next; + rhs[0]->next = 0; + } +switch ( reduction ) { +case 215: { +#line 1284 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5839 "rlparse.cpp" +} break; +case 216: { +#line 1285 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5845 "rlparse.cpp" +} break; +case 217: { +#line 1286 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5851 "rlparse.cpp" +} break; +case 218: { +#line 1287 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5857 "rlparse.cpp" +} break; +case 219: { +#line 1288 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5863 "rlparse.cpp" +} break; +case 220: { +#line 1289 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5869 "rlparse.cpp" +} break; +case 221: { +#line 1290 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5875 "rlparse.cpp" +} break; +case 222: { +#line 1297 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5881 "rlparse.cpp" +} break; +case 223: { +#line 1298 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5887 "rlparse.cpp" +} break; +case 224: { +#line 1299 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5893 "rlparse.cpp" +} break; +case 225: { +#line 1300 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5899 "rlparse.cpp" +} break; +case 226: { +#line 1301 "rlparse.kl" + (&redLel->user.token_type)->token = *(&rhs[0]->user.token); + +#line 5905 "rlparse.cpp" +} break; +} + #ifdef LOG_ACTIONS + cerr << "reduced: " + << Parser_prodNames[reduction] + << " rhsLen: " << rhsLen; + #endif + if ( action[1] == 0 ) + redLel->retry = 0; + else { + redLel->retry += 0x10000; + numRetry += 1; + #ifdef LOG_ACTIONS + cerr << " retry: " << redLel; + #endif + } + + #ifdef LOG_ACTIONS + cerr << endl; + #endif + + if ( rhsLen == 0 ) { + redLel->file = lel->file; + redLel->line = lel->line; + targState = curs; + } + else { + redLel->child = rhs[rhsLen-1]; + redLel->file = rhs[0]->file; + redLel->line = rhs[0]->line; + targState = rhs[0]->state; + } + + if ( induceReject ) { + #ifdef LOG_ACTIONS + cerr << "error induced during reduction of " << + Parser_lelNames[redLel->type] << endl; + #endif + redLel->state = curs; + redLel->next = stackTop; + stackTop = redLel; + curs = targState; + goto parseError; + } + else { + redLel->next = input; + input = redLel; + } + } + + + curs = targState; + goto again; + +parseError: + #ifdef LOG_BACKTRACK + cerr << "hit error" << endl; + #endif + if ( numRetry > 0 ) { + while ( 1 ) { + struct Parser_LangEl *redLel = stackTop; + if ( stackTop->type < 225 ) { + #ifdef LOG_BACKTRACK + cerr << "backing up over terminal: " << + Parser_lelNames[stackTop->type] << endl; + #endif + stackTop = stackTop->next; + redLel->next = input; + input = redLel; + } + else { + #ifdef LOG_BACKTRACK + cerr << "backing up over non-terminal: " << + Parser_lelNames[stackTop->type] << endl; + #endif + stackTop = stackTop->next; + struct Parser_LangEl *first = redLel->child; + if ( first == 0 ) + rhsLen = 0; + else { + rhsLen = 1; + while ( first->next != 0 ) { + first = first->next; + rhsLen += 1; + } + first->next = stackTop; + stackTop = redLel->child; + + struct Parser_LangEl *rhsEl = stackTop; + int p = rhsLen; + while ( p > 0 ) { + rhs[--p] = rhsEl; + rhsEl = rhsEl->next; + } + } + redLel->next = pool; + pool = redLel; + numNodes -= 1; + } + + if ( redLel->retry > 0 ) { + #ifdef LOG_BACKTRACK + cerr << "found retry targ: " << redLel << endl; + #endif + numRetry -= 1; + #ifdef LOG_BACKTRACK + cerr << "found retry: " << redLel << endl; + #endif + if ( redLel->retry & 0x0000ffff ) + curs = input->state; + else { + input->retry = redLel->retry >> 16; + if ( stackTop->state < 0 ) + curs = Parser_startState; + else { + curs = Parser_targs[(int)Parser_indicies[Parser_offsets[stackTop->state] + (stackTop->type - Parser_keys[stackTop->state<<1])]]; + } + } + goto again; + } + } + } + curs = -1; + errCount += 1; +_out: {} +#line 1385 "rlparse.kl" + return errCount == 0 ? 0 : -1; +} + +void Parser::tryMachineDef( InputLoc &loc, char *name, + JoinOrLm *joinOrLm, bool isInstance ) +{ + GraphDictEl *newEl = pd->graphDict.insert( name ); + if ( newEl != 0 ) { + /* New element in the dict, all good. */ + newEl->value = new VarDef( name, joinOrLm ); + newEl->isInstance = isInstance; + newEl->loc = loc; + newEl->value->isExport = exportContext[exportContext.length()-1]; + + /* It it is an instance, put on the instance list. */ + if ( isInstance ) + pd->instanceList.append( newEl ); + } + else { + // Recover by ignoring the duplicate. + error(loc) << "fsm \"" << name << "\" previously defined" << endl; + } +} + +ostream &Parser::parse_error( int tokId, Token &token ) +{ + /* Maintain the error count. */ + gblErrorCount += 1; + + cerr << token.loc.fileName << ":" << token.loc.line << ":" << token.loc.col << ": "; + cerr << "at token "; + if ( tokId < 128 ) + cerr << "\"" << Parser_lelNames[tokId] << "\""; + else + cerr << Parser_lelNames[tokId]; + if ( token.data != 0 ) + cerr << " with data \"" << token.data << "\""; + cerr << ": "; + + return cerr; +} + +int Parser::token( InputLoc &loc, int tokId, char *tokstart, int toklen ) +{ + Token token; + token.data = tokstart; + token.length = toklen; + token.loc = loc; + int res = parseLangEl( tokId, &token ); + if ( res < 0 ) { + parse_error(tokId, token) << "parse error" << endl; + exit(1); + } + return res; +} diff --git a/contrib/tools/ragel5/ragel/rlparse.h b/contrib/tools/ragel5/ragel/rlparse.h new file mode 100644 index 00000000000..957db0fd690 --- /dev/null +++ b/contrib/tools/ragel5/ragel/rlparse.h @@ -0,0 +1,184 @@ +/* Automatically generated by Kelbt from "rlparse.kh". + * + * Parts of this file are copied from Kelbt source covered by the GNU + * GPL. As a special exception, you may use the parts of this file copied + * from Kelbt source without restriction. The remainder is derived from + * "rlparse.kh" and inherits the copyright status of that file. + */ + +#line 1 "rlparse.kh" +/* + * Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef RLPARSE_H +#define RLPARSE_H + +#include <iostream> +#include "avltree.h" +#include "parsedata.h" + +struct Parser +{ +#line 93 "rlparse.kh" + + + #line 44 "rlparse.h" + struct Parser_LangEl *freshEl; + int freshPos; + struct Parser_LangEl *pool; + int numRetry; + int numNodes; + struct Parser_LangEl *stackTop; + struct Parser_LangEl *lastFinal; + int errCount; + int curs; +#line 96 "rlparse.kh" + + void init(); + int parseLangEl( int type, const Token *token ); + + Parser(const char *fileName, char *sectionName, InputLoc §ionLoc ) + : sectionName(sectionName) + { + pd = new ParseData( fileName, sectionName, sectionLoc ); + exportContext.append( false ); + } + + int token( InputLoc &loc, int tokId, char *tokstart, int toklen ); + void tryMachineDef( InputLoc &loc, char *name, + JoinOrLm *joinOrLm, bool isInstance ); + + /* Report an error encountered by the parser. */ + ostream &parse_error( int tokId, Token &token ); + + ParseData *pd; + + /* The name of the root section, this does not change during an include. */ + char *sectionName; + + NameRef nameRef; + NameRefList nameRefList; + + Vector<bool> exportContext; +}; + +#line 84 "rlparse.h" +#define KW_Machine 128 +#define KW_Include 129 +#define KW_Import 130 +#define KW_Write 131 +#define TK_Word 132 +#define TK_Literal 133 +#define TK_Number 134 +#define TK_Inline 135 +#define TK_Reference 136 +#define TK_ColonEquals 137 +#define TK_EndSection 138 +#define TK_UInt 139 +#define TK_Hex 140 +#define TK_BaseClause 141 +#define TK_DotDot 142 +#define TK_ColonGt 143 +#define TK_ColonGtGt 144 +#define TK_LtColon 145 +#define TK_Arrow 146 +#define TK_DoubleArrow 147 +#define TK_StarStar 148 +#define TK_NameSep 149 +#define TK_BarStar 150 +#define TK_DashDash 151 +#define TK_StartCond 152 +#define TK_AllCond 153 +#define TK_LeavingCond 154 +#define TK_Middle 155 +#define TK_StartGblError 156 +#define TK_AllGblError 157 +#define TK_FinalGblError 158 +#define TK_NotFinalGblError 159 +#define TK_NotStartGblError 160 +#define TK_MiddleGblError 161 +#define TK_StartLocalError 162 +#define TK_AllLocalError 163 +#define TK_FinalLocalError 164 +#define TK_NotFinalLocalError 165 +#define TK_NotStartLocalError 166 +#define TK_MiddleLocalError 167 +#define TK_StartEOF 168 +#define TK_AllEOF 169 +#define TK_FinalEOF 170 +#define TK_NotFinalEOF 171 +#define TK_NotStartEOF 172 +#define TK_MiddleEOF 173 +#define TK_StartToState 174 +#define TK_AllToState 175 +#define TK_FinalToState 176 +#define TK_NotFinalToState 177 +#define TK_NotStartToState 178 +#define TK_MiddleToState 179 +#define TK_StartFromState 180 +#define TK_AllFromState 181 +#define TK_FinalFromState 182 +#define TK_NotFinalFromState 183 +#define TK_NotStartFromState 184 +#define TK_MiddleFromState 185 +#define RE_Slash 186 +#define RE_SqOpen 187 +#define RE_SqOpenNeg 188 +#define RE_SqClose 189 +#define RE_Dot 190 +#define RE_Star 191 +#define RE_Dash 192 +#define RE_Char 193 +#define IL_WhiteSpace 194 +#define IL_Comment 195 +#define IL_Literal 196 +#define IL_Symbol 197 +#define KW_Action 198 +#define KW_AlphType 199 +#define KW_Range 200 +#define KW_GetKey 201 +#define KW_When 202 +#define KW_Eof 203 +#define KW_Err 204 +#define KW_Lerr 205 +#define KW_To 206 +#define KW_From 207 +#define KW_Export 208 +#define KW_Break 209 +#define KW_Exec 210 +#define KW_Hold 211 +#define KW_PChar 212 +#define KW_Char 213 +#define KW_Goto 214 +#define KW_Call 215 +#define KW_Ret 216 +#define KW_CurState 217 +#define KW_TargState 218 +#define KW_Entry 219 +#define KW_Next 220 +#define KW_Variable 221 +#define KW_Access 222 +#define TK_Semi 223 +#define _eof 224 + +#line 126 "rlparse.kh" + +#endif diff --git a/contrib/tools/ragel5/ragel/rlscan.cpp b/contrib/tools/ragel5/ragel/rlscan.cpp new file mode 100644 index 00000000000..47a7f02148f --- /dev/null +++ b/contrib/tools/ragel5/ragel/rlscan.cpp @@ -0,0 +1,4876 @@ +#line 1 "rlscan.rl" +/* + * Copyright 2006-2007 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <iostream> +#include <fstream> +#include <string.h> + +#include "ragel.h" +#include "rlscan.h" + +//#define LOG_TOKENS + +using std::ifstream; +using std::istream; +using std::ostream; +using std::cout; +using std::cerr; +using std::endl; + +enum InlineBlockType +{ + CurlyDelimited, + SemiTerminated +}; + + +/* + * The Scanner for Importing + */ + +#define IMP_Word 128 +#define IMP_Literal 129 +#define IMP_UInt 130 +#define IMP_Define 131 + +#line 124 "rlscan.rl" + + + +#line 60 "rlscan.cpp" +static const int inline_token_scan_start = 2; + +static const int inline_token_scan_first_final = 2; + +static const int inline_token_scan_error = -1; + +#line 127 "rlscan.rl" + +void Scanner::flushImport() +{ + int *p = token_data; + int *pe = token_data + cur_token; + + +#line 75 "rlscan.cpp" + { + tok_cs = inline_token_scan_start; + tok_tokstart = 0; + tok_tokend = 0; + tok_act = 0; + } +#line 134 "rlscan.rl" + +#line 84 "rlscan.cpp" + { + if ( p == pe ) + goto _out; + switch ( tok_cs ) + { +tr0: +#line 122 "rlscan.rl" + {{p = (( tok_tokend))-1;}} + goto st2; +tr1: +#line 108 "rlscan.rl" + { tok_tokend = p+1;{ + int base = tok_tokstart - token_data; + int nameOff = 0; + int litOff = 2; + + directToParser( inclToParser, fileName, line, column, TK_Word, + token_strings[base+nameOff], token_lens[base+nameOff] ); + directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); + directToParser( inclToParser, fileName, line, column, TK_Literal, + token_strings[base+litOff], token_lens[base+litOff] ); + directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); + }{p = (( tok_tokend))-1;}} + goto st2; +tr2: +#line 80 "rlscan.rl" + { tok_tokend = p+1;{ + int base = tok_tokstart - token_data; + int nameOff = 0; + int numOff = 2; + + directToParser( inclToParser, fileName, line, column, TK_Word, + token_strings[base+nameOff], token_lens[base+nameOff] ); + directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); + directToParser( inclToParser, fileName, line, column, TK_UInt, + token_strings[base+numOff], token_lens[base+numOff] ); + directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); + }{p = (( tok_tokend))-1;}} + goto st2; +tr3: +#line 94 "rlscan.rl" + { tok_tokend = p+1;{ + int base = tok_tokstart - token_data; + int nameOff = 1; + int litOff = 2; + + directToParser( inclToParser, fileName, line, column, TK_Word, + token_strings[base+nameOff], token_lens[base+nameOff] ); + directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); + directToParser( inclToParser, fileName, line, column, TK_Literal, + token_strings[base+litOff], token_lens[base+litOff] ); + directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); + }{p = (( tok_tokend))-1;}} + goto st2; +tr4: +#line 66 "rlscan.rl" + { tok_tokend = p+1;{ + int base = tok_tokstart - token_data; + int nameOff = 1; + int numOff = 2; + + directToParser( inclToParser, fileName, line, column, TK_Word, + token_strings[base+nameOff], token_lens[base+nameOff] ); + directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); + directToParser( inclToParser, fileName, line, column, TK_UInt, + token_strings[base+numOff], token_lens[base+numOff] ); + directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); + }{p = (( tok_tokend))-1;}} + goto st2; +tr5: +#line 122 "rlscan.rl" + { tok_tokend = p+1;{p = (( tok_tokend))-1;}} + goto st2; +tr8: +#line 122 "rlscan.rl" + { tok_tokend = p;{p = (( tok_tokend))-1;}} + goto st2; +st2: +#line 1 "rlscan.rl" + { tok_tokstart = 0;} + if ( ++p == pe ) + goto _out2; +case 2: +#line 1 "rlscan.rl" + { tok_tokstart = p;} +#line 170 "rlscan.cpp" + switch( (*p) ) { + case 128: goto tr6; + case 131: goto tr7; + } + goto tr5; +tr6: +#line 1 "rlscan.rl" + { tok_tokend = p+1;} + goto st3; +st3: + if ( ++p == pe ) + goto _out3; +case 3: +#line 184 "rlscan.cpp" + if ( (*p) == 61 ) + goto st0; + goto tr8; +st0: + if ( ++p == pe ) + goto _out0; +case 0: + switch( (*p) ) { + case 129: goto tr1; + case 130: goto tr2; + } + goto tr0; +tr7: +#line 1 "rlscan.rl" + { tok_tokend = p+1;} + goto st4; +st4: + if ( ++p == pe ) + goto _out4; +case 4: +#line 205 "rlscan.cpp" + if ( (*p) == 128 ) + goto st1; + goto tr8; +st1: + if ( ++p == pe ) + goto _out1; +case 1: + switch( (*p) ) { + case 129: goto tr3; + case 130: goto tr4; + } + goto tr0; + } + _out2: tok_cs = 2; goto _out; + _out3: tok_cs = 3; goto _out; + _out0: tok_cs = 0; goto _out; + _out4: tok_cs = 4; goto _out; + _out1: tok_cs = 1; goto _out; + + _out: {} + } +#line 135 "rlscan.rl" + + if ( tok_tokstart == 0 ) + cur_token = 0; + else { + cur_token = pe - tok_tokstart; + int ts_offset = tok_tokstart - token_data; + memmove( token_data, token_data+ts_offset, cur_token*sizeof(token_data[0]) ); + memmove( token_strings, token_strings+ts_offset, cur_token*sizeof(token_strings[0]) ); + memmove( token_lens, token_lens+ts_offset, cur_token*sizeof(token_lens[0]) ); + } +} + +void Scanner::directToParser( Parser *toParser, const char *tokFileName, int tokLine, + int tokColumn, int type, char *tokdata, int toklen ) +{ + InputLoc loc; + + #ifdef LOG_TOKENS + cerr << "scanner:" << tokLine << ":" << tokColumn << + ": sending token to the parser " << Parser_lelNames[type]; + cerr << " " << toklen; + if ( tokdata != 0 ) + cerr << " " << tokdata; + cerr << endl; + #endif + + loc.fileName = tokFileName; + loc.line = tokLine; + loc.col = tokColumn; + + toParser->token( loc, type, tokdata, toklen ); +} + +void Scanner::importToken( int token, char *start, char *end ) +{ + if ( cur_token == max_tokens ) + flushImport(); + + token_data[cur_token] = token; + if ( start == 0 ) { + token_strings[cur_token] = 0; + token_lens[cur_token] = 0; + } + else { + int toklen = end-start; + token_lens[cur_token] = toklen; + token_strings[cur_token] = new char[toklen+1]; + memcpy( token_strings[cur_token], start, toklen ); + token_strings[cur_token][toklen] = 0; + } + cur_token++; +} + +void Scanner::pass( int token, char *start, char *end ) +{ + if ( importMachines ) + importToken( token, start, end ); + pass(); +} + +void Scanner::pass() +{ + updateCol(); + + /* If no errors and we are at the bottom of the include stack (the + * source file listed on the command line) then write out the data. */ + if ( includeDepth == 0 && machineSpec == 0 && machineName == 0 ) + xmlEscapeHost( output, tokstart, tokend-tokstart ); +} + +/* + * The scanner for processing sections, includes, imports, etc. + */ + + +#line 303 "rlscan.cpp" +static const int section_parse_start = 10; + +static const int section_parse_first_final = 10; + +static const int section_parse_error = 0; + +#line 213 "rlscan.rl" + + + +void Scanner::init( ) +{ + +#line 317 "rlscan.cpp" + { + cs = section_parse_start; + } +#line 219 "rlscan.rl" +} + +bool Scanner::active() +{ + if ( ignoreSection ) + return false; + + if ( parser == 0 && ! parserExistsError ) { + scan_error() << "there is no previous specification name" << endl; + parserExistsError = true; + } + + if ( parser == 0 ) + return false; + + return true; +} + +ostream &Scanner::scan_error() +{ + /* Maintain the error count. */ + gblErrorCount += 1; + cerr << fileName << ":" << line << ":" << column << ": "; + return cerr; +} + +bool Scanner::recursiveInclude(const char *inclFileName, char *inclSectionName ) +{ + for ( IncludeStack::Iter si = includeStack; si.lte(); si++ ) { + if ( strcmp( si->fileName, inclFileName ) == 0 && + strcmp( si->sectionName, inclSectionName ) == 0 ) + { + return true; + } + } + return false; +} + +void Scanner::updateCol() +{ + char *from = lastnl; + if ( from == 0 ) + from = tokstart; + //cerr << "adding " << tokend - from << " to column" << endl; + column += tokend - from; + lastnl = 0; +} + +#line 442 "rlscan.rl" + + +void Scanner::token( int type, char c ) +{ + token( type, &c, &c + 1 ); +} + +void Scanner::token( int type ) +{ + token( type, 0, 0 ); +} + +void Scanner::token( int type, char *start, char *end ) +{ + char *tokdata = 0; + int toklen = 0; + if ( start != 0 ) { + toklen = end-start; + tokdata = new char[toklen+1]; + memcpy( tokdata, start, toklen ); + tokdata[toklen] = 0; + } + + processToken( type, tokdata, toklen ); +} + +void Scanner::processToken( int type, char *tokdata, int toklen ) +{ + int *p = &type; + int *pe = &type + 1; + + +#line 403 "rlscan.cpp" + { + if ( p == pe ) + goto _out; + switch ( cs ) + { +tr2: +#line 289 "rlscan.rl" + { + /* Assign a name to the machine. */ + char *machine = word; + + if ( !importMachines && inclSectionTarg == 0 ) { + ignoreSection = false; + + ParserDictEl *pdEl = parserDict.find( machine ); + if ( pdEl == 0 ) { + pdEl = new ParserDictEl( machine ); + pdEl->value = new Parser( fileName, machine, sectionLoc ); + pdEl->value->init(); + parserDict.insert( pdEl ); + } + + parser = pdEl->value; + } + else if ( !importMachines && strcmp( inclSectionTarg, machine ) == 0 ) { + /* found include target */ + ignoreSection = false; + parser = inclToParser; + } + else { + /* ignoring section */ + ignoreSection = true; + parser = 0; + } + } + goto st10; +tr6: +#line 323 "rlscan.rl" + { + if ( active() ) { + char *inclSectionName = word; + const char *inclFileName = 0; + + /* Implement defaults for the input file and section name. */ + if ( inclSectionName == 0 ) + inclSectionName = parser->sectionName; + + if ( lit != 0 ) + inclFileName = prepareFileName( lit, lit_len ); + else + inclFileName = fileName; + + /* Check for a recursive include structure. Add the current file/section + * name then check if what we are including is already in the stack. */ + includeStack.append( IncludeStackItem( fileName, parser->sectionName ) ); + + if ( recursiveInclude( inclFileName, inclSectionName ) ) + scan_error() << "include: this is a recursive include operation" << endl; + else { + /* Open the input file for reading. */ + ifstream *inFile = new ifstream( inclFileName ); + if ( ! inFile->is_open() ) { + scan_error() << "include: could not open " << + inclFileName << " for reading" << endl; + } + + Scanner scanner( inclFileName, *inFile, output, parser, + inclSectionName, includeDepth+1, false ); + scanner.do_scan( ); + delete inFile; + } + + /* Remove the last element (len-1) */ + includeStack.remove( -1 ); + } + } + goto st10; +tr10: +#line 372 "rlscan.rl" + { + if ( active() ) { + char *importFileName = prepareFileName( lit, lit_len ); + + /* Open the input file for reading. */ + ifstream *inFile = new ifstream( importFileName ); + if ( ! inFile->is_open() ) { + scan_error() << "import: could not open " << + importFileName << " for reading" << endl; + } + + Scanner scanner( importFileName, *inFile, output, parser, + 0, includeDepth+1, true ); + scanner.do_scan( ); + scanner.importToken( 0, 0, 0 ); + scanner.flushImport(); + delete inFile; + } + } + goto st10; +tr13: +#line 414 "rlscan.rl" + { + if ( active() && machineSpec == 0 && machineName == 0 ) + output << "</write>\n"; + } + goto st10; +tr14: +#line 425 "rlscan.rl" + { + /* Send the token off to the parser. */ + if ( active() ) + directToParser( parser, fileName, line, column, type, tokdata, toklen ); + } + goto st10; +st10: + if ( ++p == pe ) + goto _out10; +case 10: +#line 522 "rlscan.cpp" + switch( (*p) ) { + case 128: goto st1; + case 129: goto st3; + case 130: goto st6; + case 131: goto tr18; + } + goto tr14; +st1: + if ( ++p == pe ) + goto _out1; +case 1: + if ( (*p) == 132 ) + goto tr1; + goto tr0; +tr0: +#line 283 "rlscan.rl" + { scan_error() << "bad machine statement" << endl; } + goto st0; +tr3: +#line 284 "rlscan.rl" + { scan_error() << "bad include statement" << endl; } + goto st0; +tr8: +#line 285 "rlscan.rl" + { scan_error() << "bad import statement" << endl; } + goto st0; +tr11: +#line 286 "rlscan.rl" + { scan_error() << "bad write statement" << endl; } + goto st0; +#line 553 "rlscan.cpp" +st0: + goto _out0; +tr1: +#line 280 "rlscan.rl" + { word = tokdata; word_len = toklen; } + goto st2; +st2: + if ( ++p == pe ) + goto _out2; +case 2: +#line 564 "rlscan.cpp" + if ( (*p) == 59 ) + goto tr2; + goto tr0; +st3: + if ( ++p == pe ) + goto _out3; +case 3: + switch( (*p) ) { + case 132: goto tr4; + case 133: goto tr5; + } + goto tr3; +tr4: +#line 279 "rlscan.rl" + { word = lit = 0; word_len = lit_len = 0; } +#line 280 "rlscan.rl" + { word = tokdata; word_len = toklen; } + goto st4; +st4: + if ( ++p == pe ) + goto _out4; +case 4: +#line 587 "rlscan.cpp" + switch( (*p) ) { + case 59: goto tr6; + case 133: goto tr7; + } + goto tr3; +tr5: +#line 279 "rlscan.rl" + { word = lit = 0; word_len = lit_len = 0; } +#line 281 "rlscan.rl" + { lit = tokdata; lit_len = toklen; } + goto st5; +tr7: +#line 281 "rlscan.rl" + { lit = tokdata; lit_len = toklen; } + goto st5; +st5: + if ( ++p == pe ) + goto _out5; +case 5: +#line 607 "rlscan.cpp" + if ( (*p) == 59 ) + goto tr6; + goto tr3; +st6: + if ( ++p == pe ) + goto _out6; +case 6: + if ( (*p) == 133 ) + goto tr9; + goto tr8; +tr9: +#line 281 "rlscan.rl" + { lit = tokdata; lit_len = toklen; } + goto st7; +st7: + if ( ++p == pe ) + goto _out7; +case 7: +#line 626 "rlscan.cpp" + if ( (*p) == 59 ) + goto tr10; + goto tr8; +tr18: +#line 397 "rlscan.rl" + { + if ( active() && machineSpec == 0 && machineName == 0 ) { + output << "<write" + " def_name=\"" << parser->sectionName << "\"" + " line=\"" << line << "\"" + " col=\"" << column << "\"" + ">"; + } + } + goto st8; +st8: + if ( ++p == pe ) + goto _out8; +case 8: +#line 646 "rlscan.cpp" + if ( (*p) == 132 ) + goto tr12; + goto tr11; +tr12: +#line 408 "rlscan.rl" + { + if ( active() && machineSpec == 0 && machineName == 0 ) + output << "<arg>" << tokdata << "</arg>"; + } + goto st9; +st9: + if ( ++p == pe ) + goto _out9; +case 9: +#line 661 "rlscan.cpp" + switch( (*p) ) { + case 59: goto tr13; + case 132: goto tr12; + } + goto tr11; + } + _out10: cs = 10; goto _out; + _out1: cs = 1; goto _out; + _out0: cs = 0; goto _out; + _out2: cs = 2; goto _out; + _out3: cs = 3; goto _out; + _out4: cs = 4; goto _out; + _out5: cs = 5; goto _out; + _out6: cs = 6; goto _out; + _out7: cs = 7; goto _out; + _out8: cs = 8; goto _out; + _out9: cs = 9; goto _out; + + _out: {} + } +#line 476 "rlscan.rl" + + + updateCol(); + + /* Record the last token for use in controlling the scan of subsequent + * tokens. */ + lastToken = type; +} + +void Scanner::startSection( ) +{ + parserExistsError = false; + + if ( includeDepth == 0 ) { + if ( machineSpec == 0 && machineName == 0 ) + output << "</host>\n"; + } + + sectionLoc.fileName = fileName; + sectionLoc.line = line; + sectionLoc.col = 0; +} + +void Scanner::endSection( ) +{ + /* Execute the eof actions for the section parser. */ + +#line 710 "rlscan.cpp" + { + switch ( cs ) { + case 1: + case 2: +#line 283 "rlscan.rl" + { scan_error() << "bad machine statement" << endl; } + break; + case 3: + case 4: + case 5: +#line 284 "rlscan.rl" + { scan_error() << "bad include statement" << endl; } + break; + case 6: + case 7: +#line 285 "rlscan.rl" + { scan_error() << "bad import statement" << endl; } + break; + case 8: + case 9: +#line 286 "rlscan.rl" + { scan_error() << "bad write statement" << endl; } + break; +#line 734 "rlscan.cpp" + } + } + +#line 505 "rlscan.rl" + + + /* Close off the section with the parser. */ + if ( active() ) { + InputLoc loc; + loc.fileName = fileName; + loc.line = line; + loc.col = 0; + + parser->token( loc, TK_EndSection, 0, 0 ); + } + + if ( includeDepth == 0 ) { + if ( machineSpec == 0 && machineName == 0 ) { + /* The end section may include a newline on the end, so + * we use the last line, which will count the newline. */ + output << "<host line=\"" << line << "\">"; + } + } +} + +#line 917 "rlscan.rl" + + + +#line 764 "rlscan.cpp" +static const int rlscan_start = 23; + +static const int rlscan_first_final = 23; + +static const int rlscan_error = 0; + +#line 920 "rlscan.rl" + +void Scanner::do_scan() +{ + int bufsize = 8; + char *buf = new char[bufsize]; + const char last_char = 0; + int cs, act, have = 0; + int top, stack[1]; + int curly_count = 0; + bool execute = true; + bool singleLineSpec = false; + InlineBlockType inlineBlockType = CurlyDelimited; + + /* Init the section parser and the character scanner. */ + init(); + +#line 788 "rlscan.cpp" + { + cs = rlscan_start; + top = 0; + tokstart = 0; + tokend = 0; + act = 0; + } +#line 936 "rlscan.rl" + + while ( execute ) { + char *p = buf + have; + int space = bufsize - have; + + if ( space == 0 ) { + /* We filled up the buffer trying to scan a token. Grow it. */ + bufsize = bufsize * 2; + char *newbuf = new char[bufsize]; + + /* Recompute p and space. */ + p = newbuf + have; + space = bufsize - have; + + /* Patch up pointers possibly in use. */ + if ( tokstart != 0 ) + tokstart = newbuf + ( tokstart - buf ); + tokend = newbuf + ( tokend - buf ); + + /* Copy the new buffer in. */ + memcpy( newbuf, buf, have ); + delete[] buf; + buf = newbuf; + } + + input.read( p, space ); + int len = input.gcount(); + + /* If we see eof then append the EOF char. */ + if ( len == 0 ) { + p[0] = last_char, len = 1; + execute = false; + } + + char *pe = p + len; + +#line 833 "rlscan.cpp" + { + if ( p == pe ) + goto _out; + goto _resume; + +_again: + switch ( cs ) { + case 23: goto st23; + case 24: goto st24; + case 25: goto st25; + case 1: goto st1; + case 2: goto st2; + case 26: goto st26; + case 27: goto st27; + case 28: goto st28; + case 3: goto st3; + case 4: goto st4; + case 29: goto st29; + case 5: goto st5; + case 6: goto st6; + case 7: goto st7; + case 30: goto st30; + case 31: goto st31; + case 32: goto st32; + case 33: goto st33; + case 34: goto st34; + case 35: goto st35; + case 36: goto st36; + case 37: goto st37; + case 38: goto st38; + case 39: goto st39; + case 8: goto st8; + case 9: goto st9; + case 40: goto st40; + case 10: goto st10; + case 11: goto st11; + case 41: goto st41; + case 12: goto st12; + case 13: goto st13; + case 14: goto st14; + case 42: goto st42; + case 43: goto st43; + case 15: goto st15; + case 44: goto st44; + case 45: goto st45; + case 46: goto st46; + case 47: goto st47; + case 48: goto st48; + case 49: goto st49; + case 50: goto st50; + case 51: goto st51; + case 52: goto st52; + case 53: goto st53; + case 54: goto st54; + case 55: goto st55; + case 56: goto st56; + case 57: goto st57; + case 58: goto st58; + case 59: goto st59; + case 60: goto st60; + case 61: goto st61; + case 62: goto st62; + case 63: goto st63; + case 64: goto st64; + case 65: goto st65; + case 66: goto st66; + case 67: goto st67; + case 68: goto st68; + case 69: goto st69; + case 70: goto st70; + case 71: goto st71; + case 72: goto st72; + case 73: goto st73; + case 74: goto st74; + case 75: goto st75; + case 76: goto st76; + case 77: goto st77; + case 78: goto st78; + case 79: goto st79; + case 80: goto st80; + case 81: goto st81; + case 82: goto st82; + case 83: goto st83; + case 84: goto st84; + case 85: goto st85; + case 0: goto st0; + case 86: goto st86; + case 87: goto st87; + case 88: goto st88; + case 89: goto st89; + case 90: goto st90; + case 16: goto st16; + case 91: goto st91; + case 17: goto st17; + case 92: goto st92; + case 18: goto st18; + case 93: goto st93; + case 94: goto st94; + case 95: goto st95; + case 19: goto st19; + case 20: goto st20; + case 96: goto st96; + case 97: goto st97; + case 98: goto st98; + case 99: goto st99; + case 100: goto st100; + case 21: goto st21; + case 101: goto st101; + case 102: goto st102; + case 103: goto st103; + case 104: goto st104; + case 105: goto st105; + case 106: goto st106; + case 107: goto st107; + case 108: goto st108; + case 109: goto st109; + case 110: goto st110; + case 111: goto st111; + case 112: goto st112; + case 113: goto st113; + case 114: goto st114; + case 115: goto st115; + case 116: goto st116; + case 117: goto st117; + case 118: goto st118; + case 119: goto st119; + case 120: goto st120; + case 121: goto st121; + case 122: goto st122; + case 123: goto st123; + case 124: goto st124; + case 125: goto st125; + case 126: goto st126; + case 127: goto st127; + case 128: goto st128; + case 129: goto st129; + case 130: goto st130; + case 131: goto st131; + case 132: goto st132; + case 133: goto st133; + case 134: goto st134; + case 135: goto st135; + case 136: goto st136; + case 137: goto st137; + case 138: goto st138; + case 139: goto st139; + case 140: goto st140; + case 141: goto st141; + case 142: goto st142; + case 143: goto st143; + case 144: goto st144; + case 145: goto st145; + case 146: goto st146; + case 147: goto st147; + case 148: goto st148; + case 149: goto st149; + case 150: goto st150; + case 151: goto st151; + case 152: goto st152; + case 153: goto st153; + case 154: goto st154; + case 155: goto st155; + case 156: goto st156; + case 157: goto st157; + case 158: goto st158; + case 159: goto st159; + case 160: goto st160; + case 161: goto st161; + case 162: goto st162; + case 163: goto st163; + case 164: goto st164; + case 165: goto st165; + case 166: goto st166; + case 167: goto st167; + case 168: goto st168; + case 169: goto st169; + case 170: goto st170; + case 171: goto st171; + case 172: goto st172; + case 173: goto st173; + case 174: goto st174; + case 22: goto st22; + default: break; + } + + if ( ++p == pe ) + goto _out; +_resume: + switch ( cs ) + { +tr2: +#line 899 "rlscan.rl" + {tokend = p+1;{ pass( IMP_Literal, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st23; +tr10: +#line 898 "rlscan.rl" + {tokend = p+1;{ pass(); }{p = ((tokend))-1;}} + goto st23; +tr12: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } +#line 898 "rlscan.rl" + {tokend = p+1;{ pass(); }{p = ((tokend))-1;}} + goto st23; +tr41: +#line 915 "rlscan.rl" + {tokend = p+1;{ pass( *tokstart, 0, 0 ); }{p = ((tokend))-1;}} + goto st23; +tr42: +#line 914 "rlscan.rl" + {tokend = p+1;{p = ((tokend))-1;}} + goto st23; +tr52: +#line 913 "rlscan.rl" + {tokend = p;{ pass(); }{p = ((tokend))-1;}} + goto st23; +tr53: +#line 915 "rlscan.rl" + {tokend = p;{ pass( *tokstart, 0, 0 ); }{p = ((tokend))-1;}} + goto st23; +tr55: +#line 907 "rlscan.rl" + {tokend = p;{ + updateCol(); + singleLineSpec = true; + startSection(); + {{p = ((tokend))-1;}{goto st88;}} + }{p = ((tokend))-1;}} + goto st23; +tr56: +#line 901 "rlscan.rl" + {tokend = p+1;{ + updateCol(); + singleLineSpec = false; + startSection(); + {{p = ((tokend))-1;}{goto st88;}} + }{p = ((tokend))-1;}} + goto st23; +tr57: +#line 897 "rlscan.rl" + {tokend = p;{ pass( IMP_UInt, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st23; +tr58: +#line 1 "rlscan.rl" + { switch( act ) { + case 137: + { pass( IMP_Define, 0, 0 ); } + break; + case 138: + { pass( IMP_Word, tokstart, tokend ); } + break; + default: break; + } + {p = ((tokend))-1;}} + goto st23; +tr59: +#line 896 "rlscan.rl" + {tokend = p;{ pass( IMP_Word, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st23; +st23: +#line 1 "rlscan.rl" + {tokstart = 0;} + if ( ++p == pe ) + goto _out23; +case 23: +#line 1 "rlscan.rl" + {tokstart = p;} +#line 1105 "rlscan.cpp" + switch( (*p) ) { + case 0: goto tr42; + case 9: goto st24; + case 10: goto tr44; + case 32: goto st24; + case 34: goto tr45; + case 37: goto st26; + case 39: goto tr47; + case 47: goto tr48; + case 95: goto tr50; + case 100: goto st32; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto st30; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr50; + } else + goto tr50; + goto tr41; +tr44: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } + goto st24; +st24: + if ( ++p == pe ) + goto _out24; +case 24: +#line 1139 "rlscan.cpp" + switch( (*p) ) { + case 9: goto st24; + case 10: goto tr44; + case 32: goto st24; + } + goto tr52; +tr45: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st25; +st25: + if ( ++p == pe ) + goto _out25; +case 25: +#line 1154 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr1; + case 34: goto tr2; + case 92: goto st2; + } + goto st1; +tr1: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } + goto st1; +st1: + if ( ++p == pe ) + goto _out1; +case 1: +#line 1173 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr1; + case 34: goto tr2; + case 92: goto st2; + } + goto st1; +st2: + if ( ++p == pe ) + goto _out2; +case 2: + if ( (*p) == 10 ) + goto tr1; + goto st1; +st26: + if ( ++p == pe ) + goto _out26; +case 26: + if ( (*p) == 37 ) + goto st27; + goto tr53; +st27: + if ( ++p == pe ) + goto _out27; +case 27: + if ( (*p) == 123 ) + goto tr56; + goto tr55; +tr47: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st28; +st28: + if ( ++p == pe ) + goto _out28; +case 28: +#line 1209 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr5; + case 39: goto tr2; + case 92: goto st4; + } + goto st3; +tr5: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } + goto st3; +st3: + if ( ++p == pe ) + goto _out3; +case 3: +#line 1228 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr5; + case 39: goto tr2; + case 92: goto st4; + } + goto st3; +st4: + if ( ++p == pe ) + goto _out4; +case 4: + if ( (*p) == 10 ) + goto tr5; + goto st3; +tr48: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st29; +st29: + if ( ++p == pe ) + goto _out29; +case 29: +#line 1250 "rlscan.cpp" + switch( (*p) ) { + case 42: goto st5; + case 47: goto st7; + } + goto tr53; +tr8: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } + goto st5; +st5: + if ( ++p == pe ) + goto _out5; +case 5: +#line 1268 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr8; + case 42: goto st6; + } + goto st5; +st6: + if ( ++p == pe ) + goto _out6; +case 6: + switch( (*p) ) { + case 10: goto tr8; + case 42: goto st6; + case 47: goto tr10; + } + goto st5; +st7: + if ( ++p == pe ) + goto _out7; +case 7: + if ( (*p) == 10 ) + goto tr12; + goto st7; +st30: + if ( ++p == pe ) + goto _out30; +case 30: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st30; + goto tr57; +tr50: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 896 "rlscan.rl" + {act = 138;} + goto st31; +tr64: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 895 "rlscan.rl" + {act = 137;} + goto st31; +st31: + if ( ++p == pe ) + goto _out31; +case 31: +#line 1314 "rlscan.cpp" + if ( (*p) == 95 ) + goto tr50; + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr50; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr50; + } else + goto tr50; + goto tr58; +st32: + if ( ++p == pe ) + goto _out32; +case 32: + switch( (*p) ) { + case 95: goto tr50; + case 101: goto st33; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr50; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr50; + } else + goto tr50; + goto tr59; +st33: + if ( ++p == pe ) + goto _out33; +case 33: + switch( (*p) ) { + case 95: goto tr50; + case 102: goto st34; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr50; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr50; + } else + goto tr50; + goto tr59; +st34: + if ( ++p == pe ) + goto _out34; +case 34: + switch( (*p) ) { + case 95: goto tr50; + case 105: goto st35; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr50; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr50; + } else + goto tr50; + goto tr59; +st35: + if ( ++p == pe ) + goto _out35; +case 35: + switch( (*p) ) { + case 95: goto tr50; + case 110: goto st36; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr50; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr50; + } else + goto tr50; + goto tr59; +st36: + if ( ++p == pe ) + goto _out36; +case 36: + switch( (*p) ) { + case 95: goto tr50; + case 101: goto tr64; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr50; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr50; + } else + goto tr50; + goto tr59; +tr15: +#line 606 "rlscan.rl" + {tokend = p+1;{ token( IL_Literal, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr23: +#line 612 "rlscan.rl" + {tokend = p+1;{ token( IL_Comment, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr25: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } +#line 612 "rlscan.rl" + {tokend = p+1;{ token( IL_Comment, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr26: +#line 602 "rlscan.rl" + {{ token( TK_UInt, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr65: +#line 659 "rlscan.rl" + {tokend = p+1;{ token( IL_Symbol, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr66: +#line 654 "rlscan.rl" + {tokend = p+1;{ + scan_error() << "unterminated code block" << endl; + }{p = ((tokend))-1;}} + goto st37; +tr71: +#line 634 "rlscan.rl" + {tokend = p+1;{ token( *tokstart, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr72: +#line 629 "rlscan.rl" + {tokend = p+1;{ + whitespaceOn = true; + token( *tokstart, tokstart, tokend ); + }{p = ((tokend))-1;}} + goto st37; +tr77: +#line 622 "rlscan.rl" + {tokend = p+1;{ + whitespaceOn = true; + token( *tokstart, tokstart, tokend ); + if ( inlineBlockType == SemiTerminated ) + {{p = ((tokend))-1;}{goto st88;}} + }{p = ((tokend))-1;}} + goto st37; +tr80: +#line 636 "rlscan.rl" + {tokend = p+1;{ + token( IL_Symbol, tokstart, tokend ); + curly_count += 1; + }{p = ((tokend))-1;}} + goto st37; +tr81: +#line 641 "rlscan.rl" + {tokend = p+1;{ + if ( --curly_count == 0 && inlineBlockType == CurlyDelimited ) { + /* Inline code block ends. */ + token( '}' ); + {{p = ((tokend))-1;}{goto st88;}} + } + else { + /* Either a semi terminated inline block or only the closing + * brace of some inner scope, not the block's closing brace. */ + token( IL_Symbol, tokstart, tokend ); + } + }{p = ((tokend))-1;}} + goto st37; +tr82: +#line 608 "rlscan.rl" + {tokend = p;{ + if ( whitespaceOn ) + token( IL_WhiteSpace, tokstart, tokend ); + }{p = ((tokend))-1;}} + goto st37; +tr83: +#line 659 "rlscan.rl" + {tokend = p;{ token( IL_Symbol, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr84: +#line 602 "rlscan.rl" + {tokend = p;{ token( TK_UInt, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr86: +#line 603 "rlscan.rl" + {tokend = p;{ token( TK_Hex, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr87: +#line 614 "rlscan.rl" + {tokend = p+1;{ token( TK_NameSep, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr88: +#line 1 "rlscan.rl" + { switch( act ) { + case 1: + { token( KW_PChar ); } + break; + case 3: + { token( KW_CurState ); } + break; + case 4: + { token( KW_TargState ); } + break; + case 5: + { + whitespaceOn = false; + token( KW_Entry ); + } + break; + case 6: + { + whitespaceOn = false; + token( KW_Hold ); + } + break; + case 7: + { token( KW_Exec, 0, 0 ); } + break; + case 8: + { + whitespaceOn = false; + token( KW_Goto ); + } + break; + case 9: + { + whitespaceOn = false; + token( KW_Next ); + } + break; + case 10: + { + whitespaceOn = false; + token( KW_Call ); + } + break; + case 11: + { + whitespaceOn = false; + token( KW_Ret ); + } + break; + case 12: + { + whitespaceOn = false; + token( KW_Break ); + } + break; + case 13: + { token( TK_Word, tokstart, tokend ); } + break; + default: break; + } + {p = ((tokend))-1;}} + goto st37; +tr89: +#line 600 "rlscan.rl" + {tokend = p;{ token( TK_Word, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st37; +tr103: +#line 565 "rlscan.rl" + {tokend = p;{ token( KW_Char ); }{p = ((tokend))-1;}} + goto st37; +st37: +#line 1 "rlscan.rl" + {tokstart = 0;} + if ( ++p == pe ) + goto _out37; +case 37: +#line 1 "rlscan.rl" + {tokstart = p;} +#line 1588 "rlscan.cpp" + switch( (*p) ) { + case 0: goto tr66; + case 9: goto st38; + case 10: goto tr68; + case 32: goto st38; + case 34: goto tr69; + case 39: goto tr70; + case 40: goto tr71; + case 44: goto tr71; + case 47: goto tr73; + case 48: goto tr74; + case 58: goto st45; + case 59: goto tr77; + case 95: goto tr78; + case 102: goto st47; + case 123: goto tr80; + case 125: goto tr81; + } + if ( (*p) < 49 ) { + if ( 41 <= (*p) && (*p) <= 42 ) + goto tr72; + } else if ( (*p) > 57 ) { + if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else if ( (*p) >= 65 ) + goto tr78; + } else + goto st43; + goto tr65; +tr68: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } + goto st38; +st38: + if ( ++p == pe ) + goto _out38; +case 38: +#line 1631 "rlscan.cpp" + switch( (*p) ) { + case 9: goto st38; + case 10: goto tr68; + case 32: goto st38; + } + goto tr82; +tr69: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st39; +st39: + if ( ++p == pe ) + goto _out39; +case 39: +#line 1646 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr14; + case 34: goto tr15; + case 92: goto st9; + } + goto st8; +tr14: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } + goto st8; +st8: + if ( ++p == pe ) + goto _out8; +case 8: +#line 1665 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr14; + case 34: goto tr15; + case 92: goto st9; + } + goto st8; +st9: + if ( ++p == pe ) + goto _out9; +case 9: + if ( (*p) == 10 ) + goto tr14; + goto st8; +tr70: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st40; +st40: + if ( ++p == pe ) + goto _out40; +case 40: +#line 1687 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr18; + case 39: goto tr15; + case 92: goto st11; + } + goto st10; +tr18: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } + goto st10; +st10: + if ( ++p == pe ) + goto _out10; +case 10: +#line 1706 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr18; + case 39: goto tr15; + case 92: goto st11; + } + goto st10; +st11: + if ( ++p == pe ) + goto _out11; +case 11: + if ( (*p) == 10 ) + goto tr18; + goto st10; +tr73: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st41; +st41: + if ( ++p == pe ) + goto _out41; +case 41: +#line 1728 "rlscan.cpp" + switch( (*p) ) { + case 42: goto st12; + case 47: goto st14; + } + goto tr83; +tr21: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } + goto st12; +st12: + if ( ++p == pe ) + goto _out12; +case 12: +#line 1746 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr21; + case 42: goto st13; + } + goto st12; +st13: + if ( ++p == pe ) + goto _out13; +case 13: + switch( (*p) ) { + case 10: goto tr21; + case 42: goto st13; + case 47: goto tr23; + } + goto st12; +st14: + if ( ++p == pe ) + goto _out14; +case 14: + if ( (*p) == 10 ) + goto tr25; + goto st14; +tr74: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st42; +st42: + if ( ++p == pe ) + goto _out42; +case 42: +#line 1777 "rlscan.cpp" + if ( (*p) == 120 ) + goto st15; + if ( 48 <= (*p) && (*p) <= 57 ) + goto st43; + goto tr84; +st43: + if ( ++p == pe ) + goto _out43; +case 43: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st43; + goto tr84; +st15: + if ( ++p == pe ) + goto _out15; +case 15: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto st44; + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) + goto st44; + } else + goto st44; + goto tr26; +st44: + if ( ++p == pe ) + goto _out44; +case 44: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto st44; + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) + goto st44; + } else + goto st44; + goto tr86; +st45: + if ( ++p == pe ) + goto _out45; +case 45: + if ( (*p) == 58 ) + goto tr87; + goto tr83; +tr78: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 600 "rlscan.rl" + {act = 13;} + goto st46; +tr102: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 595 "rlscan.rl" + {act = 12;} + goto st46; +tr107: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 587 "rlscan.rl" + {act = 10;} + goto st46; +tr109: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 566 "rlscan.rl" + {act = 3;} + goto st46; +tr114: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 568 "rlscan.rl" + {act = 5;} + goto st46; +tr116: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 578 "rlscan.rl" + {act = 7;} + goto st46; +tr119: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 579 "rlscan.rl" + {act = 8;} + goto st46; +tr122: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 574 "rlscan.rl" + {act = 6;} + goto st46; +tr125: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 583 "rlscan.rl" + {act = 9;} + goto st46; +tr126: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 564 "rlscan.rl" + {act = 1;} + goto st46; +tr128: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 591 "rlscan.rl" + {act = 11;} + goto st46; +tr132: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 567 "rlscan.rl" + {act = 4;} + goto st46; +st46: + if ( ++p == pe ) + goto _out46; +case 46: +#line 1899 "rlscan.cpp" + if ( (*p) == 95 ) + goto tr78; + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr88; +st47: + if ( ++p == pe ) + goto _out47; +case 47: + switch( (*p) ) { + case 95: goto tr78; + case 98: goto st48; + case 99: goto st52; + case 101: goto st57; + case 103: goto st63; + case 104: goto st66; + case 110: goto st69; + case 112: goto st72; + case 114: goto st73; + case 116: goto st75; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st48: + if ( ++p == pe ) + goto _out48; +case 48: + switch( (*p) ) { + case 95: goto tr78; + case 114: goto st49; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st49: + if ( ++p == pe ) + goto _out49; +case 49: + switch( (*p) ) { + case 95: goto tr78; + case 101: goto st50; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st50: + if ( ++p == pe ) + goto _out50; +case 50: + switch( (*p) ) { + case 95: goto tr78; + case 97: goto st51; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st51: + if ( ++p == pe ) + goto _out51; +case 51: + switch( (*p) ) { + case 95: goto tr78; + case 107: goto tr102; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st52: + if ( ++p == pe ) + goto _out52; +case 52: + switch( (*p) ) { + case 95: goto tr78; + case 97: goto st53; + case 117: goto st55; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr103; +st53: + if ( ++p == pe ) + goto _out53; +case 53: + switch( (*p) ) { + case 95: goto tr78; + case 108: goto st54; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st54: + if ( ++p == pe ) + goto _out54; +case 54: + switch( (*p) ) { + case 95: goto tr78; + case 108: goto tr107; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st55: + if ( ++p == pe ) + goto _out55; +case 55: + switch( (*p) ) { + case 95: goto tr78; + case 114: goto st56; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st56: + if ( ++p == pe ) + goto _out56; +case 56: + switch( (*p) ) { + case 95: goto tr78; + case 115: goto tr109; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st57: + if ( ++p == pe ) + goto _out57; +case 57: + switch( (*p) ) { + case 95: goto tr78; + case 110: goto st58; + case 120: goto st61; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st58: + if ( ++p == pe ) + goto _out58; +case 58: + switch( (*p) ) { + case 95: goto tr78; + case 116: goto st59; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st59: + if ( ++p == pe ) + goto _out59; +case 59: + switch( (*p) ) { + case 95: goto tr78; + case 114: goto st60; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st60: + if ( ++p == pe ) + goto _out60; +case 60: + switch( (*p) ) { + case 95: goto tr78; + case 121: goto tr114; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st61: + if ( ++p == pe ) + goto _out61; +case 61: + switch( (*p) ) { + case 95: goto tr78; + case 101: goto st62; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st62: + if ( ++p == pe ) + goto _out62; +case 62: + switch( (*p) ) { + case 95: goto tr78; + case 99: goto tr116; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st63: + if ( ++p == pe ) + goto _out63; +case 63: + switch( (*p) ) { + case 95: goto tr78; + case 111: goto st64; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st64: + if ( ++p == pe ) + goto _out64; +case 64: + switch( (*p) ) { + case 95: goto tr78; + case 116: goto st65; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st65: + if ( ++p == pe ) + goto _out65; +case 65: + switch( (*p) ) { + case 95: goto tr78; + case 111: goto tr119; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st66: + if ( ++p == pe ) + goto _out66; +case 66: + switch( (*p) ) { + case 95: goto tr78; + case 111: goto st67; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st67: + if ( ++p == pe ) + goto _out67; +case 67: + switch( (*p) ) { + case 95: goto tr78; + case 108: goto st68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st68: + if ( ++p == pe ) + goto _out68; +case 68: + switch( (*p) ) { + case 95: goto tr78; + case 100: goto tr122; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st69: + if ( ++p == pe ) + goto _out69; +case 69: + switch( (*p) ) { + case 95: goto tr78; + case 101: goto st70; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st70: + if ( ++p == pe ) + goto _out70; +case 70: + switch( (*p) ) { + case 95: goto tr78; + case 120: goto st71; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st71: + if ( ++p == pe ) + goto _out71; +case 71: + switch( (*p) ) { + case 95: goto tr78; + case 116: goto tr125; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st72: + if ( ++p == pe ) + goto _out72; +case 72: + switch( (*p) ) { + case 95: goto tr78; + case 99: goto tr126; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st73: + if ( ++p == pe ) + goto _out73; +case 73: + switch( (*p) ) { + case 95: goto tr78; + case 101: goto st74; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st74: + if ( ++p == pe ) + goto _out74; +case 74: + switch( (*p) ) { + case 95: goto tr78; + case 116: goto tr128; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st75: + if ( ++p == pe ) + goto _out75; +case 75: + switch( (*p) ) { + case 95: goto tr78; + case 97: goto st76; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st76: + if ( ++p == pe ) + goto _out76; +case 76: + switch( (*p) ) { + case 95: goto tr78; + case 114: goto st77; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st77: + if ( ++p == pe ) + goto _out77; +case 77: + switch( (*p) ) { + case 95: goto tr78; + case 103: goto st78; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +st78: + if ( ++p == pe ) + goto _out78; +case 78: + switch( (*p) ) { + case 95: goto tr78; + case 115: goto tr132; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr78; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr78; + } else + goto tr78; + goto tr89; +tr133: +#line 686 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st79; +tr134: +#line 681 "rlscan.rl" + {tokend = p+1;{ + scan_error() << "unterminated OR literal" << endl; + }{p = ((tokend))-1;}} + goto st79; +tr135: +#line 676 "rlscan.rl" + {tokend = p+1;{ token( RE_Dash, 0, 0 ); }{p = ((tokend))-1;}} + goto st79; +tr137: +#line 679 "rlscan.rl" + {tokend = p+1;{ token( RE_SqClose ); {{p = ((tokend))-1;}{cs = stack[--top]; goto _again;}} }{p = ((tokend))-1;}} + goto st79; +tr138: +#line 673 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, tokstart+1, tokend ); }{p = ((tokend))-1;}} + goto st79; +tr139: +#line 672 "rlscan.rl" + {tokend = p+1;{ updateCol(); }{p = ((tokend))-1;}} + goto st79; +tr140: +#line 664 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\0' ); }{p = ((tokend))-1;}} + goto st79; +tr141: +#line 665 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\a' ); }{p = ((tokend))-1;}} + goto st79; +tr142: +#line 666 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\b' ); }{p = ((tokend))-1;}} + goto st79; +tr143: +#line 670 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\f' ); }{p = ((tokend))-1;}} + goto st79; +tr144: +#line 668 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\n' ); }{p = ((tokend))-1;}} + goto st79; +tr145: +#line 671 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\r' ); }{p = ((tokend))-1;}} + goto st79; +tr146: +#line 667 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\t' ); }{p = ((tokend))-1;}} + goto st79; +tr147: +#line 669 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\v' ); }{p = ((tokend))-1;}} + goto st79; +st79: +#line 1 "rlscan.rl" + {tokstart = 0;} + if ( ++p == pe ) + goto _out79; +case 79: +#line 1 "rlscan.rl" + {tokstart = p;} +#line 2531 "rlscan.cpp" + switch( (*p) ) { + case 0: goto tr134; + case 45: goto tr135; + case 92: goto st80; + case 93: goto tr137; + } + goto tr133; +st80: + if ( ++p == pe ) + goto _out80; +case 80: + switch( (*p) ) { + case 10: goto tr139; + case 48: goto tr140; + case 97: goto tr141; + case 98: goto tr142; + case 102: goto tr143; + case 110: goto tr144; + case 114: goto tr145; + case 116: goto tr146; + case 118: goto tr147; + } + goto tr138; +tr148: +#line 721 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st81; +tr149: +#line 716 "rlscan.rl" + {tokend = p+1;{ + scan_error() << "unterminated regular expression" << endl; + }{p = ((tokend))-1;}} + goto st81; +tr150: +#line 711 "rlscan.rl" + {tokend = p+1;{ token( RE_Star ); }{p = ((tokend))-1;}} + goto st81; +tr151: +#line 710 "rlscan.rl" + {tokend = p+1;{ token( RE_Dot ); }{p = ((tokend))-1;}} + goto st81; +tr155: +#line 704 "rlscan.rl" + {tokend = p;{ + token( RE_Slash, tokstart, tokend ); + {{p = ((tokend))-1;}{goto st88;}} + }{p = ((tokend))-1;}} + goto st81; +tr156: +#line 704 "rlscan.rl" + {tokend = p+1;{ + token( RE_Slash, tokstart, tokend ); + {{p = ((tokend))-1;}{goto st88;}} + }{p = ((tokend))-1;}} + goto st81; +tr157: +#line 713 "rlscan.rl" + {tokend = p;{ token( RE_SqOpen ); {{p = ((tokend))-1;}{stack[top++] = 81; goto st79;}} }{p = ((tokend))-1;}} + goto st81; +tr158: +#line 714 "rlscan.rl" + {tokend = p+1;{ token( RE_SqOpenNeg ); {{p = ((tokend))-1;}{stack[top++] = 81; goto st79;}} }{p = ((tokend))-1;}} + goto st81; +tr159: +#line 701 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, tokstart+1, tokend ); }{p = ((tokend))-1;}} + goto st81; +tr160: +#line 700 "rlscan.rl" + {tokend = p+1;{ updateCol(); }{p = ((tokend))-1;}} + goto st81; +tr161: +#line 692 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\0' ); }{p = ((tokend))-1;}} + goto st81; +tr162: +#line 693 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\a' ); }{p = ((tokend))-1;}} + goto st81; +tr163: +#line 694 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\b' ); }{p = ((tokend))-1;}} + goto st81; +tr164: +#line 698 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\f' ); }{p = ((tokend))-1;}} + goto st81; +tr165: +#line 696 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\n' ); }{p = ((tokend))-1;}} + goto st81; +tr166: +#line 699 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\r' ); }{p = ((tokend))-1;}} + goto st81; +tr167: +#line 695 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\t' ); }{p = ((tokend))-1;}} + goto st81; +tr168: +#line 697 "rlscan.rl" + {tokend = p+1;{ token( RE_Char, '\v' ); }{p = ((tokend))-1;}} + goto st81; +st81: +#line 1 "rlscan.rl" + {tokstart = 0;} + if ( ++p == pe ) + goto _out81; +case 81: +#line 1 "rlscan.rl" + {tokstart = p;} +#line 2643 "rlscan.cpp" + switch( (*p) ) { + case 0: goto tr149; + case 42: goto tr150; + case 46: goto tr151; + case 47: goto st82; + case 91: goto st83; + case 92: goto st84; + } + goto tr148; +st82: + if ( ++p == pe ) + goto _out82; +case 82: + if ( (*p) == 105 ) + goto tr156; + goto tr155; +st83: + if ( ++p == pe ) + goto _out83; +case 83: + if ( (*p) == 94 ) + goto tr158; + goto tr157; +st84: + if ( ++p == pe ) + goto _out84; +case 84: + switch( (*p) ) { + case 10: goto tr160; + case 48: goto tr161; + case 97: goto tr162; + case 98: goto tr163; + case 102: goto tr164; + case 110: goto tr165; + case 114: goto tr166; + case 116: goto tr167; + case 118: goto tr168; + } + goto tr159; +tr169: +#line 730 "rlscan.rl" + {tokend = p+1;{ + scan_error() << "unterminated write statement" << endl; + }{p = ((tokend))-1;}} + goto st85; +tr172: +#line 728 "rlscan.rl" + {tokend = p+1;{ token( ';' ); {{p = ((tokend))-1;}{goto st88;}} }{p = ((tokend))-1;}} + goto st85; +tr174: +#line 727 "rlscan.rl" + {tokend = p;{ updateCol(); }{p = ((tokend))-1;}} + goto st85; +tr175: +#line 726 "rlscan.rl" + {tokend = p;{ token( TK_Word, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st85; +st85: +#line 1 "rlscan.rl" + {tokstart = 0;} + if ( ++p == pe ) + goto _out85; +case 85: +#line 1 "rlscan.rl" + {tokstart = p;} +#line 2709 "rlscan.cpp" + switch( (*p) ) { + case 0: goto tr169; + case 32: goto st86; + case 59: goto tr172; + case 95: goto st87; + } + if ( (*p) < 65 ) { + if ( 9 <= (*p) && (*p) <= 10 ) + goto st86; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto st87; + } else + goto st87; + goto st0; +st0: + goto _out0; +st86: + if ( ++p == pe ) + goto _out86; +case 86: + if ( (*p) == 32 ) + goto st86; + if ( 9 <= (*p) && (*p) <= 10 ) + goto st86; + goto tr174; +st87: + if ( ++p == pe ) + goto _out87; +case 87: + if ( (*p) == 95 ) + goto st87; + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto st87; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto st87; + } else + goto st87; + goto tr175; +tr33: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } +#line 790 "rlscan.rl" + {tokend = p+1;{ updateCol(); }{p = ((tokend))-1;}} + goto st88; +tr37: +#line 777 "rlscan.rl" + {{ token( TK_UInt, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st88; +tr39: +#line 890 "rlscan.rl" + {{ token( *tokstart ); }{p = ((tokend))-1;}} + goto st88; +tr40: +#line 858 "rlscan.rl" + {tokend = p+1;{ + updateCol(); + endSection(); + {{p = ((tokend))-1;}{goto st23;}} + }{p = ((tokend))-1;}} + goto st88; +tr176: +#line 890 "rlscan.rl" + {tokend = p+1;{ token( *tokstart ); }{p = ((tokend))-1;}} + goto st88; +tr177: +#line 886 "rlscan.rl" + {tokend = p+1;{ + scan_error() << "unterminated ragel section" << endl; + }{p = ((tokend))-1;}} + goto st88; +tr179: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } +#line 867 "rlscan.rl" + {tokend = p+1;{ + updateCol(); + if ( singleLineSpec ) { + endSection(); + {{p = ((tokend))-1;}{goto st23;}} + } + }{p = ((tokend))-1;}} + goto st88; +tr188: +#line 787 "rlscan.rl" + {tokend = p+1;{ token( RE_Slash ); {{p = ((tokend))-1;}{goto st81;}} }{p = ((tokend))-1;}} + goto st88; +tr208: +#line 875 "rlscan.rl" + {tokend = p+1;{ + if ( lastToken == KW_Export || lastToken == KW_Entry ) + token( '{' ); + else { + token( '{' ); + curly_count = 1; + inlineBlockType = CurlyDelimited; + {{p = ((tokend))-1;}{goto st37;}} + } + }{p = ((tokend))-1;}} + goto st88; +tr211: +#line 864 "rlscan.rl" + {tokend = p;{ updateCol(); }{p = ((tokend))-1;}} + goto st88; +tr212: +#line 782 "rlscan.rl" + {tokend = p;{ token( TK_Literal, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st88; +tr213: +#line 782 "rlscan.rl" + {tokend = p+1;{ token( TK_Literal, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st88; +tr214: +#line 890 "rlscan.rl" + {tokend = p;{ token( *tokstart ); }{p = ((tokend))-1;}} + goto st88; +tr215: +#line 820 "rlscan.rl" + {tokend = p+1;{ token( TK_AllGblError ); }{p = ((tokend))-1;}} + goto st88; +tr216: +#line 804 "rlscan.rl" + {tokend = p+1;{ token( TK_AllFromState ); }{p = ((tokend))-1;}} + goto st88; +tr217: +#line 812 "rlscan.rl" + {tokend = p+1;{ token( TK_AllEOF ); }{p = ((tokend))-1;}} + goto st88; +tr218: +#line 839 "rlscan.rl" + {tokend = p+1;{ token( TK_AllCond ); }{p = ((tokend))-1;}} + goto st88; +tr219: +#line 828 "rlscan.rl" + {tokend = p+1;{ token( TK_AllLocalError ); }{p = ((tokend))-1;}} + goto st88; +tr220: +#line 796 "rlscan.rl" + {tokend = p+1;{ token( TK_AllToState ); }{p = ((tokend))-1;}} + goto st88; +tr221: +#line 821 "rlscan.rl" + {tokend = p+1;{ token( TK_FinalGblError ); }{p = ((tokend))-1;}} + goto st88; +tr222: +#line 805 "rlscan.rl" + {tokend = p+1;{ token( TK_FinalFromState ); }{p = ((tokend))-1;}} + goto st88; +tr223: +#line 813 "rlscan.rl" + {tokend = p+1;{ token( TK_FinalEOF ); }{p = ((tokend))-1;}} + goto st88; +tr224: +#line 840 "rlscan.rl" + {tokend = p+1;{ token( TK_LeavingCond ); }{p = ((tokend))-1;}} + goto st88; +tr225: +#line 829 "rlscan.rl" + {tokend = p+1;{ token( TK_FinalLocalError ); }{p = ((tokend))-1;}} + goto st88; +tr226: +#line 797 "rlscan.rl" + {tokend = p+1;{ token( TK_FinalToState ); }{p = ((tokend))-1;}} + goto st88; +tr227: +#line 843 "rlscan.rl" + {tokend = p+1;{ token( TK_StarStar ); }{p = ((tokend))-1;}} + goto st88; +tr228: +#line 844 "rlscan.rl" + {tokend = p+1;{ token( TK_DashDash ); }{p = ((tokend))-1;}} + goto st88; +tr229: +#line 845 "rlscan.rl" + {tokend = p+1;{ token( TK_Arrow ); }{p = ((tokend))-1;}} + goto st88; +tr230: +#line 842 "rlscan.rl" + {tokend = p+1;{ token( TK_DotDot ); }{p = ((tokend))-1;}} + goto st88; +tr231: +#line 777 "rlscan.rl" + {tokend = p;{ token( TK_UInt, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st88; +tr233: +#line 778 "rlscan.rl" + {tokend = p;{ token( TK_Hex, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st88; +tr234: +#line 856 "rlscan.rl" + {tokend = p+1;{ token( TK_NameSep, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st88; +tr235: +#line 792 "rlscan.rl" + {tokend = p+1;{ token( TK_ColonEquals ); }{p = ((tokend))-1;}} + goto st88; +tr237: +#line 848 "rlscan.rl" + {tokend = p;{ token( TK_ColonGt ); }{p = ((tokend))-1;}} + goto st88; +tr238: +#line 849 "rlscan.rl" + {tokend = p+1;{ token( TK_ColonGtGt ); }{p = ((tokend))-1;}} + goto st88; +tr239: +#line 822 "rlscan.rl" + {tokend = p+1;{ token( TK_NotStartGblError ); }{p = ((tokend))-1;}} + goto st88; +tr240: +#line 806 "rlscan.rl" + {tokend = p+1;{ token( TK_NotStartFromState ); }{p = ((tokend))-1;}} + goto st88; +tr241: +#line 814 "rlscan.rl" + {tokend = p+1;{ token( TK_NotStartEOF ); }{p = ((tokend))-1;}} + goto st88; +tr242: +#line 850 "rlscan.rl" + {tokend = p+1;{ token( TK_LtColon ); }{p = ((tokend))-1;}} + goto st88; +tr244: +#line 830 "rlscan.rl" + {tokend = p+1;{ token( TK_NotStartLocalError ); }{p = ((tokend))-1;}} + goto st88; +tr245: +#line 798 "rlscan.rl" + {tokend = p+1;{ token( TK_NotStartToState ); }{p = ((tokend))-1;}} + goto st88; +tr246: +#line 835 "rlscan.rl" + {tokend = p;{ token( TK_Middle ); }{p = ((tokend))-1;}} + goto st88; +tr247: +#line 824 "rlscan.rl" + {tokend = p+1;{ token( TK_MiddleGblError ); }{p = ((tokend))-1;}} + goto st88; +tr248: +#line 808 "rlscan.rl" + {tokend = p+1;{ token( TK_MiddleFromState ); }{p = ((tokend))-1;}} + goto st88; +tr249: +#line 816 "rlscan.rl" + {tokend = p+1;{ token( TK_MiddleEOF ); }{p = ((tokend))-1;}} + goto st88; +tr250: +#line 832 "rlscan.rl" + {tokend = p+1;{ token( TK_MiddleLocalError ); }{p = ((tokend))-1;}} + goto st88; +tr251: +#line 800 "rlscan.rl" + {tokend = p+1;{ token( TK_MiddleToState ); }{p = ((tokend))-1;}} + goto st88; +tr252: +#line 846 "rlscan.rl" + {tokend = p+1;{ token( TK_DoubleArrow ); }{p = ((tokend))-1;}} + goto st88; +tr253: +#line 819 "rlscan.rl" + {tokend = p+1;{ token( TK_StartGblError ); }{p = ((tokend))-1;}} + goto st88; +tr254: +#line 803 "rlscan.rl" + {tokend = p+1;{ token( TK_StartFromState ); }{p = ((tokend))-1;}} + goto st88; +tr255: +#line 811 "rlscan.rl" + {tokend = p+1;{ token( TK_StartEOF ); }{p = ((tokend))-1;}} + goto st88; +tr256: +#line 838 "rlscan.rl" + {tokend = p+1;{ token( TK_StartCond ); }{p = ((tokend))-1;}} + goto st88; +tr257: +#line 827 "rlscan.rl" + {tokend = p+1;{ token( TK_StartLocalError ); }{p = ((tokend))-1;}} + goto st88; +tr258: +#line 795 "rlscan.rl" + {tokend = p+1;{ token( TK_StartToState ); }{p = ((tokend))-1;}} + goto st88; +tr259: +#line 823 "rlscan.rl" + {tokend = p+1;{ token( TK_NotFinalGblError ); }{p = ((tokend))-1;}} + goto st88; +tr260: +#line 807 "rlscan.rl" + {tokend = p+1;{ token( TK_NotFinalFromState ); }{p = ((tokend))-1;}} + goto st88; +tr261: +#line 815 "rlscan.rl" + {tokend = p+1;{ token( TK_NotFinalEOF ); }{p = ((tokend))-1;}} + goto st88; +tr262: +#line 831 "rlscan.rl" + {tokend = p+1;{ token( TK_NotFinalLocalError ); }{p = ((tokend))-1;}} + goto st88; +tr263: +#line 799 "rlscan.rl" + {tokend = p+1;{ token( TK_NotFinalToState ); }{p = ((tokend))-1;}} + goto st88; +tr264: +#line 1 "rlscan.rl" + { switch( act ) { + case 62: + { token( KW_Machine ); } + break; + case 63: + { token( KW_Include ); } + break; + case 64: + { token( KW_Import ); } + break; + case 65: + { + token( KW_Write ); + {{p = ((tokend))-1;}{goto st85;}} + } + break; + case 66: + { token( KW_Action ); } + break; + case 67: + { token( KW_AlphType ); } + break; + case 68: + { + token( KW_GetKey ); + inlineBlockType = SemiTerminated; + {{p = ((tokend))-1;}{goto st37;}} + } + break; + case 69: + { + token( KW_Access ); + inlineBlockType = SemiTerminated; + {{p = ((tokend))-1;}{goto st37;}} + } + break; + case 70: + { + token( KW_Variable ); + inlineBlockType = SemiTerminated; + {{p = ((tokend))-1;}{goto st37;}} + } + break; + case 71: + { token( KW_When ); } + break; + case 72: + { token( KW_Eof ); } + break; + case 73: + { token( KW_Err ); } + break; + case 74: + { token( KW_Lerr ); } + break; + case 75: + { token( KW_To ); } + break; + case 76: + { token( KW_From ); } + break; + case 77: + { token( KW_Export ); } + break; + case 78: + { token( TK_Word, tokstart, tokend ); } + break; + default: break; + } + {p = ((tokend))-1;}} + goto st88; +tr265: +#line 784 "rlscan.rl" + {tokend = p;{ token( RE_SqOpen ); {{p = ((tokend))-1;}{stack[top++] = 88; goto st79;}} }{p = ((tokend))-1;}} + goto st88; +tr266: +#line 785 "rlscan.rl" + {tokend = p+1;{ token( RE_SqOpenNeg ); {{p = ((tokend))-1;}{stack[top++] = 88; goto st79;}} }{p = ((tokend))-1;}} + goto st88; +tr267: +#line 774 "rlscan.rl" + {tokend = p;{ token( TK_Word, tokstart, tokend ); }{p = ((tokend))-1;}} + goto st88; +tr336: +#line 853 "rlscan.rl" + {tokend = p+1;{ token( TK_BarStar ); }{p = ((tokend))-1;}} + goto st88; +st88: +#line 1 "rlscan.rl" + {tokstart = 0;} + if ( ++p == pe ) + goto _out88; +case 88: +#line 1 "rlscan.rl" + {tokstart = p;} +#line 3117 "rlscan.cpp" + switch( (*p) ) { + case 0: goto tr177; + case 9: goto st89; + case 10: goto tr179; + case 13: goto st89; + case 32: goto st89; + case 34: goto tr180; + case 35: goto tr181; + case 36: goto st93; + case 37: goto st94; + case 39: goto tr184; + case 42: goto st96; + case 45: goto st97; + case 46: goto st98; + case 47: goto tr188; + case 48: goto tr189; + case 58: goto st102; + case 60: goto st104; + case 61: goto st106; + case 62: goto st107; + case 64: goto st108; + case 91: goto st110; + case 95: goto tr196; + case 97: goto st111; + case 101: goto st125; + case 102: goto st132; + case 103: goto st135; + case 105: goto st140; + case 108: goto st150; + case 109: goto st153; + case 116: goto st159; + case 118: goto st160; + case 119: goto st167; + case 123: goto tr208; + case 124: goto st173; + case 125: goto tr210; + } + if ( (*p) < 65 ) { + if ( 49 <= (*p) && (*p) <= 57 ) + goto st100; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr176; +st89: + if ( ++p == pe ) + goto _out89; +case 89: + switch( (*p) ) { + case 9: goto st89; + case 13: goto st89; + case 32: goto st89; + } + goto tr211; +tr180: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st90; +st90: + if ( ++p == pe ) + goto _out90; +case 90: +#line 3182 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr29; + case 34: goto st91; + case 92: goto st17; + } + goto st16; +tr29: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } + goto st16; +st16: + if ( ++p == pe ) + goto _out16; +case 16: +#line 3201 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr29; + case 34: goto st91; + case 92: goto st17; + } + goto st16; +st91: + if ( ++p == pe ) + goto _out91; +case 91: + if ( (*p) == 105 ) + goto tr213; + goto tr212; +st17: + if ( ++p == pe ) + goto _out17; +case 17: + if ( (*p) == 10 ) + goto tr29; + goto st16; +tr181: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st92; +st92: + if ( ++p == pe ) + goto _out92; +case 92: +#line 3230 "rlscan.cpp" + if ( (*p) == 10 ) + goto tr33; + goto st18; +st18: + if ( ++p == pe ) + goto _out18; +case 18: + if ( (*p) == 10 ) + goto tr33; + goto st18; +st93: + if ( ++p == pe ) + goto _out93; +case 93: + switch( (*p) ) { + case 33: goto tr215; + case 42: goto tr216; + case 47: goto tr217; + case 63: goto tr218; + case 94: goto tr219; + case 126: goto tr220; + } + goto tr214; +st94: + if ( ++p == pe ) + goto _out94; +case 94: + switch( (*p) ) { + case 33: goto tr221; + case 42: goto tr222; + case 47: goto tr223; + case 63: goto tr224; + case 94: goto tr225; + case 126: goto tr226; + } + goto tr214; +tr184: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st95; +st95: + if ( ++p == pe ) + goto _out95; +case 95: +#line 3275 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr35; + case 39: goto st91; + case 92: goto st20; + } + goto st19; +tr35: +#line 532 "rlscan.rl" + { + lastnl = p; + column = 0; + line++; + } + goto st19; +st19: + if ( ++p == pe ) + goto _out19; +case 19: +#line 3294 "rlscan.cpp" + switch( (*p) ) { + case 10: goto tr35; + case 39: goto st91; + case 92: goto st20; + } + goto st19; +st20: + if ( ++p == pe ) + goto _out20; +case 20: + if ( (*p) == 10 ) + goto tr35; + goto st19; +st96: + if ( ++p == pe ) + goto _out96; +case 96: + if ( (*p) == 42 ) + goto tr227; + goto tr214; +st97: + if ( ++p == pe ) + goto _out97; +case 97: + switch( (*p) ) { + case 45: goto tr228; + case 62: goto tr229; + } + goto tr214; +st98: + if ( ++p == pe ) + goto _out98; +case 98: + if ( (*p) == 46 ) + goto tr230; + goto tr214; +tr189: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st99; +st99: + if ( ++p == pe ) + goto _out99; +case 99: +#line 3339 "rlscan.cpp" + if ( (*p) == 120 ) + goto st21; + if ( 48 <= (*p) && (*p) <= 57 ) + goto st100; + goto tr231; +st100: + if ( ++p == pe ) + goto _out100; +case 100: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st100; + goto tr231; +st21: + if ( ++p == pe ) + goto _out21; +case 21: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto st101; + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) + goto st101; + } else + goto st101; + goto tr37; +st101: + if ( ++p == pe ) + goto _out101; +case 101: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto st101; + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) + goto st101; + } else + goto st101; + goto tr233; +st102: + if ( ++p == pe ) + goto _out102; +case 102: + switch( (*p) ) { + case 58: goto tr234; + case 61: goto tr235; + case 62: goto st103; + } + goto tr214; +st103: + if ( ++p == pe ) + goto _out103; +case 103: + if ( (*p) == 62 ) + goto tr238; + goto tr237; +st104: + if ( ++p == pe ) + goto _out104; +case 104: + switch( (*p) ) { + case 33: goto tr239; + case 42: goto tr240; + case 47: goto tr241; + case 58: goto tr242; + case 62: goto st105; + case 94: goto tr244; + case 126: goto tr245; + } + goto tr214; +st105: + if ( ++p == pe ) + goto _out105; +case 105: + switch( (*p) ) { + case 33: goto tr247; + case 42: goto tr248; + case 47: goto tr249; + case 94: goto tr250; + case 126: goto tr251; + } + goto tr246; +st106: + if ( ++p == pe ) + goto _out106; +case 106: + if ( (*p) == 62 ) + goto tr252; + goto tr214; +st107: + if ( ++p == pe ) + goto _out107; +case 107: + switch( (*p) ) { + case 33: goto tr253; + case 42: goto tr254; + case 47: goto tr255; + case 63: goto tr256; + case 94: goto tr257; + case 126: goto tr258; + } + goto tr214; +st108: + if ( ++p == pe ) + goto _out108; +case 108: + switch( (*p) ) { + case 33: goto tr259; + case 42: goto tr260; + case 47: goto tr261; + case 94: goto tr262; + case 126: goto tr263; + } + goto tr214; +tr196: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 774 "rlscan.rl" + {act = 78;} + goto st109; +tr274: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 755 "rlscan.rl" + {act = 69;} + goto st109; +tr277: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 744 "rlscan.rl" + {act = 66;} + goto st109; +tr283: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 745 "rlscan.rl" + {act = 67;} + goto st109; +tr287: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 766 "rlscan.rl" + {act = 72;} + goto st109; +tr288: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 767 "rlscan.rl" + {act = 73;} + goto st109; +tr292: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 771 "rlscan.rl" + {act = 77;} + goto st109; +tr295: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 770 "rlscan.rl" + {act = 76;} + goto st109; +tr300: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 750 "rlscan.rl" + {act = 68;} + goto st109; +tr306: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 739 "rlscan.rl" + {act = 64;} + goto st109; +tr311: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 738 "rlscan.rl" + {act = 63;} + goto st109; +tr314: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 768 "rlscan.rl" + {act = 74;} + goto st109; +tr320: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 737 "rlscan.rl" + {act = 62;} + goto st109; +tr321: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 769 "rlscan.rl" + {act = 75;} + goto st109; +tr328: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 760 "rlscan.rl" + {act = 70;} + goto st109; +tr332: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 765 "rlscan.rl" + {act = 71;} + goto st109; +tr335: +#line 1 "rlscan.rl" + {tokend = p+1;} +#line 740 "rlscan.rl" + {act = 65;} + goto st109; +st109: + if ( ++p == pe ) + goto _out109; +case 109: +#line 3559 "rlscan.cpp" + if ( (*p) == 95 ) + goto tr196; + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr264; +st110: + if ( ++p == pe ) + goto _out110; +case 110: + if ( (*p) == 94 ) + goto tr266; + goto tr265; +st111: + if ( ++p == pe ) + goto _out111; +case 111: + switch( (*p) ) { + case 95: goto tr196; + case 99: goto st112; + case 108: goto st119; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st112: + if ( ++p == pe ) + goto _out112; +case 112: + switch( (*p) ) { + case 95: goto tr196; + case 99: goto st113; + case 116: goto st116; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st113: + if ( ++p == pe ) + goto _out113; +case 113: + switch( (*p) ) { + case 95: goto tr196; + case 101: goto st114; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st114: + if ( ++p == pe ) + goto _out114; +case 114: + switch( (*p) ) { + case 95: goto tr196; + case 115: goto st115; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st115: + if ( ++p == pe ) + goto _out115; +case 115: + switch( (*p) ) { + case 95: goto tr196; + case 115: goto tr274; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st116: + if ( ++p == pe ) + goto _out116; +case 116: + switch( (*p) ) { + case 95: goto tr196; + case 105: goto st117; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st117: + if ( ++p == pe ) + goto _out117; +case 117: + switch( (*p) ) { + case 95: goto tr196; + case 111: goto st118; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st118: + if ( ++p == pe ) + goto _out118; +case 118: + switch( (*p) ) { + case 95: goto tr196; + case 110: goto tr277; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st119: + if ( ++p == pe ) + goto _out119; +case 119: + switch( (*p) ) { + case 95: goto tr196; + case 112: goto st120; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st120: + if ( ++p == pe ) + goto _out120; +case 120: + switch( (*p) ) { + case 95: goto tr196; + case 104: goto st121; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st121: + if ( ++p == pe ) + goto _out121; +case 121: + switch( (*p) ) { + case 95: goto tr196; + case 116: goto st122; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st122: + if ( ++p == pe ) + goto _out122; +case 122: + switch( (*p) ) { + case 95: goto tr196; + case 121: goto st123; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st123: + if ( ++p == pe ) + goto _out123; +case 123: + switch( (*p) ) { + case 95: goto tr196; + case 112: goto st124; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st124: + if ( ++p == pe ) + goto _out124; +case 124: + switch( (*p) ) { + case 95: goto tr196; + case 101: goto tr283; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st125: + if ( ++p == pe ) + goto _out125; +case 125: + switch( (*p) ) { + case 95: goto tr196; + case 111: goto st126; + case 114: goto st127; + case 120: goto st128; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st126: + if ( ++p == pe ) + goto _out126; +case 126: + switch( (*p) ) { + case 95: goto tr196; + case 102: goto tr287; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st127: + if ( ++p == pe ) + goto _out127; +case 127: + switch( (*p) ) { + case 95: goto tr196; + case 114: goto tr288; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st128: + if ( ++p == pe ) + goto _out128; +case 128: + switch( (*p) ) { + case 95: goto tr196; + case 112: goto st129; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st129: + if ( ++p == pe ) + goto _out129; +case 129: + switch( (*p) ) { + case 95: goto tr196; + case 111: goto st130; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st130: + if ( ++p == pe ) + goto _out130; +case 130: + switch( (*p) ) { + case 95: goto tr196; + case 114: goto st131; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st131: + if ( ++p == pe ) + goto _out131; +case 131: + switch( (*p) ) { + case 95: goto tr196; + case 116: goto tr292; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st132: + if ( ++p == pe ) + goto _out132; +case 132: + switch( (*p) ) { + case 95: goto tr196; + case 114: goto st133; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st133: + if ( ++p == pe ) + goto _out133; +case 133: + switch( (*p) ) { + case 95: goto tr196; + case 111: goto st134; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st134: + if ( ++p == pe ) + goto _out134; +case 134: + switch( (*p) ) { + case 95: goto tr196; + case 109: goto tr295; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st135: + if ( ++p == pe ) + goto _out135; +case 135: + switch( (*p) ) { + case 95: goto tr196; + case 101: goto st136; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st136: + if ( ++p == pe ) + goto _out136; +case 136: + switch( (*p) ) { + case 95: goto tr196; + case 116: goto st137; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st137: + if ( ++p == pe ) + goto _out137; +case 137: + switch( (*p) ) { + case 95: goto tr196; + case 107: goto st138; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st138: + if ( ++p == pe ) + goto _out138; +case 138: + switch( (*p) ) { + case 95: goto tr196; + case 101: goto st139; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st139: + if ( ++p == pe ) + goto _out139; +case 139: + switch( (*p) ) { + case 95: goto tr196; + case 121: goto tr300; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st140: + if ( ++p == pe ) + goto _out140; +case 140: + switch( (*p) ) { + case 95: goto tr196; + case 109: goto st141; + case 110: goto st145; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st141: + if ( ++p == pe ) + goto _out141; +case 141: + switch( (*p) ) { + case 95: goto tr196; + case 112: goto st142; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st142: + if ( ++p == pe ) + goto _out142; +case 142: + switch( (*p) ) { + case 95: goto tr196; + case 111: goto st143; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st143: + if ( ++p == pe ) + goto _out143; +case 143: + switch( (*p) ) { + case 95: goto tr196; + case 114: goto st144; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st144: + if ( ++p == pe ) + goto _out144; +case 144: + switch( (*p) ) { + case 95: goto tr196; + case 116: goto tr306; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st145: + if ( ++p == pe ) + goto _out145; +case 145: + switch( (*p) ) { + case 95: goto tr196; + case 99: goto st146; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st146: + if ( ++p == pe ) + goto _out146; +case 146: + switch( (*p) ) { + case 95: goto tr196; + case 108: goto st147; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st147: + if ( ++p == pe ) + goto _out147; +case 147: + switch( (*p) ) { + case 95: goto tr196; + case 117: goto st148; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st148: + if ( ++p == pe ) + goto _out148; +case 148: + switch( (*p) ) { + case 95: goto tr196; + case 100: goto st149; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st149: + if ( ++p == pe ) + goto _out149; +case 149: + switch( (*p) ) { + case 95: goto tr196; + case 101: goto tr311; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st150: + if ( ++p == pe ) + goto _out150; +case 150: + switch( (*p) ) { + case 95: goto tr196; + case 101: goto st151; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st151: + if ( ++p == pe ) + goto _out151; +case 151: + switch( (*p) ) { + case 95: goto tr196; + case 114: goto st152; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st152: + if ( ++p == pe ) + goto _out152; +case 152: + switch( (*p) ) { + case 95: goto tr196; + case 114: goto tr314; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st153: + if ( ++p == pe ) + goto _out153; +case 153: + switch( (*p) ) { + case 95: goto tr196; + case 97: goto st154; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st154: + if ( ++p == pe ) + goto _out154; +case 154: + switch( (*p) ) { + case 95: goto tr196; + case 99: goto st155; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st155: + if ( ++p == pe ) + goto _out155; +case 155: + switch( (*p) ) { + case 95: goto tr196; + case 104: goto st156; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st156: + if ( ++p == pe ) + goto _out156; +case 156: + switch( (*p) ) { + case 95: goto tr196; + case 105: goto st157; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st157: + if ( ++p == pe ) + goto _out157; +case 157: + switch( (*p) ) { + case 95: goto tr196; + case 110: goto st158; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st158: + if ( ++p == pe ) + goto _out158; +case 158: + switch( (*p) ) { + case 95: goto tr196; + case 101: goto tr320; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st159: + if ( ++p == pe ) + goto _out159; +case 159: + switch( (*p) ) { + case 95: goto tr196; + case 111: goto tr321; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st160: + if ( ++p == pe ) + goto _out160; +case 160: + switch( (*p) ) { + case 95: goto tr196; + case 97: goto st161; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st161: + if ( ++p == pe ) + goto _out161; +case 161: + switch( (*p) ) { + case 95: goto tr196; + case 114: goto st162; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st162: + if ( ++p == pe ) + goto _out162; +case 162: + switch( (*p) ) { + case 95: goto tr196; + case 105: goto st163; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st163: + if ( ++p == pe ) + goto _out163; +case 163: + switch( (*p) ) { + case 95: goto tr196; + case 97: goto st164; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st164: + if ( ++p == pe ) + goto _out164; +case 164: + switch( (*p) ) { + case 95: goto tr196; + case 98: goto st165; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st165: + if ( ++p == pe ) + goto _out165; +case 165: + switch( (*p) ) { + case 95: goto tr196; + case 108: goto st166; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st166: + if ( ++p == pe ) + goto _out166; +case 166: + switch( (*p) ) { + case 95: goto tr196; + case 101: goto tr328; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st167: + if ( ++p == pe ) + goto _out167; +case 167: + switch( (*p) ) { + case 95: goto tr196; + case 104: goto st168; + case 114: goto st170; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st168: + if ( ++p == pe ) + goto _out168; +case 168: + switch( (*p) ) { + case 95: goto tr196; + case 101: goto st169; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st169: + if ( ++p == pe ) + goto _out169; +case 169: + switch( (*p) ) { + case 95: goto tr196; + case 110: goto tr332; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st170: + if ( ++p == pe ) + goto _out170; +case 170: + switch( (*p) ) { + case 95: goto tr196; + case 105: goto st171; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st171: + if ( ++p == pe ) + goto _out171; +case 171: + switch( (*p) ) { + case 95: goto tr196; + case 116: goto st172; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st172: + if ( ++p == pe ) + goto _out172; +case 172: + switch( (*p) ) { + case 95: goto tr196; + case 101: goto tr335; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr196; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr196; + } else + goto tr196; + goto tr267; +st173: + if ( ++p == pe ) + goto _out173; +case 173: + if ( (*p) == 42 ) + goto tr336; + goto tr214; +tr210: +#line 1 "rlscan.rl" + {tokend = p+1;} + goto st174; +st174: + if ( ++p == pe ) + goto _out174; +case 174: +#line 4653 "rlscan.cpp" + if ( (*p) == 37 ) + goto st22; + goto tr214; +st22: + if ( ++p == pe ) + goto _out22; +case 22: + if ( (*p) == 37 ) + goto tr40; + goto tr39; + } + _out23: cs = 23; goto _out; + _out24: cs = 24; goto _out; + _out25: cs = 25; goto _out; + _out1: cs = 1; goto _out; + _out2: cs = 2; goto _out; + _out26: cs = 26; goto _out; + _out27: cs = 27; goto _out; + _out28: cs = 28; goto _out; + _out3: cs = 3; goto _out; + _out4: cs = 4; goto _out; + _out29: cs = 29; goto _out; + _out5: cs = 5; goto _out; + _out6: cs = 6; goto _out; + _out7: cs = 7; goto _out; + _out30: cs = 30; goto _out; + _out31: cs = 31; goto _out; + _out32: cs = 32; goto _out; + _out33: cs = 33; goto _out; + _out34: cs = 34; goto _out; + _out35: cs = 35; goto _out; + _out36: cs = 36; goto _out; + _out37: cs = 37; goto _out; + _out38: cs = 38; goto _out; + _out39: cs = 39; goto _out; + _out8: cs = 8; goto _out; + _out9: cs = 9; goto _out; + _out40: cs = 40; goto _out; + _out10: cs = 10; goto _out; + _out11: cs = 11; goto _out; + _out41: cs = 41; goto _out; + _out12: cs = 12; goto _out; + _out13: cs = 13; goto _out; + _out14: cs = 14; goto _out; + _out42: cs = 42; goto _out; + _out43: cs = 43; goto _out; + _out15: cs = 15; goto _out; + _out44: cs = 44; goto _out; + _out45: cs = 45; goto _out; + _out46: cs = 46; goto _out; + _out47: cs = 47; goto _out; + _out48: cs = 48; goto _out; + _out49: cs = 49; goto _out; + _out50: cs = 50; goto _out; + _out51: cs = 51; goto _out; + _out52: cs = 52; goto _out; + _out53: cs = 53; goto _out; + _out54: cs = 54; goto _out; + _out55: cs = 55; goto _out; + _out56: cs = 56; goto _out; + _out57: cs = 57; goto _out; + _out58: cs = 58; goto _out; + _out59: cs = 59; goto _out; + _out60: cs = 60; goto _out; + _out61: cs = 61; goto _out; + _out62: cs = 62; goto _out; + _out63: cs = 63; goto _out; + _out64: cs = 64; goto _out; + _out65: cs = 65; goto _out; + _out66: cs = 66; goto _out; + _out67: cs = 67; goto _out; + _out68: cs = 68; goto _out; + _out69: cs = 69; goto _out; + _out70: cs = 70; goto _out; + _out71: cs = 71; goto _out; + _out72: cs = 72; goto _out; + _out73: cs = 73; goto _out; + _out74: cs = 74; goto _out; + _out75: cs = 75; goto _out; + _out76: cs = 76; goto _out; + _out77: cs = 77; goto _out; + _out78: cs = 78; goto _out; + _out79: cs = 79; goto _out; + _out80: cs = 80; goto _out; + _out81: cs = 81; goto _out; + _out82: cs = 82; goto _out; + _out83: cs = 83; goto _out; + _out84: cs = 84; goto _out; + _out85: cs = 85; goto _out; + _out0: cs = 0; goto _out; + _out86: cs = 86; goto _out; + _out87: cs = 87; goto _out; + _out88: cs = 88; goto _out; + _out89: cs = 89; goto _out; + _out90: cs = 90; goto _out; + _out16: cs = 16; goto _out; + _out91: cs = 91; goto _out; + _out17: cs = 17; goto _out; + _out92: cs = 92; goto _out; + _out18: cs = 18; goto _out; + _out93: cs = 93; goto _out; + _out94: cs = 94; goto _out; + _out95: cs = 95; goto _out; + _out19: cs = 19; goto _out; + _out20: cs = 20; goto _out; + _out96: cs = 96; goto _out; + _out97: cs = 97; goto _out; + _out98: cs = 98; goto _out; + _out99: cs = 99; goto _out; + _out100: cs = 100; goto _out; + _out21: cs = 21; goto _out; + _out101: cs = 101; goto _out; + _out102: cs = 102; goto _out; + _out103: cs = 103; goto _out; + _out104: cs = 104; goto _out; + _out105: cs = 105; goto _out; + _out106: cs = 106; goto _out; + _out107: cs = 107; goto _out; + _out108: cs = 108; goto _out; + _out109: cs = 109; goto _out; + _out110: cs = 110; goto _out; + _out111: cs = 111; goto _out; + _out112: cs = 112; goto _out; + _out113: cs = 113; goto _out; + _out114: cs = 114; goto _out; + _out115: cs = 115; goto _out; + _out116: cs = 116; goto _out; + _out117: cs = 117; goto _out; + _out118: cs = 118; goto _out; + _out119: cs = 119; goto _out; + _out120: cs = 120; goto _out; + _out121: cs = 121; goto _out; + _out122: cs = 122; goto _out; + _out123: cs = 123; goto _out; + _out124: cs = 124; goto _out; + _out125: cs = 125; goto _out; + _out126: cs = 126; goto _out; + _out127: cs = 127; goto _out; + _out128: cs = 128; goto _out; + _out129: cs = 129; goto _out; + _out130: cs = 130; goto _out; + _out131: cs = 131; goto _out; + _out132: cs = 132; goto _out; + _out133: cs = 133; goto _out; + _out134: cs = 134; goto _out; + _out135: cs = 135; goto _out; + _out136: cs = 136; goto _out; + _out137: cs = 137; goto _out; + _out138: cs = 138; goto _out; + _out139: cs = 139; goto _out; + _out140: cs = 140; goto _out; + _out141: cs = 141; goto _out; + _out142: cs = 142; goto _out; + _out143: cs = 143; goto _out; + _out144: cs = 144; goto _out; + _out145: cs = 145; goto _out; + _out146: cs = 146; goto _out; + _out147: cs = 147; goto _out; + _out148: cs = 148; goto _out; + _out149: cs = 149; goto _out; + _out150: cs = 150; goto _out; + _out151: cs = 151; goto _out; + _out152: cs = 152; goto _out; + _out153: cs = 153; goto _out; + _out154: cs = 154; goto _out; + _out155: cs = 155; goto _out; + _out156: cs = 156; goto _out; + _out157: cs = 157; goto _out; + _out158: cs = 158; goto _out; + _out159: cs = 159; goto _out; + _out160: cs = 160; goto _out; + _out161: cs = 161; goto _out; + _out162: cs = 162; goto _out; + _out163: cs = 163; goto _out; + _out164: cs = 164; goto _out; + _out165: cs = 165; goto _out; + _out166: cs = 166; goto _out; + _out167: cs = 167; goto _out; + _out168: cs = 168; goto _out; + _out169: cs = 169; goto _out; + _out170: cs = 170; goto _out; + _out171: cs = 171; goto _out; + _out172: cs = 172; goto _out; + _out173: cs = 173; goto _out; + _out174: cs = 174; goto _out; + _out22: cs = 22; goto _out; + + _out: {} + } +#line 972 "rlscan.rl" + + /* Check if we failed. */ + if ( cs == rlscan_error ) { + /* Machine failed before finding a token. I'm not yet sure if this + * is reachable. */ + scan_error() << "scanner error" << endl; + exit(1); + } + + /* Decide if we need to preserve anything. */ + char *preserve = tokstart; + + /* Now set up the prefix. */ + if ( preserve == 0 ) + have = 0; + else { + /* There is data that needs to be shifted over. */ + have = pe - preserve; + memmove( buf, preserve, have ); + unsigned int shiftback = preserve - buf; + if ( tokstart != 0 ) + tokstart -= shiftback; + tokend -= shiftback; + + preserve = buf; + } + } + + delete[] buf; +} + +void scan( char *fileName, istream &input, ostream &output ) +{ +} diff --git a/contrib/tools/ragel5/ragel/rlscan.h b/contrib/tools/ragel5/ragel/rlscan.h new file mode 100644 index 00000000000..e6302aa4c94 --- /dev/null +++ b/contrib/tools/ragel5/ragel/rlscan.h @@ -0,0 +1,161 @@ +/* + * Copyright 2007 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _RLSCAN_H +#define _RLSCAN_H + +#include <iostream> +#include "rlscan.h" +#include "vector.h" +#include "rlparse.h" +#include "parsedata.h" +#include "avltree.h" +#include "vector.h" + +using std::istream; +using std::ostream; + +extern char *Parser_lelNames[]; + +/* This is used for tracking the current stack of include file/machine pairs. It is + * is used to detect and recursive include structure. */ +struct IncludeStackItem +{ + IncludeStackItem(const char *fileName, char *sectionName ) + : fileName(fileName), sectionName(sectionName) {} + + const char *fileName; + char *sectionName; +}; + +typedef Vector<IncludeStackItem> IncludeStack; + +inline char* resolvePath(const char* rel, const char* abs) { + const size_t l1 = strlen(rel); + const size_t l2 = strlen(abs); + char* ret = new char[l1 + l2 + 1]; + + const char* p = strrchr(abs, '/') + 1; + const size_t l3 = p - abs; + + memcpy(ret, abs, l3); + strcpy(ret + l3, rel); + + return ret; +} + +struct Scanner +{ + Scanner(const char *fileName, istream &input, ostream &output, + Parser *inclToParser, char *inclSectionTarg, + int includeDepth, bool importMachines ) + : + fileName(fileName), input(input), output(output), + inclToParser(inclToParser), + inclSectionTarg(inclSectionTarg), + includeDepth(includeDepth), + importMachines(importMachines), + cur_token(0), + line(1), column(1), lastnl(0), + parser(0), ignoreSection(false), + parserExistsError(false), + whitespaceOn(true), + lastToken(0) + {} + + bool recursiveInclude(const char *inclFileName, char *inclSectionName ); + + char *prepareFileName( char *inclFileName, int len ) + { + if (*inclFileName == '\"') { + inclFileName[len - 1] = 0; + ++inclFileName; + } + char* res = resolvePath(inclFileName, fileName); // there was a memory leek in the original too + return res; + } + + void init(); + void token( int type, char *start, char *end ); + void token( int type, char c ); + void token( int type ); + void processToken( int type, char *tokdata, int toklen ); + void directToParser( Parser *toParser, const char *tokFileName, int tokLine, + int tokColumn, int type, char *tokdata, int toklen ); + void flushImport( ); + void importToken( int type, char *start, char *end ); + void pass( int token, char *start, char *end ); + void pass(); + void updateCol(); + void startSection(); + void endSection(); + void do_scan(); + bool active(); + ostream &scan_error(); + + const char *fileName; + istream &input; + ostream &output; + Parser *inclToParser; + char *inclSectionTarg; + int includeDepth; + bool importMachines; + + /* For import parsing. */ + int tok_cs, tok_act; + int *tok_tokstart, *tok_tokend; + int cur_token; + static const int max_tokens = 32; + int token_data[max_tokens]; + char *token_strings[max_tokens]; + int token_lens[max_tokens]; + + /* For section processing. */ + int cs; + char *word, *lit; + int word_len, lit_len; + + /* For character scanning. */ + int line; + InputLoc sectionLoc; + char *tokstart, *tokend; + int column; + char *lastnl; + + /* Set by machine statements, these persist from section to section + * allowing for unnamed sections. */ + Parser *parser; + bool ignoreSection; + IncludeStack includeStack; + + /* This is set if ragel has already emitted an error stating that + * no section name has been seen and thus no parser exists. */ + bool parserExistsError; + + /* This is for inline code. By default it is on. It goes off for + * statements and values in inline blocks which are parsed. */ + bool whitespaceOn; + + /* Keeps a record of the previous token sent to the section parser. */ + int lastToken; +}; + +#endif /* _RLSCAN_H */ diff --git a/contrib/tools/ragel5/ragel/xmlcodegen.cpp b/contrib/tools/ragel5/ragel/xmlcodegen.cpp new file mode 100644 index 00000000000..021c97e87de --- /dev/null +++ b/contrib/tools/ragel5/ragel/xmlcodegen.cpp @@ -0,0 +1,713 @@ +/* + * Copyright 2005, 2006 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "ragel.h" +#include "xmlcodegen.h" +#include "parsedata.h" +#include "fsmgraph.h" +#include <string.h> + +using namespace std; + +XMLCodeGen::XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm, + std::ostream &out ) +: + fsmName(fsmName), + pd(pd), + fsm(fsm), + out(out), + nextActionTableId(0) +{ +} + + +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::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 << 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::writeLmSwitch( InlineItem *item ) +{ + LongestMatch *longestMatch = item->longestMatch; + + out << "<lm_switch"; + if ( longestMatch->lmSwitchHandlesError ) + out << " handles_error=\"t\""; + out << ">\n"; + + 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 << "\">"; + writeInlineList( lmi->action->inlineList, item ); + out << "</sub_action>\n"; + } + } + + out << " </lm_switch><exec><get_tokend></get_tokend></exec>"; +} + +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::writeCtrlFlow( InlineItem *item, InlineItem *context ) +{ + if ( context != 0 ) { + out << "<sub_action>"; + + switch ( context->type ) { + case InlineItem::LmOnLast: + out << "<exec><get_tokend></get_tokend></exec>"; + break; + case InlineItem::LmOnNext: + out << "<exec><get_tokend></get_tokend></exec>"; + break; + case InlineItem::LmOnLagBehind: + out << "<exec><get_tokend></get_tokend></exec>"; + break; + case InlineItem::LmSwitch: + out << "<exec><get_tokend></get_tokend></exec>"; + break; + default: break; + } + } + + 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; + } + + if ( context != 0 ) + out << "</sub_action>"; +} + +void XMLCodeGen::writePtrMod( InlineItem *item, InlineItem *context ) +{ + if ( context != 0 && ( context->type == InlineItem::LmOnNext || + context->type == InlineItem::LmOnLagBehind || + context->type == InlineItem::LmSwitch ) ) + { + switch ( item->type ) { + case InlineItem::Hold: + out << "<holdte></holdte>"; + break; + case InlineItem::Exec: + writeActionExecTE( item ); + break; + default: break; + } + } + else { + switch ( item->type ) { + case InlineItem::Hold: + out << "<hold></hold>"; + break; + case InlineItem::Exec: + writeActionExec( item ); + break; + default: break; + } + } +} + + +void XMLCodeGen::writeGoto( InlineItem *item, InlineItem *context ) +{ + 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, InlineItem *context ) +{ + 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, InlineItem *context ) +{ + 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, InlineItem *context ) +{ + out << "<goto_expr>"; + writeInlineList( item->children, 0 ); + out << "</goto_expr>"; +} + +void XMLCodeGen::writeCallExpr( InlineItem *item, InlineItem *context ) +{ + out << "<call_expr>"; + writeInlineList( item->children, 0 ); + out << "</call_expr>"; +} + +void XMLCodeGen::writeNextExpr( InlineItem *item, InlineItem *context ) +{ + out << "<next_expr>"; + writeInlineList( item->children, 0 ); + 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, 0 ); + 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 ); + out << "</sub_action>"; + } + out << "<exec><get_tokend></get_tokend></exec>"; +} + +void XMLCodeGen::writeLmOnNext( InlineItem *item ) +{ + out << "<set_tokend>0</set_tokend>"; + if ( item->longestMatchPart->action != 0 ) { + out << "<sub_action>"; + writeInlineList( item->longestMatchPart->action->inlineList, item ); + out << "</sub_action>"; + } + out << "<exec><get_tokend></get_tokend></exec>"; +} + +void XMLCodeGen::writeLmOnLagBehind( InlineItem *item ) +{ + if ( item->longestMatchPart->action != 0 ) { + out << "<sub_action>"; + writeInlineList( item->longestMatchPart->action->inlineList, item ); + out << "</sub_action>"; + } + out << "<exec><get_tokend></get_tokend></exec>"; +} + + +void XMLCodeGen::writeInlineList( InlineList *inlineList, InlineItem *context ) +{ + 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 ); + 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: + case InlineItem::Exec: + writePtrMod( item, context ); + break; + + case InlineItem::LmSwitch: + writeLmSwitch( 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::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; + } + } +} + +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 ); + out << "</action>\n"; +} + +void xmlEscapeHost( std::ostream &out, char *data, int 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 ); + + RedActionTable *eofActions = 0; + if ( 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 ); + 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. */ + GraphDictEl *mainEl = pd->graphDict.find( mainMachine ); + if ( mainEl != 0 ) { + 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::writeAlphType() +{ + out << " <alphtype>" << + (keyOps->alphType - hostLang->hostTypes) << "</alphtype>\n"; +} + +void XMLCodeGen::writeGetKeyExpr() +{ + out << " <getkey>"; + writeInlineList( pd->getKeyExpr, 0 ); + out << "</getkey>\n"; +} + +void XMLCodeGen::writeAccessExpr() +{ + out << " <access>"; + writeInlineList( pd->accessExpr, 0 ); + out << "</access>\n"; +} + +void XMLCodeGen::writeCurStateExpr() +{ + out << " <curstate>"; + writeInlineList( pd->curStateExpr, 0 ); + out << "</curstate>\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"; + writeAlphType(); + + if ( pd->getKeyExpr != 0 ) + writeGetKeyExpr(); + + if ( pd->accessExpr != 0 ) + writeAccessExpr(); + + if ( pd->curStateExpr != 0 ) + writeCurStateExpr(); + + writeExports(); + + writeMachine(); + + out << + "</ragel_def>\n"; +} + diff --git a/contrib/tools/ragel5/ragel/xmlcodegen.h b/contrib/tools/ragel5/ragel/xmlcodegen.h new file mode 100644 index 00000000000..99b985395a9 --- /dev/null +++ b/contrib/tools/ragel5/ragel/xmlcodegen.h @@ -0,0 +1,137 @@ +/* + * Copyright 2005, 2006 Adrian Thurston <thurston@cs.queensu.ca> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _XMLDOTGEN_H +#define _XMLDOTGEN_H + +#include <iostream> +#include "avltree.h" +#include "fsmgraph.h" +#include "parsedata.h" + +/* Forwards. */ +struct TransAp; +struct FsmAp; +struct ParseData; + +struct RedActionTable +: + public AvlTreeEl<RedActionTable> +{ + RedActionTable( const ActionTable &key ) + : + key(key), + id(0) + { } + + const ActionTable &getKey() + { return key; } + + ActionTable key; + int id; +}; + +typedef AvlTree<RedActionTable, ActionTable, CmpActionTable> ActionTableMap; + +struct NextRedTrans +{ + Key lowKey, highKey; + TransAp *trans; + TransAp *next; + + void load() { + if ( trans != 0 ) { + next = trans->next; + lowKey = trans->lowKey; + highKey = trans->highKey; + } + } + + NextRedTrans( TransAp *t ) { + trans = t; + load(); + } + + void increment() { + trans = next; + load(); + } +}; + +class XMLCodeGen +{ +public: + XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm, std::ostream &out ); + void writeXML( ); + +private: + void appendTrans( TransListVect &outList, Key lowKey, Key highKey, TransAp *trans ); + void writeStateActions( StateAp *state ); + void writeStateList(); + void writeStateConditions( StateAp *state ); + + void writeKey( Key key ); + void writeText( InlineItem *item ); + void writeCtrlFlow( InlineItem *item, InlineItem *context ); + void writePtrMod( InlineItem *item, InlineItem *context ); + void writeGoto( InlineItem *item, InlineItem *context ); + void writeGotoExpr( InlineItem *item, InlineItem *context ); + void writeCall( InlineItem *item, InlineItem *context ); + void writeCallExpr( InlineItem *item, InlineItem *context ); + void writeNext( InlineItem *item, InlineItem *context ); + void writeNextExpr( InlineItem *item, InlineItem *context ); + void writeEntry( InlineItem *item ); + void writeLmSetActId( InlineItem *item ); + void writeLmOnLast( InlineItem *item ); + void writeLmOnNext( InlineItem *item ); + void writeLmOnLagBehind( InlineItem *item ); + + void writeExports(); + bool writeNameInst( NameInst *nameInst ); + void writeEntryPoints(); + void writeGetKeyExpr(); + void writeAccessExpr(); + void writeCurStateExpr(); + void writeConditions(); + void writeInlineList( InlineList *inlineList, InlineItem *context ); + void writeAlphType(); + void writeActionList(); + void writeActionTableList(); + void reduceTrans( TransAp *trans ); + void reduceActionTables(); + void writeTransList( StateAp *state ); + void writeTrans( Key lowKey, Key highKey, TransAp *defTrans ); + void writeAction( Action *action ); + void writeLmSwitch( InlineItem *item ); + void writeMachine(); + void writeActionExec( InlineItem *item ); + void writeActionExecTE( InlineItem *item ); + + char *fsmName; + ParseData *pd; + FsmAp *fsm; + std::ostream &out; + ActionTableMap actionTableMap; + int nextActionTableId; +}; + + +#endif /* _XMLDOTGEN_H */ |