private static Tuple <ProtoEntity, ProtoField> ParseMapField(Lexer lexer, IEnumerable <string> parentNames) { var entity = new ProtoEntity(ProtoContainer.Message, Guid.NewGuid().ToString("N")); Parser.ParseValue(lexer, LexemType.LowerThan, "lower than sign"); entity.Fields.Add(new ProtoField(1, Parser.ParseType(lexer, parentNames), "key", ProtoOccurrence.Required)); Parser.ParseValue(lexer, LexemType.Comma, "comma"); entity.Fields.Add(new ProtoField(2, Parser.ParseType(lexer, parentNames), "value", ProtoOccurrence.Required)); Parser.ParseValue(lexer, LexemType.GreaterThan, "greater than sign"); return(Tuple.Create(entity, Parser.ParseField(lexer, new ProtoReference(parentNames.Concat(new [] { entity.Name })), ProtoOccurrence.Required))); }
private ProtoBinding[] ResolveEntity(ProtoEntity entity, IEnumerable <ProtoEntity> parents) { var bindings = new ProtoBinding[0]; foreach (var field in entity.Fields) { if (bindings.Length <= field.Number) { Array.Resize(ref bindings, field.Number + 1); } bindings[field.Number] = this.ResolveField(field, parents); } return(bindings); }
private static ProtoEntity ParseEnum(Lexer lexer) { var entity = new ProtoEntity(ProtoContainer.Enum, Parser.ParseValue(lexer, LexemType.Symbol, "enum name")); Parser.ParseValue(lexer, LexemType.BraceBegin, "opening brace"); while (lexer.Current.Type != LexemType.BraceEnd) { var label = Parser.ParseValue(lexer, LexemType.Symbol, "enum label"); if (label == "option") { Parser.ParseOption(lexer); } else { Parser.ParseValue(lexer, LexemType.Equal, "equal sign"); int value; if (!int.TryParse(Parser.ParseValue(lexer, LexemType.Number, "enum value"), NumberStyles.Integer, CultureInfo.InvariantCulture, out value)) { throw new ParserException(lexer.Position, "invalid enum value"); } if (lexer.Current.Type == LexemType.BracketBegin) { lexer.Next(); Parser.ParseOptions(lexer); Parser.ParseValue(lexer, LexemType.BracketEnd, "closing bracket"); } entity.Labels.Add(new ProtoLabel(value, label)); } Parser.ParseValue(lexer, LexemType.SemiColon, "semicolon"); } lexer.Next(); if (entity.Labels.Count < 1 || entity.Labels[0].Value != 0) { throw new ParserException(lexer.Position, "first enum value must be zero"); } return(entity); }
public static ProtoEntity Parse(TextReader proto) { var entity = new ProtoEntity(ProtoContainer.Root, string.Empty); var lexer = new Lexer(proto); while (lexer.Current.Type != LexemType.End) { if (lexer.Current == Lexem.Option) { lexer.Next(); Parser.ParseOption(lexer); Parser.ParseValue(lexer, LexemType.SemiColon, "semicolon"); } else { entity.Entities.Add(Parser.ParseEntity(lexer)); } } return(entity); }
private static ProtoEntity ParseMessage(Lexer lexer, IEnumerable <string> parentNames) { var name = Parser.ParseValue(lexer, LexemType.Symbol, "message name"); var currentNames = parentNames.Concat(new [] { name }); var entity = new ProtoEntity(ProtoContainer.Message, name); Parser.ParseValue(lexer, LexemType.BraceBegin, "opening brace"); while (lexer.Current.Type != LexemType.BraceEnd) { if (lexer.Current == Lexem.Enum) { lexer.Next(); entity.Entities.Add(Parser.ParseEnum(lexer)); } else if (lexer.Current == Lexem.Extend) { throw new InvalidOperationException("extensions are not supported yet"); } else if (lexer.Current == Lexem.Extensions) { throw new InvalidOperationException("extensions are not supported yet"); } else if (lexer.Current == Lexem.Group) { throw new InvalidOperationException("groups are not supported yet"); } else if (lexer.Current == Lexem.Map) { lexer.Next(); var map = Parser.ParseMapField(lexer, currentNames); entity.Entities.Add(map.Item1); entity.Fields.Add(map.Item2); Parser.ParseValue(lexer, LexemType.SemiColon, "semicolon"); } else if (lexer.Current == Lexem.Message) { lexer.Next(); entity.Entities.Add(Parser.ParseMessage(lexer, currentNames)); } else if (lexer.Current == Lexem.OneOf) { lexer.Next(); entity.Entities.Add(Parser.ParseOneOf(lexer, currentNames)); } else if (lexer.Current == Lexem.Option) { lexer.Next(); Parser.ParseOption(lexer); Parser.ParseValue(lexer, LexemType.SemiColon, "semicolon"); } else if (lexer.Current == Lexem.Reserved) { throw new InvalidOperationException("reserved fields are not supported yet"); } else { ProtoOccurrence occurrence; if (lexer.Current == Lexem.Optional) { lexer.Next(); occurrence = ProtoOccurrence.Optional; } else if (lexer.Current == Lexem.Repeated) { lexer.Next(); occurrence = ProtoOccurrence.Repeated; } else if (lexer.Current == Lexem.Required) { lexer.Next(); occurrence = ProtoOccurrence.Required; } else { occurrence = ProtoOccurrence.Optional; } entity.Fields.Add(Parser.ParseField(lexer, Parser.ParseType(lexer, parentNames), occurrence)); Parser.ParseValue(lexer, LexemType.SemiColon, "semicolon"); } } lexer.Next(); return(entity); }