/*---------------------------------------------------------------------------------------------- If there are no settings for this feature, fill in with the default boolean settings. ----------------------------------------------------------------------------------------------*/ void GdlFeatureDefn::FillInBoolean(GrcSymbolTable * psymtbl) { if (m_fStdLang) return; bool fBoolean = false; if (m_vpfset.Size() == 0) { GdlFeatureSetting * pfsetFalse = new GdlFeatureSetting(); pfsetFalse->CopyLineAndFile(*this); pfsetFalse->m_nValue = 0; pfsetFalse->m_fHasValue = true; pfsetFalse->m_staName = StrAnsi("false"); pfsetFalse->m_vextname.Push(GdlExtName(StrUni("False"), LG_USENG)); m_vpfset.Push(pfsetFalse); GdlFeatureSetting * pfsetTrue = new GdlFeatureSetting(); pfsetTrue->CopyLineAndFile(*this); pfsetTrue->m_nValue = 1; pfsetTrue->m_fHasValue = true; pfsetTrue->m_staName = StrAnsi("true"); pfsetTrue->m_vextname.Push(GdlExtName(StrUni("True"), LG_USENG)); m_vpfset.Push(pfsetTrue); if (!m_fDefaultSet) m_nDefault = 0; m_fDefaultSet = true; fBoolean = true; } else if (m_vpfset.Size() == 2) { fBoolean = ((m_vpfset[0]->m_nValue == 0 && m_vpfset[1]->m_nValue == 1) || (m_vpfset[0]->m_nValue == 1 && m_vpfset[1]->m_nValue == 0)); } if (fBoolean) { // Mark the expression type as boolean, not number. Symbol psymFeat = psymtbl->FindSymbol(m_staName); Assert(psymFeat->ExpType() == kexptNumber); psymFeat->SetExpType(kexptBoolean); } }
/*--------------------------------------------------------------------------------------------*/ void GdlRule::ReplaceAliases() { // Look for slots with more than one name, or names assigned to more than one slot. int ipalias; for (ipalias = 0; ipalias < m_vpalias.Size() - 1; ipalias++) { for (int ipalias2 = ipalias + 1; ipalias2 < m_vpalias.Size(); ipalias2++) { if (m_vpalias[ipalias]->m_srIndex == m_vpalias[ipalias2]->m_srIndex) { if (m_vpalias[ipalias]->m_staName != m_vpalias[ipalias2]->m_staName) { char rgch[20]; itoa(m_vpalias[ipalias]->m_srIndex, rgch, 10); g_errorList.AddWarning(1510, this, "Item ", StrAnsi(rgch), " was assigned more than one slot alias"); } } else if (m_vpalias[ipalias]->m_staName == m_vpalias[ipalias2]->m_staName) { g_errorList.AddError(1173, this, "Slot alias '", m_vpalias[ipalias]->m_staName, "' was assigned to more than one item"); } } } // Replace the aliases with the indices in any attribute-setters or constraints. for (int irit = 0; irit < m_vprit.Size(); irit++) { m_vprit[irit]->ReplaceAliases(this); } for (ipalias = 0; ipalias < m_vpalias.Size(); ipalias++) delete m_vpalias[ipalias]; m_vpalias.Clear(); }
/*---------------------------------------------------------------------------------------------- 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; }
/*---------------------------------------------------------------------------------------------- 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; }