public SymbolTypeMap(SymbolTypeMap <T> parent) { this.parent = parent; if (parent == null) { baseTypeCache = new Dictionary <Type, ReadOnlyCollection <Type> >(); } }
protected virtual void CheckConsistency(ICollection <string> errors, bool trace) { SymbolTypeMap <T> symbolTypes = new SymbolTypeMap <T>(); // step 1: check that all terminals have a factory and register their output type for (int i = 0; i < grammar.SymbolCount; i++) { Symbol symbol = grammar.GetSymbol(i); if (symbol.Kind != SymbolKind.Nonterminal) { SemanticTerminalFactory <T> factory; if (TryGetTerminalFactory(symbol, out factory)) { // Debug.WriteLine(factory.OutputType.FullName, symbol.ToString()); if (symbolTypes.SetTypeForSymbol(symbol, factory.OutputType) && trace) { Trace.WriteLine(string.Format("Terminal {0} yields type {1}", symbol, symbolTypes.GetSymbolType(symbol))); } } else { errors.Add(String.Format("Semantic token is missing for terminal {0}", symbol)); } } } // step 2: check that all rules have a factory and register their output type for (int i = 0; i < grammar.RuleCount; i++) { Rule rule = grammar.GetRule(i); SemanticNonterminalFactory <T> factory; if (TryGetNonterminalFactory(rule, out factory)) { // Debug.WriteLine(factory.OutputType.FullName, rule.RuleSymbol.ToString()); if (symbolTypes.SetTypeForSymbol(rule.RuleSymbol, factory.OutputType) && trace) { Trace.WriteLine(string.Format("Rule {0} yields type {1} (static: {2})", rule, symbolTypes.GetSymbolType(rule.RuleSymbol), factory.IsStaticOutputType)); } } else { errors.Add(String.Format("Semantic token is missing for rule {0}", rule)); } } // step 3: check the input types of all rules foreach (KeyValuePair <Rule, SemanticNonterminalFactory <T> > pair in nonterminalFactories) { ReadOnlyCollection <Type> inputTypes = pair.Value.InputTypes; int index = 0; foreach (Symbol inputSymbol in pair.Value.GetInputSymbols(pair.Key)) { if (index < inputTypes.Count) { Type handleType = symbolTypes.GetSymbolType(inputSymbol); if (!inputTypes[index].IsAssignableFrom(handleType)) { errors.Add(string.Format("The factory for the type {0} used by rule {1} expects a {2} on index {3}, but receives a {4}", pair.Value.OutputType.FullName, pair.Key.Definition, inputTypes[index].FullName, index, handleType.FullName)); } } index++; } if (index != inputTypes.Count) { errors.Add(string.Format("The factory for the type {0} used by rule {1} has a mismatch of input symbol count ({2}) and type count ({3})", pair.Value.OutputType.FullName, pair.Key.Definition, index, inputTypes.Count)); } } }