public AstMacroQuote(PegAstNode node) : base(node) { CheckLabel(AstLabel.MacroQuote); foreach (PegAstNode child in node.GetChildren()) { AstMacroTerm term = Create(child) as AstMacroTerm; if (term == null) { throw new Exception("internal grammar error: macro quotations can only contain macro terms"); } mTerms.Add(term); } }
public AstMacroPattern(PegAstNode node) : base(node) { CheckLabel(AstLabel.MacroPattern); foreach (PegAstNode child in node.GetChildren()) { AstMacroTerm tmp = CatAstNode.Create(child) as AstMacroTerm; if (tmp == null) { throw new Exception("invalid grammar: only macro terms can be children of an ast macro mPattern"); } mPattern.Add(tmp); } }
public bool DoesTokenMatch(AstMacroTerm tkn, CatExpr x, out bool bRecoverable) { bRecoverable = true; if (tkn is AstMacroName) { bRecoverable = false; if (x.Count != 1) return false; Function f = x[0]; string sName = f.GetName(); return sName == tkn.ToString(); } else if (tkn is AstMacroTypeVar) { if (x.GetFxnType() == null) return false; if (!CatFxnType.CompareFxnTypes(x.GetFxnType(), CatFxnType.PushSomethingType)) return false; mCapturedVars.Add(tkn.ToString(), x); return true; } else if (tkn is AstMacroQuote) { AstMacroQuote macroQuote = tkn as AstMacroQuote; if (x.Count != 1) return false; PushFunction quote = x[0] as PushFunction; if (quote == null) return false; for (int i = 0; i < macroQuote.mTerms.Count; ++i) { // Are we are at a stack variable in the matching pattern // if so it must be the last token in the pattern // e.g. [1 2 $A] is legal [1 $A 2] is not. if (macroQuote.mTerms[i] is AstMacroStackVar) { if (i != macroQuote.mTerms.Count - 1) throw new Exception("within a quotation, expression variables can only be used in the right-most postition"); AstMacroStackVar v = macroQuote.mTerms[0] as AstMacroStackVar; CatExpr expr = quote.GetChildren().GetRangeFrom(i); mCapturedVars.Add(v.msName, expr); return true; } else if (macroQuote.mTerms[i] is AstMacroName) { // Well this is just an ordinary name pattern AstMacroName name = macroQuote.mTerms[i] as AstMacroName; if (quote.GetChildren().Count <= i) return false; Function f = quote.GetChildren()[i]; if (!f.GetName().Equals(name.ToString())) return false; } else { return false; } } // No stack variable was encountered in the pattern // therefore the match must have been perfect, which means there are no // more terms in the input if (quote.GetChildren().Count != macroQuote.mTerms.Count) return false; return true; } else if (tkn is AstMacroStackVar) { AstMacroStackVar v = tkn as AstMacroStackVar; if (v.mType == null) return false; if (x.GetFxnType() == null) return false; if (!CatFxnType.CompareFxnTypes(x.GetFxnType(), v.mType)) return false; mCapturedVars.Add(v.msName, x); return true; } else { throw new Exception("unrecognized macro term " + tkn.ToString()); } }
public bool DoesTokenMatch(AstMacroTerm tkn, CatExpr x, out bool bRecoverable) { bRecoverable = true; if (tkn is AstMacroName) { bRecoverable = false; if (x.Count != 1) { return(false); } Function f = x[0]; string sName = f.GetName(); return(sName == tkn.ToString()); } else if (tkn is AstMacroTypeVar) { if (x.GetFxnType() == null) { return(false); } if (!CatFxnType.CompareFxnTypes(x.GetFxnType(), CatFxnType.PushSomethingType)) { return(false); } mCapturedVars.Add(tkn.ToString(), x); return(true); } else if (tkn is AstMacroQuote) { AstMacroQuote macroQuote = tkn as AstMacroQuote; if (x.Count != 1) { return(false); } PushFunction quote = x[0] as PushFunction; if (quote == null) { return(false); } for (int i = 0; i < macroQuote.mTerms.Count; ++i) { // Are we are at a stack variable in the matching pattern // if so it must be the last token in the pattern // e.g. [1 2 $A] is legal [1 $A 2] is not. if (macroQuote.mTerms[i] is AstMacroStackVar) { if (i != macroQuote.mTerms.Count - 1) { throw new Exception("within a quotation, expression variables can only be used in the right-most postition"); } AstMacroStackVar v = macroQuote.mTerms[0] as AstMacroStackVar; CatExpr expr = quote.GetChildren().GetRangeFrom(i); mCapturedVars.Add(v.msName, expr); return(true); } else if (macroQuote.mTerms[i] is AstMacroName) { // Well this is just an ordinary name pattern AstMacroName name = macroQuote.mTerms[i] as AstMacroName; if (quote.GetChildren().Count <= i) { return(false); } Function f = quote.GetChildren()[i]; if (!f.GetName().Equals(name.ToString())) { return(false); } } else { return(false); } } // No stack variable was encountered in the pattern // therefore the match must have been perfect, which means there are no // more terms in the input if (quote.GetChildren().Count != macroQuote.mTerms.Count) { return(false); } return(true); } else if (tkn is AstMacroStackVar) { AstMacroStackVar v = tkn as AstMacroStackVar; if (v.mType == null) { return(false); } if (x.GetFxnType() == null) { return(false); } if (!CatFxnType.CompareFxnTypes(x.GetFxnType(), v.mType)) { return(false); } mCapturedVars.Add(v.msName, x); return(true); } else { throw new Exception("unrecognized macro term " + tkn.ToString()); } }
static public MacroMatch Create(AstMacro m, CatExpr fxns, int nPrevMatchPos, int nFxnIndex, int nSubExprSize) { if (nFxnIndex < 0) { return(null); } if (nFxnIndex >= fxns.Count) { return(null); } List <AstMacroTerm> pattern = m.mSrc.mPattern; MacroMatch match = new MacroMatch(m); int nFirst = nFxnIndex; int nLast = nFxnIndex; int nTokenIndex = pattern.Count - 1; // Start at the end of the pattern and move backwards comparing expressions while (nFirst > nPrevMatchPos) { Trace.Assert(nTokenIndex <= pattern.Count); Trace.Assert(nFirst >= 0); Trace.Assert(nLast >= nFirst); Trace.Assert(nTokenIndex < pattern.Count); // get the current sub-expression that we are evaluating CatExpr expr = fxns.GetRangeFromTo(nFirst, nLast); AstMacroTerm tkn = pattern[nTokenIndex]; bool bRecoverable = false; if (match.DoesTokenMatch(tkn, expr, out bRecoverable)) { // Check if we have matched the whole pattern if (nTokenIndex == 0) { match.mnFxnIndex = nFirst; match.mnFxnCount = (nFxnIndex - nFirst) + 1; return(match); } // Go to the previous token nTokenIndex -= 1; // Adjust the sub-expression range nFirst -= 1; nLast = nFirst; } else { // Some failed matches (such as identifier names) can not be recovered from. if (!bRecoverable) { return(null); } // Widen the sub-expression. nFirst -= 1; // Check if we have passed the limit of how big of a // sub-expression will be examined if (nLast - nFirst > nSubExprSize) { return(null); } } } // The loop was finished and no match was found. return(null); }