示例#1
0
bool RedFsmAp::alphabetCovered( RedTransList &outRange )
{
	/* Cannot cover without any out ranges. */
	if ( outRange.length() == 0 )
		return false;

	/* If the first range doesn't start at the the lower bound then the
	 * alphabet is not covered. */
	RedTransList::Iter rtel = outRange;
	if ( keyOps->minKey < rtel->lowKey )
		return false;

	/* Check that every range is next to the previous one. */
	rtel.increment();
	for ( ; rtel.lte(); rtel++ ) {
		Key highKey = rtel[-1].highKey;
		highKey.increment();
		if ( highKey != rtel->lowKey )
			return false;
	}

	/* The last must extend to the upper bound. */
	RedTransEl *last = &outRange[outRange.length()-1];
	if ( last->highKey < keyOps->maxKey )
		return false;

	return true;
}
示例#2
0
std::ostream &RubyTabCodeGen::KEYS()
{
    START_ARRAY_LINE();
    int totalTrans = 0;
    for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
        /* Loop the singles. */
        for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
            ARRAY_ITEM( KEY( stel->lowKey ), ++totalTrans, false );
        }

        /* Loop the state's transitions. */
        for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
            /* Lower key. */
            ARRAY_ITEM( KEY( rtel->lowKey ), ++totalTrans, false );

            /* Upper key. */
            ARRAY_ITEM( KEY( rtel->highKey ), ++totalTrans, false );
        }
    }

    /* Output one last number so we don't have to figure out when the last
     * entry is and avoid writing a comma. */
    ARRAY_ITEM( INT(0), ++totalTrans, true );
    END_ARRAY_LINE();
    return out;
}
示例#3
0
std::ostream &RubyTabCodeGen::INDICIES()
{
    int totalTrans = 0;
    START_ARRAY_LINE();
    for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
        /* Walk the singles. */
        for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
            ARRAY_ITEM( KEY( stel->value->id ), ++totalTrans, false );
        }

        /* Walk the ranges. */
        for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
            ARRAY_ITEM( KEY( rtel->value->id ), ++totalTrans, false );
        }

        /* The state's default index goes next. */
        if ( st->defTrans != 0 ) {
            ARRAY_ITEM( KEY( st->defTrans->id ), ++totalTrans, false );
        }
    }

    /* Output one last number so we don't have to figure out when the last
     * entry is and avoid writing a comma. */
    ARRAY_ITEM( INT(0), ++totalTrans, true );
    END_ARRAY_LINE();
    return out;
}
示例#4
0
std::ostream &TabCodeGen::INDICIES()
{
	int totalTrans = 0;
	out << '\t';
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		/* Walk the singles. */
		for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
			out << stel->value->id << ", ";
			if ( ++totalTrans % IALL == 0 )
				out << "\n\t";
		}

		/* Walk the ranges. */
		for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
			out << rtel->value->id << ", ";
			if ( ++totalTrans % IALL == 0 )
				out << "\n\t";
		}

		/* The state's default index goes next. */
		if ( st->defTrans != 0 ) {
			out << st->defTrans->id << ", ";
			if ( ++totalTrans % IALL == 0 )
				out << "\n\t";
		}
	}

	/* Output one last number so we don't have to figure out when the last
	 * entry is and avoid writing a comma. */
	out << 0 << "\n";
	return out;
}
示例#5
0
/* Gather various info on the machine. */
void CodeGenData::analyzeMachine()
{
	/* Find the true count of action references.  */
	findFinalActionRefs();

	/* Check if there are any calls in action code. */
	for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
		/* Record the occurrence of various kinds of actions. */
		if ( act->numToStateRefs > 0 )
			redFsm->bAnyToStateActions = true;
		if ( act->numFromStateRefs > 0 )
			redFsm->bAnyFromStateActions = true;
		if ( act->numEofRefs > 0 )
			redFsm->bAnyEofActions = true;
		if ( act->numTransRefs > 0 )
			redFsm->bAnyRegActions = true;

		/* Recurse through the action's parse tree looking for various things. */
		analyzeAction( act, act->inlineList );
	}

	/* Analyze reduced action lists. */
	for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
		for ( GenActionTable::Iter act = redAct->key; act.lte(); act++ )
			analyzeActionList( redAct, act->value->inlineList );
	}

	/* Find states that have transitions with actions that have next
	 * statements. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		/* Check any actions out of outSinge. */
		for ( RedTransList::Iter rtel = st->outSingle; rtel.lte(); rtel++ ) {
			if ( rtel->value->action != 0 && rtel->value->action->anyCurStateRef() )
				st->bAnyRegCurStateRef = true;
		}

		/* Check any actions out of outRange. */
		for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
			if ( rtel->value->action != 0 && rtel->value->action->anyCurStateRef() )
				st->bAnyRegCurStateRef = true;
		}

		/* Check any action out of default. */
		if ( st->defTrans != 0 && st->defTrans->action != 0 && 
				st->defTrans->action->anyCurStateRef() )
			st->bAnyRegCurStateRef = true;
		
		if ( st->stateCondList.length() > 0 )
			redFsm->bAnyConditions = true;

		if ( st->eofTrans != 0 )
			redFsm->bAnyEofTrans = true;
	}

	/* Assign ids to actions that are referenced. */
	assignActionIds();

	/* Set the maximums of various values used for deciding types. */
	setValueLimits();
}
示例#6
0
std::ostream &TabCodeGen::KEYS()
{
	out << '\t';
	int totalTrans = 0;
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		/* Loop the singles. */
		for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
			out << KEY( stel->lowKey ) << ", ";
			if ( ++totalTrans % IALL == 0 )
				out << "\n\t";
		}

		/* Loop the state's transitions. */
		for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
			/* Lower key. */
			out << KEY( rtel->lowKey ) << ", ";
			if ( ++totalTrans % IALL == 0 )
				out << "\n\t";

			/* Upper key. */
			out << KEY( rtel->highKey ) << ", ";
			if ( ++totalTrans % IALL == 0 )
				out << "\n\t";
		}
	}

	/* Output one last number so we don't have to figure out when the last
	 * entry is and avoid writing a comma. */
	out << 0 << "\n";
	return out;
}
示例#7
0
std::ostream &JavaTabCodeGen::TRANS_ACTIONS()
{
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		/* Walk the singles. */
		for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
			RedTransAp *trans = stel->value;
			ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
		}

		/* Walk the ranges. */
		for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
			RedTransAp *trans = rtel->value;
			ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
		}

		/* The state's default index goes next. */
		if ( st->defTrans != 0 ) {
			RedTransAp *trans = st->defTrans;
			ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
		}
	}

	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->eofTrans != 0 ) {
			RedTransAp *trans = st->eofTrans;
			ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
		}
	}

	/* Output one last number so we don't have to figure out when the last
	 * entry is and avoid writing a comma. */
	ARRAY_ITEM( INT(0), true );
	return out;
}
示例#8
0
RedTransAp *RedFsmAp::chooseDefaultNumRanges( RedStateAp *state )
{
	/* Make a set of transitions from the outRange. */
	RedTransSet stateTransSet;
	for ( RedTransList::Iter rtel = state->outRange; rtel.lte(); rtel++ )
		stateTransSet.insert( rtel->value );
	
	/* For each transition in the find how many ranges use the transition. */
	int *numRanges = new int[stateTransSet.length()];
	memset( numRanges, 0, sizeof(int) * stateTransSet.length() );
	for ( RedTransList::Iter rtel = state->outRange; rtel.lte(); rtel++ ) {
		/* Lookup the transition in the set. */
		RedTransAp **inSet = stateTransSet.find( rtel->value );
		numRanges[inSet - stateTransSet.data] += 1;
	}

	/* Find the max number of ranges. */
	RedTransAp *maxTrans = 0;
	int maxNumRanges = 0;
	for ( RedTransSet::Iter rtel = stateTransSet; rtel.lte(); rtel++ ) {
		if ( numRanges[rtel.pos()] > maxNumRanges ) {
			maxNumRanges = numRanges[rtel.pos()];
			maxTrans = *rtel;
		}
	}

	delete[] numRanges;
	return maxTrans;
}
示例#9
0
RedTransAp *RedFsmAp::chooseDefaultSpan( RedStateAp *state )
{
	/* Make a set of transitions from the outRange. */
	RedTransSet stateTransSet;
	for ( RedTransList::Iter rtel = state->outRange; rtel.lte(); rtel++ )
		stateTransSet.insert( rtel->value );
	
	/* For each transition in the find how many alphabet characters the
	 * transition spans. */
	unsigned long long *span = new unsigned long long[stateTransSet.length()];
	memset( span, 0, sizeof(unsigned long long) * stateTransSet.length() );
	for ( RedTransList::Iter rtel = state->outRange; rtel.lte(); rtel++ ) {
		/* Lookup the transition in the set. */
		RedTransAp **inSet = stateTransSet.find( rtel->value );
		int pos = inSet - stateTransSet.data;
		span[pos] += keyOps->span( rtel->lowKey, rtel->highKey );
	}

	/* Find the max span, choose it for making the default. */
	RedTransAp *maxTrans = 0;
	unsigned long long maxSpan = 0;
	for ( RedTransSet::Iter rtel = stateTransSet; rtel.lte(); rtel++ ) {
		if ( span[rtel.pos()] > maxSpan ) {
			maxSpan = span[rtel.pos()];
			maxTrans = *rtel;
		}
	}

	delete[] span;
	return maxTrans;
}
示例#10
0
void CodeGenData::findFinalActionRefs()
{
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		/* Rerence count out of single transitions. */
		for ( RedTransList::Iter rtel = st->outSingle; rtel.lte(); rtel++ ) {
			if ( rtel->value->action != 0 ) {
				rtel->value->action->numTransRefs += 1;
				for ( GenActionTable::Iter item = rtel->value->action->key; item.lte(); item++ )
					item->value->numTransRefs += 1;
			}
		}

		/* Reference count out of range transitions. */
		for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
			if ( rtel->value->action != 0 ) {
				rtel->value->action->numTransRefs += 1;
				for ( GenActionTable::Iter item = rtel->value->action->key; item.lte(); item++ )
					item->value->numTransRefs += 1;
			}
		}

		/* Reference count default transition. */
		if ( st->defTrans != 0 && st->defTrans->action != 0 ) {
			st->defTrans->action->numTransRefs += 1;
			for ( GenActionTable::Iter item = st->defTrans->action->key; item.lte(); item++ )
				item->value->numTransRefs += 1;
		}

		/* Reference count eof transitions. */
		if ( st->eofTrans != 0 && st->eofTrans->action != 0 ) {
			st->eofTrans->action->numTransRefs += 1;
			for ( GenActionTable::Iter item = st->eofTrans->action->key; item.lte(); item++ )
				item->value->numTransRefs += 1;
		}

		/* Reference count to state actions. */
		if ( st->toStateAction != 0 ) {
			st->toStateAction->numToStateRefs += 1;
			for ( GenActionTable::Iter item = st->toStateAction->key; item.lte(); item++ )
				item->value->numToStateRefs += 1;
		}

		/* Reference count from state actions. */
		if ( st->fromStateAction != 0 ) {
			st->fromStateAction->numFromStateRefs += 1;
			for ( GenActionTable::Iter item = st->fromStateAction->key; item.lte(); item++ )
				item->value->numFromStateRefs += 1;
		}

		/* Reference count EOF actions. */
		if ( st->eofAction != 0 ) {
			st->eofAction->numEofRefs += 1;
			for ( GenActionTable::Iter item = st->eofAction->key; item.lte(); item++ )
				item->value->numEofRefs += 1;
		}
	}
}
示例#11
0
RedTransAp *RedFsmAp::chooseDefaultGoto( RedStateAp *state )
{
	/* Make a set of transitions from the outRange. */
	RedTransSet stateTransSet;
	for ( RedTransList::Iter rtel = state->outRange; rtel.lte(); rtel++ ) {
		if ( rtel->value->targ == state->next )
			return rtel->value;
	}
	return 0;
}
示例#12
0
void GraphvizDotGen::writeTransList( RedStateAp *state )
{
	/* Build the set of unique transitions out of this state. */
	RedTransSet stTransSet;
	for ( RedTransList::Iter tel = state->outRange; tel.lte(); tel++ ) {
		/* If we haven't seen the transitions before, the move forward
		 * emitting all the transitions on the same character. */
		if ( stTransSet.insert( tel->value ) ) {
			/* Write out the from and to states. */
			out << "\t" << state->id << " -> ";

			if ( tel->value->targ == 0 )
				out << "err_" << state->id;
			else
				out << tel->value->targ->id;

			/* Begin the label. */
			out << " [ label = \""; 
			ONCHAR( tel->lowKey, tel->highKey );

			/* Walk the transition list, finding the same. */
			for ( RedTransList::Iter mtel = tel.next(); mtel.lte(); mtel++ ) {
				if ( mtel->value == tel->value ) {
					out << ", ";
					ONCHAR( mtel->lowKey, mtel->highKey );
				}
			}

			/* Write the action and close the transition. */
			TRANS_ACTION( state, tel->value );
			out << "\" ];\n";
		}
	}

	/* Write the default transition. */
	if ( state->defTrans != 0 ) {
		/* Write out the from and to states. */
		out << "\t" << state->id << " -> ";

		if ( state->defTrans->targ == 0 )
			out << "err_" << state->id;
		else
			out << state->defTrans->targ->id;

		/* Begin the label. */
		out << " [ label = \"DEF"; 

		/* Write the action and close the transition. */
		TRANS_ACTION( state, state->defTrans );
		out << "\" ];\n";
	}
}
示例#13
0
void RedFsmAp::makeFlat()
{
	for ( RedStateList::Iter st = stateList; st.lte(); st++ ) {
		if ( st->stateCondList.length() == 0 ) {
			st->condLowKey = 0;
			st->condHighKey = 0;
		}
		else {
			st->condLowKey = st->stateCondList.head->lowKey;
			st->condHighKey = st->stateCondList.tail->highKey;

			unsigned long long span = keyOps->span( st->condLowKey, st->condHighKey );
			st->condList = new GenCondSpace*[ span ];
			memset( st->condList, 0, sizeof(GenCondSpace*)*span );

			for ( GenStateCondList::Iter sci = st->stateCondList; sci.lte(); sci++ ) {
				unsigned long long base, trSpan;
				base = keyOps->span( st->condLowKey, sci->lowKey )-1;
				trSpan = keyOps->span( sci->lowKey, sci->highKey );
				for ( unsigned long long pos = 0; pos < trSpan; pos++ )
					st->condList[base+pos] = sci->condSpace;
			}
		}

		if ( st->outRange.length() == 0 ) {
			st->lowKey = st->highKey = 0;
			st->transList = 0;
		}
		else {
			st->lowKey = st->outRange[0].lowKey;
			st->highKey = st->outRange[st->outRange.length()-1].highKey;
			unsigned long long span = keyOps->span( st->lowKey, st->highKey );
			st->transList = new RedTransAp*[ span ];
			memset( st->transList, 0, sizeof(RedTransAp*)*span );
			
			for ( RedTransList::Iter trans = st->outRange; trans.lte(); trans++ ) {
				unsigned long long base, trSpan;
				base = keyOps->span( st->lowKey, trans->lowKey )-1;
				trSpan = keyOps->span( trans->lowKey, trans->highKey );
				for ( unsigned long long pos = 0; pos < trSpan; pos++ )
					st->transList[base+pos] = trans->value;
			}

			/* Fill in the gaps with the default transition. */
			for ( unsigned long long pos = 0; pos < span; pos++ ) {
				if ( st->transList[pos] == 0 )
					st->transList[pos] = st->defTrans;
			}
		}
	}
}
示例#14
0
std::ostream &TabCodeGen::TRANS_TARGS()
{
	int totalTrans = 0;
	out << '\t';
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		/* Walk the singles. */
		for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
			RedTransAp *trans = stel->value;
			out << trans->targ->id << ", ";
			if ( ++totalTrans % IALL == 0 )
				out << "\n\t";
		}

		/* Walk the ranges. */
		for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
			RedTransAp *trans = rtel->value;
			out << trans->targ->id << ", ";
			if ( ++totalTrans % IALL == 0 )
				out << "\n\t";
		}

		/* The state's default target state. */
		if ( st->defTrans != 0 ) {
			RedTransAp *trans = st->defTrans;
			out << trans->targ->id << ", ";
			if ( ++totalTrans % IALL == 0 )
				out << "\n\t";
		}
	}

	/* Add any eof transitions that have not yet been written out above. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->eofTrans != 0 ) {
			RedTransAp *trans = st->eofTrans;
			trans->pos = totalTrans;
			out << trans->targ->id << ", ";
			if ( ++totalTrans % IALL == 0 )
				out << "\n\t";
		}
	}


	/* Output one last number so we don't have to figure out when the last
	 * entry is and avoid writing a comma. */
	out << 0 << "\n";
	return out;
}
示例#15
0
/* A default transition has been picked, move it from the outRange to the
 * default pointer. */
void RedFsmAp::moveToDefault( RedTransAp *defTrans, RedStateAp *state )
{
	/* Rewrite the outRange, omitting any ranges that use 
	 * the picked default. */
	RedTransList outRange;
	for ( RedTransList::Iter rtel = state->outRange; rtel.lte(); rtel++ ) {
		/* If it does not take the default, copy it over. */
		if ( rtel->value != defTrans )
			outRange.append( *rtel );
	}

	/* Save off the range we just created into the state's range. */
	state->outRange.transfer( outRange );

	/* Store the default. */
	state->defTrans = defTrans;
}
示例#16
0
std::wostream &CSharpTabCodeGen::TRANS_ACTIONS()
{
	int totalTrans = 0;
	out << L'\t';
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		/* Walk the singles. */
		for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
			RedTransAp *trans = stel->value;
			TRANS_ACTION( trans ) << L", ";
			if ( ++totalTrans % IALL == 0 )
				out << L"\n\t";
		}

		/* Walk the ranges. */
		for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
			RedTransAp *trans = rtel->value;
			TRANS_ACTION( trans ) << L", ";
			if ( ++totalTrans % IALL == 0 )
				out << L"\n\t";
		}

		/* The state's default index goes next. */
		if ( st->defTrans != 0 ) {
			RedTransAp *trans = st->defTrans;
			TRANS_ACTION( trans ) << L", ";
			if ( ++totalTrans % IALL == 0 )
				out << L"\n\t";
		}
	}

	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->eofTrans != 0 ) {
			RedTransAp *trans = st->eofTrans;
			TRANS_ACTION( trans ) << L", ";
			if ( ++totalTrans % IALL == 0 )
				out << L"\n\t";
		}
	}

	/* Output one last number so we don't have to figure out when the last
	 * entry is and avoid writing a comma. */
	out << 0 << L"\n";
	return out;
}
示例#17
0
/* Set up labelNeeded flag for each state. */
void SplitCodeGen::setLabelsNeeded()
{
	/* If we use the _again label, then we the _again switch, which uses all
	 * labels. */
	if ( useAgainLabel() ) {
		for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
			st->labelNeeded = true;
	}
	else {
		/* Do not use all labels by default, init all labelNeeded vars to false. */
		for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
			st->labelNeeded = false;
		for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
			trans->labelNeeded = false;

		/* Walk all transitions and set only those that have targs. */
		for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
			for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ )
				setLabelsNeeded( st, tel->value );

			for ( RedTransList::Iter tel = st->outSingle; tel.lte(); tel++ )
				setLabelsNeeded( st, tel->value );

			if ( st->defTrans != 0 )
				setLabelsNeeded( st, st->defTrans );
		}
	}

	if ( !noEnd ) {
		for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
			st->outNeeded = st->labelNeeded;
	}
	else {
		if ( redFsm->errState != 0 )
			redFsm->errState->outNeeded = true;

		for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) {
			/* Any state with a transition in that has a break will need an
			 * out label. */
			if ( trans->action != 0 && trans->action->anyBreakStmt() )
				trans->targ->outNeeded = true;
		}
	}
}
示例#18
0
void RedFsmAp::depthFirstOrdering( RedStateAp *state )
{
	/* Nothing to do if the state is already on the list. */
	if ( state->onStateList )
		return;

	/* Doing depth first, put state on the list. */
	state->onStateList = true;
	stateList.append( state );
	
	/* At this point transitions should only be in ranges. */
	assert( state->outSingle.length() == 0 );
	assert( state->defTrans == 0 );

	/* Recurse on everything ranges. */
	for ( RedTransList::Iter rtel = state->outRange; rtel.lte(); rtel++ ) {
		if ( rtel->value->targ != 0 )
			depthFirstOrdering( rtel->value->targ );
	}
}
示例#19
0
std::ostream &JavaTabCodeGen::TRANS_TARGS()
{
	int totalTrans = 0;
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		/* Walk the singles. */
		for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
			RedTransAp *trans = stel->value;
			ARRAY_ITEM( KEY( trans->targ->id ), false );
			totalTrans++;
		}

		/* Walk the ranges. */
		for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
			RedTransAp *trans = rtel->value;
			ARRAY_ITEM( KEY( trans->targ->id ), false );
			totalTrans++;
		}

		/* The state's default target state. */
		if ( st->defTrans != 0 ) {
			RedTransAp *trans = st->defTrans;
			ARRAY_ITEM( KEY( trans->targ->id ), false );
			totalTrans++;
		}
	}

	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->eofTrans != 0 ) {
			RedTransAp *trans = st->eofTrans;
			trans->pos = totalTrans++;
			ARRAY_ITEM( KEY( trans->targ->id ), false );
		}
	}

	/* Output one last number so we don't have to figure out when the last
	 * entry is and avoid writing a comma. */
	ARRAY_ITEM( INT(0), true );
	return out;
}
示例#20
0
void GraphvizDotGen::writeDotFile( )
{
	out << 
		"digraph " << fsmName << " {\n"
		"	rankdir=LR;\n";
	
	/* Define the psuedo states. Transitions will be done after the states
	 * have been defined as either final or not final. */
	out << "	node [ shape = point ];\n";

	if ( redFsm->startState != 0 )
		out << "	ENTRY;\n";

	/* Psuedo states for entry points in the entry map. */
	for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) {
		RedStateAp *state = allStates + *en;
		out << "	en_" << state->id << ";\n";
	}

	/* Psuedo states for final states with eof actions. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->eofTrans != 0 && st->eofTrans->action != 0 )
			out << "	eof_" << st->id << ";\n";
		if ( st->eofAction != 0 )
			out << "	eof_" << st->id << ";\n";
	}

	out << "	node [ shape = circle, height = 0.2 ];\n";

	/* Psuedo states for states whose default actions go to error. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		bool needsErr = false;
		if ( st->defTrans != 0 && st->defTrans->targ == 0 )
			needsErr = true;
		else {
			for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) {
				if ( tel->value->targ == 0 ) {
					needsErr = true;
					break;
				}
			}
		}

		if ( needsErr )
			out << "	err_" << st->id << " [ label=\"\"];\n";
	}

	/* Attributes common to all nodes, plus double circle for final states. */
	out << "	node [ fixedsize = true, height = 0.65, shape = doublecircle ];\n";

	/* List Final states. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->isFinal )
			out << "	" << st->id << ";\n";
	}

	/* List transitions. */
	out << "	node [ shape = circle ];\n";

	/* Walk the states. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
		writeTransList( st );

	/* Transitions into the start state. */
	if ( redFsm->startState != 0 ) 
		out << "	ENTRY -> " << redFsm->startState->id << " [ label = \"IN\" ];\n";

	/* Transitions into the entry points. */
	for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) {
		RedStateAp *state = allStates + *en;
		char *name = entryPointNames[en.pos()];
		out << "	en_" << state->id << " -> " << state->id <<
				" [ label = \"" << name << "\" ];\n";
	}

	/* Out action transitions. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->eofTrans != 0 && st->eofTrans->action != 0 ) {
			out << "	" << st->id << " -> eof_" << 
					st->id << " [ label = \"EOF"; 
			ACTION( st->eofTrans->action ) << "\" ];\n";
		}
		if ( st->eofAction != 0 ) {
			out << "	" << st->id << " -> eof_" << 
					st->id << " [ label = \"EOF"; 
			ACTION( st->eofAction ) << "\" ];\n";
		}
	}

	out <<
		"}\n";
}