public SemTree Parse(AttrTree g, string[] words) { if (g == null) { return(null); } if (words.Length == 0) { // empty word list should return empty tree SemTree st = new SemTree(); st.Node = g.Node; return(st); } // enum clauses foreach (AttrTree c in g) { SemTree res = new SemTree(); res.Node = g.Node; int i_patt = 0; if (_Match(c, 0, words, ref i_patt, ref res)) { res.Attributes = c.Attributes; return(res); } } // no match = word list out of grammar return(null); }
protected bool _Match(AttrTree targ, int i_targ, string[] patt, ref int i_patt, ref SemTree result) { bool tend = i_targ >= targ.Count; bool pend = i_patt >= patt.Length; if (tend) { return(pend); } int tit = i_targ; if (pend) { // the rest must be optional while (tit < targ.Count) { if (!((AttrTree)targ[tit++]).IsOptional) { return(false); } } return(true); } AttrTree goal = (AttrTree)targ[tit++]; if (goal.Node == Constants.Grammar.UNIVERSAL) { // consume all words while (i_patt < patt.Length) { result.Add(new SemTree(patt[i_patt++], goal.Attributes)); } return(true); } // word string word = patt[i_patt]; if (goal.Node == word) { int pit = i_patt + 1; if (_Match(targ, tit, patt, ref pit, ref result)) { SemTree at = new SemTree(word, goal.Attributes); result.Insert(0, at); i_patt = pit; return(true); } } // prefer to skip optionals if (goal.IsOptional && _Match(targ, tit, patt, ref i_patt, ref result)) { return(true); } // find class if (!Grammars.ContainsKey(goal.Node)) { return(false); } AttrTree cls = Grammars[goal.Node]; // parse it foreach (AttrTree clause in cls) { // concatenate clause and the rest of target (after goal) to the new tree AttrTree temp_targ = new AttrTree(clause); for (int j = tit; j < targ.Count; j++) { temp_targ.Add(targ[j]); } // try to match int temp_pit = i_patt; if (_Match(temp_targ, 0, patt, ref temp_pit, ref result)) { // create subtree SemTree subtree = new SemTree(cls.Node, clause.Attributes); // move nodes to subtree foreach (var c in clause) { if (result.Count == 0) { break; } AttrTree p = result[0]; if (p.Node != c.Node) { continue; // ignore skipped optionals } subtree.Add(p); result.RemoveAt(0); } result.Insert(0, subtree); i_patt = temp_pit; return(true); } } return(false); }