Example #1
0
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
}