Ejemplo n.º 1
0
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")
}
Ejemplo n.º 2
0
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")
}
Ejemplo n.º 3
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
}
Ejemplo n.º 4
0
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")
}