public void CompileProduction(GrammarSymbol production)
        {
            Debug.Assert(production.Kind == SymbolKind.Production);
            GrammarSymbol decl = production[0];

            Debug.Assert(decl.Kind == SymbolKind.ProductionDecl);
            if (decl.FirstToken != production.FirstToken)
            {
                // Honestly I don't know why "fragment" productions are even
                // in the grammar if they're not supposed to be produced; but this is what
                // the original MSR code did and we need to parse their grammar files.
                Debug.Assert(production.FirstToken.GetText() == "fragment");
                return;
            }

            string productionName = decl.GetLogicalText();

            if (s_basicBuiltinTypes.Any(type => type.G4DeclaredName == productionName))
            {
                // Builtins don't matter in the grammar.
                return;
            }

            GrammarSymbol productionIs = production[1];

            switch (productionIs.Kind)
            {
            case SymbolKind.String:
                this.CompileEnumValueType(decl, productionIs.FirstToken);
                break;

            case SymbolKind.Identifier:
            case SymbolKind.ZeroOrMoreQuantifier:
            case SymbolKind.OneOrMoreQuantifier:
            case SymbolKind.ZeroOrOneQuantifier:
                this.CompileStandardType(decl, ImmutableArray.Create(productionIs));
                break;

            case SymbolKind.Group:
                this.CompileStandardType(decl, productionIs.Children);
                break;

            case SymbolKind.Alternation:
                if (productionIs.Children.All(child => child.Kind == SymbolKind.String))
                {
                    this.CompileEnumValueType(decl, productionIs.Children);
                    break;
                }
                else if (productionIs.Children.All(child => child.Kind == SymbolKind.Identifier))
                {
                    this.CompileBaseType(decl, productionIs.Children);
                    break;
                }

                goto default;

            default:
                throw new G4ParseFailureException(production.GetLocation(), Strings.UnrecognizedDataModel, productionName);
            }
        }
        private static GrammarSymbol GetDeclaringIdentifierSymbol(GrammarSymbol currentSymbol, string productionName)
        {
            GrammarSymbol declSymbol;

            switch (currentSymbol.Kind)
            {
            case SymbolKind.ZeroOrOneQuantifier:
            case SymbolKind.ZeroOrMoreQuantifier:
            case SymbolKind.OneOrMoreQuantifier:
                declSymbol = currentSymbol[0];
                break;

            case SymbolKind.Identifier:
                declSymbol = currentSymbol;
                break;

            default:
                declSymbol = GrammarSymbol.Empty;
                break;
            }

            if (declSymbol.Kind != SymbolKind.Identifier)
            {
                throw new G4ParseFailureException(currentSymbol.GetLocation(), Strings.UnrecognizedDataModel, productionName);
            }

            return(declSymbol);
        }
        private void CompileStandardType(GrammarSymbol decl, ImmutableArray <GrammarSymbol> groupList)
        {
            var result = new DataModelLeafTypeBuilder(decl);
            int idx    = 0;

            while (idx < groupList.Length)
            {
                List <string> staticStrings = GetStringValuesAfter(groupList, idx);
                foreach (string staticString in staticStrings)
                {
                    result.ToStringEntries.Add(new ToStringEntry(staticString, null));
                }

                idx += staticStrings.Count;
                if (idx >= groupList.Length)
                {
                    break;
                }

                GrammarSymbol currentSymbol    = groupList[idx];
                GrammarSymbol memberDeclSymbol = GetDeclaringIdentifierSymbol(currentSymbol, result.G4DeclaredName);
                GrammarSymbol lookAheadSymbol  = GetSymbolOrEmpty(groupList, idx + 1);

                // Check for patterns:
                if (MatchesDelimitedCollectionPattern(currentSymbol, memberDeclSymbol, lookAheadSymbol))
                {
                    // x ('delimiter' x)*
                    string delimeter = lookAheadSymbol[0][0].GetLogicalText();
                    result.AddMember(memberDeclSymbol, 1, currentSymbol.Kind == SymbolKind.Identifier, delimeter);
                    idx += 2;
                    continue;
                }

                int  rank;
                bool required;
                switch (currentSymbol.Kind)
                {
                case SymbolKind.Identifier:
                    // x
                    rank     = 0;
                    required = true;
                    break;

                case SymbolKind.ZeroOrOneQuantifier:
                    // x?
                    rank     = 0;
                    required = false;
                    break;

                case SymbolKind.ZeroOrMoreQuantifier:
                    // x*
                    rank     = 1;
                    required = false;
                    break;

                case SymbolKind.OneOrMoreQuantifier:
                    // x+
                    rank     = 1;
                    required = true;
                    break;

                default:
                    throw new G4ParseFailureException(currentSymbol.GetLocation(), Strings.UnrecognizedDataModel, result.G4DeclaredName);
                }

                ++idx;
                result.AddMember(memberDeclSymbol, rank, required);
            }

            this.AddCompiledType(result);
        }
Beispiel #4
0
        internal void AddMember(GrammarSymbol declSymbol, int rank, bool required, string delimeter = null)
        {
            string declaredName   = declSymbol.GetLogicalText();
            string annotationName = declSymbol.Annotations.GetAnnotationValue("name");
            string pattern        = declSymbol.Annotations.GetAnnotationValue("pattern");
            string minimum        = declSymbol.Annotations.GetAnnotationValue("minimum");
            string minItems       = declSymbol.Annotations.GetAnnotationValue("minItems");
            string uniqueItems    = declSymbol.Annotations.GetAnnotationValue("uniqueItems");
            string defaultValue   = declSymbol.Annotations.GetAnnotationValue("default");
            string cSharpName     = annotationName ?? LinguisticTransformer.ToCSharpName(declaredName);
            string serializedName = declSymbol.Annotations.GetAnnotationValue("serializedName");

            if (serializedName == null)
            {
                serializedName = LinguisticTransformer.ToJsonName(cSharpName);
            }

            if (serializedName == null)
            {
                serializedName = LinguisticTransformer.ToJsonName(declaredName);
            }

            string argumentName = declSymbol.Annotations.GetAnnotationValue("argumentName");

            if (argumentName == null)
            {
                if (annotationName == null)
                {
                    argumentName = LinguisticTransformer.ToArgumentName(declaredName);
                }
                else
                {
                    argumentName = LinguisticTransformer.ToArgumentName(annotationName);
                }
            }

            foreach (DataModelMember existingMember in this.Members)
            {
                if (existingMember.CSharpName == cSharpName)
                {
                    throw new G4ParseFailureException(declSymbol.GetLocation(), Strings.DuplicateCSharpMemberName, cSharpName);
                }

                if (existingMember.SerializedName == serializedName)
                {
                    throw new G4ParseFailureException(declSymbol.GetLocation(), Strings.DuplicateJsonMemberName, serializedName);
                }

                if (existingMember.ArgumentName == argumentName)
                {
                    throw new G4ParseFailureException(declSymbol.GetLocation(), Strings.DuplicateArgumentName, argumentName);
                }
            }

            DataModelMember newMember = new DataModelMember(
                declaredName,
                cSharpName,
                serializedName,
                declSymbol.Annotations.GetAnnotationValue("summary"),
                argumentName,
                pattern,
                minimum,
                minItems,
                uniqueItems,
                defaultValue,
                rank,
                required
                );


            this.Members.Add(newMember);
            this.ToStringEntries.Add(new ToStringEntry(delimeter, newMember));
        }