if ( trans->toState != 0 )
trans->priorTable.setPrior( ordering, prior );
}
+
+ /* If the new start state is final then set the out priority. This follows
+ * the same convention as setting start action in the out action table of
+ * a final start state. */
+ if ( startState->stateBits & SB_ISFINAL )
+ startState->outPriorTable.setPrior( ordering, prior );
}
/* Set the priority of all transitions in a graph. Walks all transition lists
if ( trans->toState != 0 )
trans->actionTable.setAction( ordering, action );
}
+
+ /* If start state is final then add the action to the out action table.
+ * This means that when the null string is accepted the start action will
+ * not be bypassed. */
+ if ( startState->stateBits & SB_ISFINAL )
+ startState->outActionTable.setAction( ordering, action );
}
/* Set functions to execute on all transitions. Walks the out lists of all
}
}
+void FsmAp::transferOutActions( StateAp *state )
+{
+ for ( ActionTable::Iter act = state->outActionTable; act.lte(); act++ )
+ state->eofActionTable.setAction( act->key, act->value );
+ state->outActionTable.empty();
+}
+
void FsmAp::transferErrorActions( StateAp *state, int transferPoint )
{
for ( int i = 0; i < state->errActionTable.length(); ) {
if ( act->transferPoint == transferPoint ) {
/* Transfer the error action and remove it. */
setErrorAction( state, act->ordering, act->action );
+ if ( ! state->isFinState() )
+ state->eofActionTable.setAction( act->ordering, act->action );
state->errActionTable.vremove( i );
}
else {
void leaveFsmPrior( int ordering, PriorDesc *prior );
/* Action setting support. */
+ void transferOutActions( StateAp *state );
void transferErrorActions( StateAp *state, int transferPoint );
void setErrorAction( StateAp *state, int ordering, Action *action );
* All state construction is now complete.
*/
+ /* Transfer actions from the out action tables to eof action tables. */
+ for ( StateSet::Iter state = graph->finStateSet; state.lte(); state++ )
+ graph->transferOutActions( *state );
+
/* Transfer global error actions. */
for ( StateList::Iter state = graph->stateList; state.lte(); state++ )
graph->transferErrorActions( state, 0 );
/* 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;
+ /* Currently no checks. */
+ default:
+ break;
}
}
{
out <<
" begin\n"
- " _break_resume = true\n"
+ " _trigger_goto = true\n"
+ " _goto_level = _out\n"
" break\n"
" end\n";
}
EOF_ACTION_SWITCH() <<
" end\n"
" end\n"
+ " if _trigger_goto\n"
+ " next\n"
+ " end\n"
" end\n";
}
{
int len = strlen( buf );
char *p = buf, *pe = buf + len;
+ char *eof = pe;
char identBuf[IDENT_BUFLEN+1];
int identLen;
int curLine;
{
const char *p = data;
const char *pe = data + len;
+ const char *eof = pe;
%% write exec;
}
{
char *p = _data;
char *pe = _data + _len;
+ char *eof = pe;
%% write exec;
}
/*
* @LANG: indep
+ * @NEEDS_EOF: yes
*/
ptr tokstart;
Scanner *fsm = this;
char *p = data;
char *pe = data + len;
+ char *eof = pe;
%% write exec;
if ( cs == Scanner_error )
{
char *p = data;
char *pe = data + len;
+ char *eof = pe;
%% write exec;
{
char *p = _data;
char *pe = _data + _len;
+ char *eof = null;
%% write exec;
{
const char *p = _data;
const char *pe = _data+_len;
+ const char *eof = pe;
%% write exec;
if ( cs == ErrAct_error )
_____INPUT_____ */
/* _____OUTPUT_____
+err_start
eof_start
+err_all
eof_all
FAIL
+err_all
+err_middle
eof_all
eof_middle
FAIL
err_start
err_all
FAIL
+err_all
+err_middle
eof_all
eof_middle
FAIL
err_all
err_middle
FAIL
+err_all
+err_middle
eof_all
eof_middle
FAIL
err_all
err_middle
FAIL
+err_all
+err_middle
eof_all
eof_middle
FAIL
err_all
err_middle
FAIL
+err_all
+err_out
eof_all
eof_out
FAIL
{
const char *p = _data;
const char *pe = _data + _len;
+ const char *eof = pe;
%% write exec;
}
{
int cs;
char *p = "hello", *pe = p + strlen(p);
+ char *eof = pe;
%%{
write init;
write exec;
static void test( char data[] )
{
int cs, p = 0, pe = data.length;
+ int eof = pe;
int top;
%% write init;
accept m1
ACCEPT
enter m2
+enter m2
accpet m2
ACCEPT
enter m1 aa
+enter m1 aa
leave m1 aa
through m1 b
enter m2
accept m1
ACCEPT
enter m1 aa
+enter m1 aa
leave m1 aa
through m1 b
enter m2
ACCEPT
correct command
ACCEPT
+error: failed to recover
FAIL
error: garbling line
error: failed to recover
# Make a temporary version of the test case using the C language translations.
sed -n '/\/\*/,/\*\//d;p' $file | txl -q stdin langtrans_c.txl > $file.pr
-has_eof_act=`sed -n '/\/\*/,/\*\//d;p' $file | txl -q stdin checkeofact.txl`
+needs_eof=`sed '/@NEEDS_EOF/s/^.*$/yes/p;d' $file`
+if [ "$needs_eof" != 'yes' ]; then
+ needs_eof=`sed -n '/\/\*/,/\*\//d;p' $file | txl -q stdin checkeofact.txl`
+fi
# Begin writing out the test case.
cat << EOF
char *pe = data + len;
EOF
-[ "$has_eof_act" = "yes" ] && echo "char *eof = pe;"
+[ "$needs_eof" = "yes" ] && echo "char *eof = pe;"
cat << EOF
%% write exec;
int cs;
int *stack;
int top, stack_size;
- char *p, *pe, *item = 0;
+ char *p, *pe, *eof, *item = 0;
int len = strlen( buf );
p = buf;
pe = buf + len;
+ eof = pe;
%% write exec;
static void test( char data[] )
{
- int cs, p = 0, pe = data.length, item = 0;
+ int cs, p = 0, pe = data.length, eof = data.length, item = 0;
int stack[] = new int[1024];
int stack_size = 1;
int top;
item = 0;
p = 0;
pe = data.length;
+ eof = pe;
cs = 0;
stack = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
stack_size = 1;
{
const char *p = data;
const char *pe = data + len;
+ const char *eof = pe;
%% write exec;
}