예제 #1
0
/*----------------------------------------------------------------------------------------------
	Return the rule table with the given name; create it if it does not exist. Assumes that
	the name is a valid one for tables, but not necessarily for rule tables.
----------------------------------------------------------------------------------------------*/
GdlRuleTable * GdlRenderer::GetRuleTable(GrpLineAndFile & lnf, StrAnsi staTableName)
{
    GdlRuleTable * prultbl = FindRuleTable(staTableName);

    if (prultbl)
        return prultbl;

    //	Create a new one, if permissible.

    Symbol psymTableName = g_cman.SymbolTable()->FindSymbol(staTableName);
    Assert(psymTableName);
    if (!psymTableName || !psymTableName->FitsSymbolType(ksymtTableRule))
    {
        g_errorList.AddError(2162, NULL,
                             "The ",
                             staTableName,
                             " table cannot hold rules",
                             lnf);
        return NULL;
    }

    prultbl = new GdlRuleTable(psymTableName);
    prultbl->SetLineAndFile(lnf);
    m_vprultbl.Push(prultbl);

    return prultbl;
}
예제 #2
0
GdlRuleItem * GdlRule::ContextItemAt(GrpLineAndFile & lnf, int irit,
	StrAnsi staInput, StrAnsi staAlias)
{
	Assert(irit <= m_vprit.Size());

	if (irit == m_vprit.Size())
	{
		Symbol psymClass = g_cman.SymbolTable()->FindSymbol(staInput);
		GdlRuleItem * prit;
		if (psymClass && psymClass->FitsSymbolType(ksymtSpecialLb))
			prit = new GdlLineBreakItem(psymClass);

		else if (psymClass && psymClass->FitsSymbolType(ksymtSpecialUnderscore))
			// place holder
			prit = new GdlSetAttrItem(psymClass);

		else
		{
			if (!psymClass || !psymClass->FitsSymbolType(ksymtClass))
			{
				g_errorList.AddError(3134, this,
					"Undefined class name: ",
					staInput,
					lnf);
				psymClass = g_cman.SymbolTable()->FindSymbol(GdlGlyphClassDefn::Undefined());
			}
			prit = new GdlRuleItem(psymClass);
		}
		prit->SetLineAndFile(lnf);
		prit->m_iritContextPos = m_vprit.Size();
		prit->m_iritContextPosOrig = prit->m_iritContextPos;
		m_vprit.Push(prit);

		//	record the 1-based slot-alias value, if any
		if (staAlias != "")
			m_vpalias.Push(new GdlAlias(staAlias, prit->m_iritContextPos + 1));
	}

	return m_vprit[irit];
}
예제 #3
0
/*----------------------------------------------------------------------------------------------
	The sort key is the number of items matched in the rule (minus the prepended ANYs).
	So we take the original total number of items and substract the insertions.
----------------------------------------------------------------------------------------------*/
int GdlRule::SortKey()
{
	//	Count insertions.
	int critIns = 0;
	for (int irit = 0; irit < m_vprit.Size(); irit++)
	{
		GdlSubstitutionItem * pritSub = dynamic_cast<GdlSubstitutionItem *>(m_vprit[irit]);
		if (pritSub)
		{
			Symbol psym = m_vprit[irit]->m_psymInput;
			if (psym && psym->FitsSymbolType(ksymtSpecialUnderscore))
				critIns++;
		}
	}
	return m_critOriginal - critIns;	// original length of rule
}
예제 #4
0
/*----------------------------------------------------------------------------------------------
	Return the irit'th item in the LHS.
	Assumes that all items have been created for the context and right-hand side, so there
	should be no need to create one here.
	Caller is responsible for checking that there is exactly an equal number of items in the
	left- and right-hand sides.
	Arguments:
		lnf					- line on which the item appears
		irit				- item number (0-based)
		staInput			- input class name, "_", or "#"
----------------------------------------------------------------------------------------------*/
GdlRuleItem * GdlRule::LhsItemAt(GrpLineAndFile & lnf, int irit,
	StrAnsi staInput, StrAnsi staAlias)
{
	bool fContext = false;
	int critLhs = 0;

	Symbol psymClassOrPlaceHolder = g_cman.SymbolTable()->FindSymbol(staInput);

	for (int iritT = 0; iritT < m_vprit.Size(); iritT++)
	{
		GdlSetAttrItem * pritset = dynamic_cast<GdlSetAttrItem*>(m_vprit[iritT]);
		if (!pritset)
			fContext = true;
		else
		{
			if (irit == critLhs)
			{
				if (!psymClassOrPlaceHolder ||
					(!psymClassOrPlaceHolder->FitsSymbolType(ksymtClass) &&
						!psymClassOrPlaceHolder->FitsSymbolType(ksymtSpecialUnderscore) &&
						!psymClassOrPlaceHolder->FitsSymbolType(ksymtSpecialLb)))
				{
					g_errorList.AddError(3141, this,
						"Undefined class name: ",
						staInput,
						lnf);
					psymClassOrPlaceHolder =
						g_cman.SymbolTable()->FindSymbol(GdlGlyphClassDefn::Undefined());
				}

				GdlSubstitutionItem * pritsub = dynamic_cast<GdlSubstitutionItem*>(pritset);
				if (pritsub)
				{
					// for instance, there was a @ in the rhs
				}
				else
				{
					pritsub = new GdlSubstitutionItem(*pritset);
					// output has been set to input
					delete pritset;
				}
				pritsub->SetLineAndFile(lnf);
				m_vprit[iritT] = pritsub;
				pritsub->m_psymInput = psymClassOrPlaceHolder;	// possibly invalid

				//	Record the 1-based slot-alias value, if any
				if (staAlias != "")
					m_vpalias.Push(
						new GdlAlias(staAlias, pritsub->m_iritContextPos + 1));

				if (psymClassOrPlaceHolder &&
					psymClassOrPlaceHolder->FitsSymbolType(ksymtSpecialLb))
				{
					goto LLbError;
				}

				return m_vprit[iritT];
			}

			else
				critLhs++;
		}
	}

	//	Need to add an item

LLbError:
	if (staInput == "#")
	{
		g_errorList.AddError(3142, this,
			StrAnsi("Line break indicator # cannot appear in the left-hand-side"));
		return NULL;
	}

	if (!psymClassOrPlaceHolder ||
		(!psymClassOrPlaceHolder->FitsSymbolType(ksymtClass) &&
			!psymClassOrPlaceHolder->FitsSymbolType(ksymtSpecialUnderscore)))
	{
		g_errorList.AddError(3143, this,
			"Undefined class name: ",
			staInput,
			lnf);
		psymClassOrPlaceHolder = g_cman.SymbolTable()->FindSymbol(GdlGlyphClassDefn::Undefined());
	}

	if (fContext)
		g_errorList.AddError(3144, this,
			StrAnsi("Context does not account for all items in the left-hand-side"));
	else
		g_errorList.AddError(3145, this,
			StrAnsi("Number of items in left- and right-hand-sides do not match"));

	//	Pretend it is a deletion.

	GdlRuleItem * pritNew = new GdlSubstitutionItem(
			psymClassOrPlaceHolder,
			g_cman.SymbolTable()->FindSymbol("_"));

	pritNew->SetLineAndFile(lnf);
	pritNew->m_iritContextPos = m_vprit.Size();
	pritNew->m_iritContextPosOrig = pritNew->m_iritContextPos;

	//	record the 1-based slot-alias value, if any
	if (staAlias != "")
		m_vpalias.Push(new GdlAlias(staAlias, pritNew->m_iritContextPos + 1));

	m_vprit.Push(pritNew);
	return pritNew;
}
예제 #5
0
/*----------------------------------------------------------------------------------------------
	Return the irit'th item in the RHS; create it if it does not exist.
	Assumes that if there was a context, then items have been created for everything in it;
	therefore, needing to create an item when there are context-only items is an error.
	Arguments:
		lnf					- line on which the item appears
		irit				- item number (0-based)
		staInput			- input class name, or "_" or '@'
		staAlias			- string indicating the alias
		fSubItem			- true if we know right off the bat we need a substitition item
----------------------------------------------------------------------------------------------*/
GdlRuleItem * GdlRule::RhsItemAt(GrpLineAndFile & lnf, int irit,
	StrAnsi staInput, StrAnsi staAlias, bool fSubItem)
{
	bool fContext = false;
	int critRhs = 0;

	Symbol psymClassOrPlaceHolder = g_cman.SymbolTable()->FindSymbol(staInput);

	for (int iritT = 0; iritT < m_vprit.Size(); iritT++)
	{
		GdlSetAttrItem * pritset = dynamic_cast<GdlSetAttrItem*>(m_vprit[iritT]);
		if (!pritset)
			fContext = true;
		else
		{
			if (irit == critRhs)
			{
				if (!psymClassOrPlaceHolder ||
					(!psymClassOrPlaceHolder->FitsSymbolType(ksymtClass) &&
						!psymClassOrPlaceHolder->FitsSymbolType(ksymtSpecialUnderscore) &&
						!psymClassOrPlaceHolder->FitsSymbolType(ksymtSpecialLb) &&
						!psymClassOrPlaceHolder->FitsSymbolType(ksymtSpecialAt)))
				{
					g_errorList.AddError(3137, this,
						"Undefined class name: ",
						staInput,
						lnf);
					psymClassOrPlaceHolder =
						g_cman.SymbolTable()->FindSymbol(GdlGlyphClassDefn::Undefined());
				}

				if (psymClassOrPlaceHolder->FitsSymbolType(ksymtSpecialLb))
				{
					goto LLbError;
				}
				else if (fSubItem)
				{
					GdlSubstitutionItem * pritsub = new GdlSubstitutionItem(*pritset);
					pritsub->SetLineAndFile(lnf);
					pritsub->m_psymOutput = psymClassOrPlaceHolder;
					pritsub->m_psymInput = NULL;	// must be set by LHS

					//	record the 1-based slot-alias value, if any
					if (staAlias != "")
						m_vpalias.Push(
							new GdlAlias(staAlias, m_vprit[iritT]->m_iritContextPos + 1));

					delete pritset;
					m_vprit[iritT] = pritsub;
					return pritsub;
				}

				else
				{
					m_vprit[iritT]->SetLineAndFile(lnf);
					m_vprit[iritT]->m_psymInput = psymClassOrPlaceHolder;

					//	record the 1-based slot-alias value, if any
					if (staAlias != "")
						m_vpalias.Push(
							new GdlAlias(staAlias, m_vprit[iritT]->m_iritContextPos + 1));

					return m_vprit[iritT];
				}
			}

			else
				critRhs++;
		}
	}

	//	Need to add an item

LLbError:
	if (staInput == "#")
	{
		g_errorList.AddError(3138, this,
			StrAnsi("Line break indicator # cannot appear in the right-hand-side"));
		return NULL;
	}

	if (!psymClassOrPlaceHolder ||
		(!psymClassOrPlaceHolder->FitsSymbolType(ksymtClass) &&
			!psymClassOrPlaceHolder->FitsSymbolType(ksymtSpecialUnderscore) &&
			!psymClassOrPlaceHolder->FitsSymbolType(ksymtSpecialAt)))
	{
		g_errorList.AddError(3139, this,
			"Undefined class name: ",
			staInput,
			lnf);
		psymClassOrPlaceHolder = g_cman.SymbolTable()->FindSymbol(GdlGlyphClassDefn::Undefined());
	}

	//	Record an error if there was a context for this rule--then pretend that
	//	there was an extra _ on the end of the context.
	if (fContext)
	{
		g_errorList.AddError(3140, this,
			StrAnsi("Context does not account for all items in the right-hand-side"));
	}

	GdlRuleItem * pritNew;
	if (fSubItem)
		pritNew = new GdlSubstitutionItem(
			g_cman.SymbolTable()->FindSymbol("_"),
			psymClassOrPlaceHolder);
	else
		pritNew = new GdlSetAttrItem(psymClassOrPlaceHolder);

	pritNew->SetLineAndFile(lnf);
	pritNew->m_iritContextPos = m_vprit.Size();
	pritNew->m_iritContextPosOrig = pritNew->m_iritContextPos;

	//	record the 1-based slot-alias value, if any
	if (staAlias != "")
		m_vpalias.Push(new GdlAlias(staAlias, pritNew->m_iritContextPos + 1));

	m_vprit.Push(pritNew);
	return pritNew;
}