예제 #1
0
파일: Fsm.cpp 프로젝트: bbriggs/FieldWorks
/*----------------------------------------------------------------------------------------------
	Generate the machine classes for the finite state machine for the pass.
	Process:

 *	By this point, each pass knows which classes need to be included in its FSM, and each
	of those classes has been assigned an FSM-ID (pertinent to the pass). This was done by
	the pre-compiler.

 *	For each glyph we figure out what set of source-classes it is a member of; we record
	the source-class-set (SCS) in a big array indexed by glyph.

	Note that each SCS defines a machine-class--group of glyphs that are considered
	equivalent for the purposes of matching input.

 *	So for each SCS, we create a machine class, which knows that SCS and also which glyphs
	have that set as their SCS. These are the glyphs that are members of that machine class.

	We organize the machine classes in a hash-map. The key for the hash map is based on the
	SCS, specifically we use the sum of the FSM-IDs for the classes in the set. This enables
	us, given a glyph, to take its SCS, find candidate machine-classes in the hash map using
	the key, and then search for the one that has a matching SCS. (This is faster than a
	linear search through the entire list of machine classes.)

	At the end of the process we have a list of machine classes that know what glyphs are
	included, and also each glyph knows which machine class it belongs to.
----------------------------------------------------------------------------------------------*/
void GdlPass::GenerateFsmMachineClasses(GrcManager * pcman)
{
	if (m_nGlobalID == -1)
		return;	// no rules in this pass

	InitializeFsmArrays(); // working arrays

	//	Get a list of all the glyph classes that need to be included in the FSM for this
	//	pass.
	Vector<GdlGlyphClassDefn *> * pvpglfcThisPass = pcman->FsmClassesForPass(m_nGlobalID);

	//	For all the glyphs in the classes, record the fact that the glyph is a member
	//	of the class.
	for (int i = 0; i < pvpglfcThisPass->Size(); i++)
		(*pvpglfcThisPass)[i]->RecordInclusionInClass(this);

//	SortFsmInclusions(); // not needed since we are working with sets

	//	At this point each glyph has a set of source classes it is a member of.
	//	That set serves as a unique identifier indicating the machine class. Ie, for
	//	each combination of source classes, we have a different machine class.

	for (utf16 w = 0; w < kMaxTotalGlyphs; w++)
	{
		int ifsmcColumn = AssignGlyphIDToMachineClasses(w, m_nGlobalID);
		if (ifsmcColumn > -1)
			m_hmGlyphToColumn.Insert(w, ifsmcColumn);
	}

	// TODO SharonC: for each machine class, generate debug string based on source class list.

	if (m_critMaxPreContext > m_critMinPreContext)
	{
		//	The ANY class is (probably) being used in the leading context for some of the rules.
		//	Make sure there is a class that corresponds to exactly the ANY class and no other.
		//	(This is needed to match non-existent glyphs before the beginning of the stream.)
		Symbol psymAnyClass = pcman->SymbolTable()->FindSymbol("ANY");
		GdlGlyphClassDefn * pglfc = psymAnyClass->GlyphClassDefnData();
		Assert(pglfc);
		bool fFound = false;
		for (int ifsmc = 0; ifsmc < m_vpfsmc.Size(); ifsmc++)
		{
			if (m_vpfsmc[ifsmc]->MatchesOneSource(pglfc))
			{
				fFound = true;
				break;
			}
		}
		//	The "non-existent glyph" should be a member of the ANY class and no other, so it
		//	should always be possible to find such a machine-class.
		Assert(fFound);

//		if (!fFound)
//		{
//			//	Add a class that corresponds to exactly the ANY class and no other.
//			FsmMachineClass * pfsmc = new FsmMachineClass(m_nGlobalID);
//			pfsmc->SetColumn(m_vpfsmc.Size());
//			pfsmc->m_scs.Insert(pglfc, false);
//			m_vpfsmc.Push(pfsmc);
//		}

	}
}