예제 #1
0
 public SymbolTypeMap(SymbolTypeMap <T> parent)
 {
     this.parent = parent;
     if (parent == null)
     {
         baseTypeCache = new Dictionary <Type, ReadOnlyCollection <Type> >();
     }
 }
예제 #2
0
        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));
                }
            }
        }