public ail.net.parser.GrammarSymbol AddSymbol(int xi_symbol_id, ail.net.parser.GrammarSymbol.EType xi_type, string xi_name) { ail.net.parser.GrammarSymbol result = (ail.net.parser.GrammarSymbol)PoolAttr[xi_symbol_id]; if (result == (object)null) { result = new ail.net.parser.GrammarSymbol(); result.Id = xi_symbol_id; result.Type = xi_type; result.Name = xi_name; PoolAttr[xi_symbol_id] = result; if (result.IsNonTerminal()) { NonTerminalCountAttr++; } else if (result.IsTerminal()) { TerminalCountAttr++; } } ail.net.framework.Assert.NonNullReference(result, "result"); result.AddRef(); return(result); }
private void Predict(ail.net.parser.EarleyParser.Chart xi_chart) { // PREDICTOR: // if [A -> ... • B ..., j] is in S(i), add [B -> • a(lpha), i] to S(i) for all rules B -> a(lpha) // no args assertion!!! if (xi_chart != (object)null) { for (int i = xi_chart.PredictedK; i < xi_chart.PredictorItems.Count; i++, xi_chart.PredictedK++) { ail.net.parser.EarleyParser.Item item = (ail.net.parser.EarleyParser.Item)xi_chart.PredictorItems[i]; ail.net.parser.GrammarSymbol symbol = (ail.net.parser.GrammarSymbol)item.CoreItem.Rule.Rhs[item.CoreItem.Dot]; // item.CoreItem.Dot is inside rhs.count if (symbol.IsNonTerminal() && !PredictedNonTerminals[symbol.Id]) { foreach (ail.net.parser.EarleyParser.CoreItem core_item in (ArrayList)PredictTable[symbol.Id]) { AddItem(core_item, xi_chart, xi_chart, null, ail.net.parser.EarleyParser.EFlags.ePredictor, GetErrorCost(item), Charts.Count == 1); // only check for initial chart, because items were introduced // by pseudo-prediction in BuildInitialSet } PredictedNonTerminals[symbol.Id] = true; // marked as predicted } } } }
public ail.net.parser.GrammarSymbol AddRhsSymbol(int xi_symbol_id, ail.net.parser.GrammarSymbol.EType xi_type, string xi_name) { ail.net.parser.GrammarSymbol result = GrammarPool.Instance.AddSymbol(xi_symbol_id, xi_type, xi_name); RhsAttr.Add(result); if (result.IsNonTerminal()) { RhsNonTerminalCountAttr++; } else if (result.IsTerminal()) { RhsTerminalCountAttr++; } return(result); }
public void RemoveSymbol(int xi_symbol_id) { ail.net.parser.GrammarSymbol symbol = (ail.net.parser.GrammarSymbol)PoolAttr[xi_symbol_id]; if (symbol != (object)null && symbol.Release() == 0) { if (symbol.IsNonTerminal()) { NonTerminalCountAttr--; } else if (symbol.IsTerminal()) { TerminalCountAttr--; } PoolAttr.Remove(symbol.Id); } }
private void BuildAstLevel(ail.net.parser.EarleyParser.Item xi_item, ail.net.parser.AstNode xi_root_node) { ail.net.framework.Assert.NonNullReference(xi_item, "xi_item"); ail.net.framework.Assert.NonNullReference(xi_root_node, "xi_root_node"); // populate a rhs stack with items of the current level Stack rhs_stack = new Stack(); PopulateRhsStack(rhs_stack, xi_item); // processing all nodes(items) of the level while (rhs_stack.Count > 0) { ail.net.parser.EarleyParser.Item curr_item = (ail.net.parser.EarleyParser.Item)rhs_stack.Pop(); ail.net.parser.GrammarSymbol symbol = (ail.net.parser.GrammarSymbol)curr_item.CoreItem.Rule.Rhs[curr_item.CoreItem.Dot - 1]; // 'dot-1', because we pushed items with 'dot' > 0 if (symbol.IsTerminal()) { // handle terminal Semantics.HandleTerminal(xi_root_node, curr_item.MasterChart.Token); } else if (symbol.IsNonTerminal()) { // handle non-terminal if (curr_item.Rptrs.Count <= 1) { // r-ptr has exactly one element ail.net.framework.Assert.Condition(curr_item.Rptrs.Count == 1, "ail.net.parser.EarleyParser.BuildAstLevel: curr_item.Rptrs.Count == 1"); ail.net.parser.EarleyParser.Item r_ptr_item = (ail.net.parser.EarleyParser.Item)curr_item.Rptrs[0]; ail.net.parser.AstNode new_node = Semantics.HandleNonTerminalBefore(xi_root_node, r_ptr_item); if (new_node != (object)null) { r_ptr_item.Flags |= (uint)ail.net.parser.EarleyParser.EFlags.eMarked; BuildAstLevel(r_ptr_item, new_node); r_ptr_item.Flags &= ~(uint)ail.net.parser.EarleyParser.EFlags.eMarked; } Semantics.HandleNonTerminalAfter(xi_root_node, r_ptr_item); } else { // r-ptr has more than one elements, ambiguity foreach (ail.net.parser.EarleyParser.Item r_ptr_item in curr_item.Rptrs.Values) { if ((r_ptr_item.Flags & (uint)ail.net.parser.EarleyParser.EFlags.eMarked) == 0) { ail.net.parser.AstNode new_node = Semantics.HandleNonTerminalBefore(xi_root_node, r_ptr_item); if (new_node != (object)null) { r_ptr_item.Flags |= (uint)ail.net.parser.EarleyParser.EFlags.eMarked; BuildAstLevel(r_ptr_item, new_node); r_ptr_item.Flags &= ~(uint)ail.net.parser.EarleyParser.EFlags.eMarked; Semantics.HandleNonTerminalAfter(xi_root_node, r_ptr_item); break; } } } } } } }
public void BuildFollowKSet(int xi_k) { // Sudkump p. 501 // 1. FL(S) = {e(psilon)} // 2. for each A belongs to N-{S} do FL(A) = empty // 3. repeat // 3.1 for each A belongs to N do FL'(A) = FL(A) // 3.2 for each rule A -> w = u1u2...un with w != T* do // 3.2.1 L = FL'(A) // 3.2.2 if un belongs to N then FL(un) = FL(un) U L // 3.2.3 for i = n-1 to 1 do // 3.2.3.1 L = TRUNCk(FIRSTk(ui+1)L) // 3.2.3.2 if ui belongs to N then FL(ui) = FL(ui) U L // end for // end for // until FL(A) = FL'(A) for every A belongs to N // 4. FOLLOWk(A) = FL(A) // FOLLOW set is list of lists for every non-terminal in grammar, size of "lists" is K // ( ) // | \ // | --- // | | // (0,1..K) (0,1..K) ail.net.framework.Assert.Condition(xi_k > 0, "ail.net.parser.Grammar.BuildFirstSet: xi_k > 0"); // collect all non-terminals to deal with Hashtable nonterminals = new Hashtable(); foreach (ail.net.parser.GrammarSymbol symbol in ail.net.parser.GrammarPool.Instance.Pool.Values) { if (symbol.IsNonTerminal()) { nonterminals[symbol.Id] = symbol; } } // 1. FL(S) = {e(psilon)} ArrayList fl = ((ail.net.parser.GrammarSymbol)nonterminals[StartSymbolId]).FollowSet; // trigger initialization ArrayList fl_e = new ArrayList(); // follow set element fl_e.Add((int)ail.net.parser.Token.EType.eEpsilon); fl.Add(fl_e); // 2. for each A belongs to N-{S} do FL(A) = empty foreach (ail.net.parser.GrammarSymbol symbol in nonterminals.Values) { ArrayList dummy = symbol.FollowSet; // trigger initialization } // 3. repeat for (;;) { bool changed = false; // 3.2 for each rule A -> w = u1u2...un with w != T* do foreach (ail.net.parser.GrammarRule rule in RulesAttr) { // w != T* if (rule.RhsNonTerminalCount > 0) { // 3.2.1 L = FL'(A) ail.net.parser.GrammarSymbol a = (ail.net.parser.GrammarSymbol)rule.Lhs[0]; ArrayList l = a.FollowSet; // 3.2.2 if un belongs to N then FL(un) = FL(un) U L ail.net.parser.GrammarSymbol un = (ail.net.parser.GrammarSymbol)rule.Rhs[rule.Rhs.Count - 1]; if (un.IsNonTerminal()) { fl = ((ail.net.parser.GrammarSymbol)nonterminals[un.Id]).FollowSet; foreach (ArrayList e in l) { if (!HasEntry(fl, e)) { fl.Add(e); changed = true; } } } // 3.2.3 for i = n-1 to 1 do // 3.2.3.1 L = TRUNCk(FIRSTk(ui+1)L) // 3.2.3.2 if ui belongs to N then FL(ui) = FL(ui) U L // end for for (int i = rule.Rhs.Count - 2; i >= 0; i--) { l = OperatorInfixK(((ail.net.parser.GrammarSymbol)rule.Rhs[i + 1]).FirstSet, l, xi_k); if (((ail.net.parser.GrammarSymbol)rule.Rhs[i]).IsNonTerminal()) { fl = ((ail.net.parser.GrammarSymbol)nonterminals[((ail.net.parser.GrammarSymbol)rule.Rhs[i]).Id]).FollowSet; foreach (ArrayList e in l) { if (!HasEntry(fl, e)) { fl.Add(e); changed = true; } } } } } } if (!changed) { break; } } }
public void BuildFollowSet() { // go through the rules and for each rule we look at each non-terminal on the righthand // side. For example, we may have a rule X -> ... ABC ..., and let A be a non-terminal. // Calculate FIRST(BC...) and add all elements from this set, except 'e' to FOLLOW(A). If // 'e' is in FIRST(BC...), then we add all elements from FOLLOW(X) to FOLLOW(A). The // process is repeated until there are no more changes to the table for FOLLOW. // // The computation of Follow(A) depends of the First sets defined earlier. If B -> a(lpha)Ab(eta) // then Follow(A) must contains First(b(eta)). If 'e' belongs to First(b(eta)) (i.e., b(eta) is nullable), // or if b(eta) is empty, then Follow(A) must also contain Follow(B). ail.net.parser.GrammarSymbol symbol = (ail.net.parser.GrammarSymbol)ail.net.parser.GrammarPool.Instance.Pool[StartSymbolIdAttr]; symbol.FollowSet.Add((int)ail.net.parser.Token.EType.eEpsilon); bool changed; for (;;) { changed = false; foreach (ail.net.parser.GrammarRule rule in RulesAttr) { ail.net.parser.GrammarSymbol l_symbol = (ail.net.parser.GrammarSymbol)rule.Lhs[0]; for (int k = 0, m = rule.Rhs.Count; k < m; k++) { ail.net.parser.GrammarSymbol r_symbol = (ail.net.parser.GrammarSymbol)rule.Rhs[k]; if (r_symbol.IsNonTerminal()) { int count = r_symbol.FollowSet.Count; ArrayList first_set = new ArrayList(); if (k < m - 1) { first_set.Add(rule.Rhs[k + 1]); // temporary storage first_set = BuildFirstSet(first_set); } for (int i = 0, n = first_set.Count; i < n; i++) { if ((int)first_set[i] != (int)ail.net.parser.Token.EType.eEpsilon && !r_symbol.FollowSet.Contains(first_set[i])) { r_symbol.FollowSet.Add(first_set[i]); } } if (k == m - 1 || first_set.Contains(ail.net.parser.Token.EType.eEpsilon)) { for (int i = 0, n = l_symbol.FollowSet.Count; i < n; i++) { if (!r_symbol.FollowSet.Contains(l_symbol.FollowSet[i])) { r_symbol.FollowSet.Add(l_symbol.FollowSet[i]); } } } changed = changed ? changed : count != r_symbol.FollowSet.Count; } } } if (!changed) { break; } } }