You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-zero/tools/goctl/api/parser/entity.go

133 lines
2.5 KiB
Go

4 years ago
package parser
import (
"errors"
"fmt"
"strings"
"zero/tools/goctl/api/spec"
)
type (
entity struct {
state *baseState
api *spec.ApiSpec
parser entityParser
}
entityParser interface {
parseLine(line string, api *spec.ApiSpec, annos []spec.Annotation) error
setEntityName(name string)
}
)
func newEntity(state *baseState, api *spec.ApiSpec, parser entityParser) entity {
return entity{
state: state,
api: api,
parser: parser,
}
}
func (s *entity) process() error {
line, err := s.state.readLine()
if err != nil {
return err
}
fields := strings.Fields(line)
if len(fields) < 2 {
return fmt.Errorf("invalid type definition for %q",
strings.TrimSpace(strings.Trim(string(line), "{")))
}
if len(fields) == 2 {
if fields[1] != leftBrace {
return fmt.Errorf("bad string %q after type", fields[1])
}
} else if len(fields) == 3 {
if fields[1] != typeStruct {
return fmt.Errorf("bad string %q after type", fields[1])
}
if fields[2] != leftBrace {
return fmt.Errorf("bad string %q after type", fields[2])
}
}
s.parser.setEntityName(fields[0])
var annos []spec.Annotation
memberLoop:
for {
ch, err := s.state.read()
if err != nil {
return err
}
var annoName string
var builder strings.Builder
switch {
case ch == at:
annotationLoop:
for {
next, err := s.state.read()
if err != nil {
return err
}
switch {
case isSpace(next):
if builder.Len() > 0 {
annoName = builder.String()
builder.Reset()
}
case isNewline(next):
if builder.Len() == 0 {
return errors.New("invalid annotation format")
}
case next == leftParenthesis:
if builder.Len() == 0 {
return errors.New("invalid annotation format")
}
annoName = builder.String()
builder.Reset()
if err := s.state.unread(); err != nil {
return err
}
attrs, err := s.state.parseProperties()
if err != nil {
return err
}
annos = append(annos, spec.Annotation{
Name: annoName,
Properties: attrs,
})
break annotationLoop
default:
builder.WriteRune(next)
}
}
case ch == rightBrace:
break memberLoop
case isLetterDigit(ch):
if err := s.state.unread(); err != nil {
return err
}
var line string
line, err = s.state.readLine()
if err != nil {
return err
}
line = strings.TrimSpace(line)
if err := s.parser.parseLine(line, s.api, annos); err != nil {
return err
}
annos = nil
}
}
return nil
}