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); }
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)); }