func (p *parser) readExtension(ext *ast.Extension) *parseError { if err := p.readToken("extend"); err != nil { return err } ext.Position = p.cur.astPosition() tok := p.next() if tok.err != nil { return tok.err } ext.Extendee = tok.value // checked during resolution if err := p.readToken("{"); err != nil { return err } for !p.done { tok := p.next() if tok.err != nil { return tok.err } if tok.value == "}" { // end of extension return nil } p.back() field := new(ast.Field) ext.Fields = append(ext.Fields, field) field.Up = ext // p.readFile uses this if err := p.readField(field); err != nil { return err } } return p.errorf("unexpected EOF while parsing extension") }
func (p *parser) readFieldOptions(f *ast.Field) *parseError { if err := p.readToken("["); err != nil { return err } for !p.done { tok := p.next() if tok.err != nil { return tok.err } // TODO: support more options than just default and packed switch tok.value { case "default": f.HasDefault = true if err := p.readToken("="); err != nil { return err } tok := p.next() if tok.err != nil { return tok.err } // TODO: check type switch f.TypeName { case "string": f.Default = tok.unquoted default: f.Default = tok.value } case "packed": f.HasPacked = true if err := p.readToken("="); err != nil { return err } packed, err := p.readBool() if err != nil { return err } f.Packed = packed default: return p.errorf(`got %q, want "default" or "packed"`, tok.value) } // next should be a comma or ] tok = p.next() if tok.err != nil { return tok.err } if tok.value == "," { continue } if tok.value == "]" { return nil } return p.errorf(`got %q, want "," or "]"`, tok.value) } return p.errorf("unexpected EOF while parsing field options") }
func (p *parser) readField(f *ast.Field) *parseError { _, inMsg := f.Up.(*ast.Message) // TODO: enforce type limitations if f.Oneof != nil // look for required/optional/repeated tok := p.next() if tok.err != nil { return tok.err } f.Position = p.cur.astPosition() switch tok.value { case "required": f.Required = true case "optional": // nothing to do case "repeated": f.Repeated = true case "map": // map < Key , Value > if err := p.readToken("<"); err != nil { return err } tok = p.next() if tok.err != nil { return tok.err } f.KeyTypeName = tok.value // checked during resolution if err := p.readToken(","); err != nil { return err } tok = p.next() if tok.err != nil { return tok.err } f.TypeName = tok.value // checked during resolution if err := p.readToken(">"); err != nil { return err } f.Repeated = true // maps are repeated goto parseFromFieldName default: // assume this is a type name p.back() } tok = p.next() if tok.err != nil { return tok.err } f.TypeName = tok.value // checked during resolution parseFromFieldName: tok = p.next() if tok.err != nil { return tok.err } f.Name = tok.value // TODO: validate if err := p.readToken("="); err != nil { return err } tag, err := p.readTagNumber(false) if err != nil { return err } f.Tag = tag if f.TypeName == "group" && inMsg { if err := p.readToken("{"); err != nil { return err } group := &ast.Message{ // the current parse position is probably good enough Position: p.cur.astPosition(), Name: f.Name, Group: true, Up: f.Up, } if err := p.readMessageContents(group); err != nil { return err } f.TypeName = f.Name msg := f.Up.(*ast.Message) msg.Messages = append(msg.Messages, group) // ugh if err := p.readToken("}"); err != nil { return err } // A semicolon after a group is optional. if err := p.readToken(";"); err != nil { p.back() } return nil } if err := p.readToken("["); err == nil { p.back() if err := p.readFieldOptions(f); err != nil { return err } } else { p.back() } if err := p.readToken(";"); err != nil { return err } return nil }
func (p *parser) readMessageContents(msg *ast.Message) *parseError { // Parse message fields and other things inside a message. var oneof *ast.Oneof // set while inside a oneof for !p.done { tok := p.next() if tok.err != nil { return tok.err } switch tok.value { case "extend": // extension p.back() ext := new(ast.Extension) msg.Extensions = append(msg.Extensions, ext) if err := p.readExtension(ext); err != nil { return err } ext.Up = msg case "oneof": // oneof if oneof != nil { return p.errorf("nested oneof not permitted") } oneof = new(ast.Oneof) msg.Oneofs = append(msg.Oneofs, oneof) oneof.Position = p.cur.astPosition() tok := p.next() if tok.err != nil { return tok.err } oneof.Name = tok.value // TODO: validate oneof.Up = msg if err := p.readToken("{"); err != nil { return err } case "message": // nested message p.back() nmsg := new(ast.Message) msg.Messages = append(msg.Messages, nmsg) if err := p.readMessage(nmsg); err != nil { return err } nmsg.Up = msg case "enum": // nested enum p.back() ne := new(ast.Enum) msg.Enums = append(msg.Enums, ne) if err := p.readEnum(ne); err != nil { return err } ne.Up = msg case "extensions": // extension range p.back() r, err := p.readExtensionRange() if err != nil { return err } msg.ExtensionRanges = append(msg.ExtensionRanges, r...) default: // field; this token is required/optional/repeated, // a primitive type, or a named type. p.back() field := new(ast.Field) msg.Fields = append(msg.Fields, field) field.Oneof = oneof field.Up = msg // p.readField uses this if err := p.readField(field); err != nil { return err } case "}": if oneof != nil { // end of oneof oneof = nil continue } // end of message p.back() return nil } } return p.errorf("unexpected EOF while parsing message") }