} //method #endregion #region Calculating Tail Firsts private void CalculateTailFirsts() { foreach (NonTerminal nt in _grammar.NonTerminals) { foreach (Production prod in nt.Productions) { StringSet accumulatedFirsts = new StringSet(); bool allNullable = true; //We are going backwards in LR0Items list for (int i = prod.LR0Items.Count - 1; i >= 0; i--) { LR0Item item = prod.LR0Items[i]; if (i >= prod.LR0Items.Count - 2) { //Last and before last items have empty tails item.TailIsNullable = true; item.TailFirsts.Clear(); continue; } BnfTerm nextTerm = prod.RValues[i + 1]; //Element after-after-dot; remember we're going in reverse direction //if (ntElem == null) continue; //it is not NonTerminal NonTerminal nextNt = nextTerm as NonTerminal; bool notNullable = nextTerm is Terminal || nextNt != null && !nextNt.Nullable; if (notNullable) //next term is not nullable (a terminal or non-nullable NonTerminal) //term is not nullable, so we clear all old firsts and add this term { accumulatedFirsts.Clear(); allNullable = false; item.TailIsNullable = false; if (nextTerm is Terminal) { item.TailFirsts.Add(nextTerm.Key);//term is terminal so add its key accumulatedFirsts.Add(nextTerm.Key); } else if (nextNt != null) //it is NonTerminal { item.TailFirsts.AddRange(nextNt.Firsts); //nonterminal accumulatedFirsts.AddRange(nextNt.Firsts); } continue; } //if we are here, then ntElem is a nullable NonTerminal. We add accumulatedFirsts.AddRange(nextNt.Firsts); item.TailFirsts.AddRange(accumulatedFirsts); item.TailIsNullable = allNullable; } //for i } //foreach prod } //foreach nt } //method
} //method #endregion #region Calculating Tail Firsts private void CalculateTailFirsts() { foreach (Production prod in Data.Productions) { StringSet accumulatedFirsts = new StringSet(); bool allNullable = true; //We are going backwards in LR0Items list for (int i = prod.LR0Items.Count - 1; i >= 0; i--) { LR0Item item = prod.LR0Items[i]; if (i >= prod.LR0Items.Count - 2) { //Last and before last items have empty tails item.TailIsNullable = true; item.TailFirsts.Clear(); continue; } BnfTerm term = prod.RValues[item.Position + 1]; //Element after-after-dot NonTerminal ntElem = term as NonTerminal; if (ntElem == null || !ntElem.Nullable) //term is a terminal or non-nullable NonTerminal //term is not nullable, so we clear all old firsts and add this term { accumulatedFirsts.Clear(); allNullable = false; item.TailIsNullable = false; if (ntElem == null) { item.TailFirsts.Add(term.Key);//term is terminal so add its key accumulatedFirsts.Add(term.Key); } else { item.TailFirsts.AddRange(ntElem.Firsts); //nonterminal accumulatedFirsts.AddRange(ntElem.Firsts); } continue; } //if we are here, then ntElem is a nullable NonTerminal. We add accumulatedFirsts.AddRange(ntElem.Firsts); item.TailFirsts.AddRange(accumulatedFirsts); item.TailIsNullable = allNullable; } //for i } //foreach prod } //method
public Adapters(DataGroups dataGroups, params string[] validAdapterNames) { this.dataGroups = dataGroups; adapters = new StringHash <Adapter <T> >(true); validAdapters = new StringSet(true); if (validAdapterNames.Length == 0) { isValidAdapterName = _ => true; } else { isValidAdapterName = adapterName => adapterName.IsNotEmpty() && validAdapters.Contains(adapterName); validAdapters.AddRange(validAdapterNames); } }
//TODO: This needs more work. Currently it reports all individual symbols most of the time, in a message like // "Syntax error, expected: + - < > = ..."; the better method is to group operator symbols under one alias "operator". // The reason is that code picks expected key list at current(!) state only, // slightly tweaking it for non-terminals, without exploring Reduce roots // It is quite difficult to discover grouping non-terminals like "operator" in current structure. // One possible solution would be to introduce "ExtendedLookaheads" in ParserState which would include // all NonTerminals that might follow the current position. This list would be calculated at start up, // in addition to normal lookaheads. #endregion private StringList GetCurrentExpectedSymbols() { BnfTermList inputElements = new BnfTermList(); StringSet inputKeys = new StringSet(); inputKeys.AddRange(_currentState.Actions.Keys); //First check all NonTerminals foreach (NonTerminal nt in Data.NonTerminals) { if (!inputKeys.Contains(nt.Key)) { continue; } //nt is one of our available inputs; check if it has an alias. If not, don't add it to element list; // and we have already all its "Firsts" keys in the list. // If yes, add nt to element list and remove // all its "fists" symbols from the list. These removed symbols will be represented by single nt alias. if (string.IsNullOrEmpty(nt.DisplayName)) { inputKeys.Remove(nt.Key); } else { inputElements.Add(nt); foreach (string first in nt.Firsts) { inputKeys.Remove(first); } } } //Now terminals foreach (Terminal term in Data.Terminals) { if (inputKeys.Contains(term.Key)) { inputElements.Add(term); } } StringList result = new StringList(); foreach (BnfTerm term in inputElements) { result.Add(string.IsNullOrEmpty(term.DisplayName)? term.Name : term.DisplayName); } result.Sort(); return(result); }
private StringList GetCurrentExpectedSymbols() { BnfTermList inputElements = new BnfTermList(); StringSet inputKeys = new StringSet(); inputKeys.AddRange(_currentState.Actions.Keys); //First check all NonTerminals foreach (NonTerminal nt in Data.NonTerminals) { if (!inputKeys.Contains(nt.Key)) continue; //nt is one of our available inputs; check if it has an alias. If not, don't add it to element list; // and we have already all its "Firsts" keys in the list. // If yes, add nt to element list and remove // all its "fists" symbols from the list. These removed symbols will be represented by single nt alias. if (string.IsNullOrEmpty(nt.DisplayName)) inputKeys.Remove(nt.Key); else { inputElements.Add(nt); foreach(string first in nt.Firsts) inputKeys.Remove(first); } } //Now terminals foreach (Terminal term in Data.Terminals) { if (inputKeys.Contains(term.Key)) inputElements.Add(term); } StringList result = new StringList(); foreach(BnfTerm term in inputElements) result.Add(string.IsNullOrEmpty(term.DisplayName)? term.Name : term.DisplayName); result.Sort(); return result; }
private void CalculateTailFirsts() { foreach (Production prod in _data.Productions) { StringSet accumulatedFirsts = new StringSet(); bool allNullable = true; for (int i = prod.LR0Items.Count - 1; i >= 0; i--) { LR0Item item = prod.LR0Items[i]; if (i >= prod.LR0Items.Count - 2) { item.TailIsNullable = true; item.TailFirsts.Clear(); continue; } GrammarTerm term = prod.RValues[item.Position + 1]; NonTerminal ntElem = term as NonTerminal; if (ntElem == null || !ntElem.Nullable) { accumulatedFirsts.Clear(); allNullable = false; item.TailIsNullable = false; if (ntElem == null) { item.TailFirsts.Add(term.Key); accumulatedFirsts.Add(term.Key); } else { item.TailFirsts.AddRange(ntElem.Firsts); accumulatedFirsts.AddRange(ntElem.Firsts); } continue; } accumulatedFirsts.AddRange(ntElem.Firsts); item.TailFirsts.AddRange(accumulatedFirsts); item.TailIsNullable = allNullable; } } }
public readonly UnicodeCategoryList CharsToRemoveCategories = new UnicodeCategoryList(); //categories of chars to remove from final id, usually formatting category #endregion public void AddKeywords(params string[] keywords) { Keywords.AddRange(keywords); }