diff --git a/workflow-pr/submodules.go b/workflow-pr/submodules.go index 49c0ac3..379d79d 100644 --- a/workflow-pr/submodules.go +++ b/workflow-pr/submodules.go @@ -1,9 +1,12 @@ package main import ( + "bytes" "errors" + "fmt" "io" - "text/scanner" + "strings" + "unicode" ) type Submodule struct { @@ -13,40 +16,113 @@ type Submodule struct { var SyntaxError error = errors.New("Syntax error") -func (sub *Submodule) parseSubmoduleName(s *scanner.Scanner) error { - s.Scan() - if s.TokenText() != "submodule" { +func (sub *Submodule) parseSubmoduleName(line string) error { + line = strings.TrimSpace(line) + if line[0:10] != "submodule " { return SyntaxError } - s.Scan() - sub.Name = s.TokenText() - l := len(sub.Name) - if sub.Name[0] != '"' || sub.Name[l-1] != '"' || s.ErrorCount > 0 { + + r := strings.NewReader(line[10:]) + + ch, _, err := r.ReadRune() + for ; ; ch, _, err = r.ReadRune() { + if err != nil { + return fmt.Errorf("%c %d", ch, 32) + } + if !unicode.IsSpace(ch) { + break + } + } + if ch != '"' { + return fmt.Errorf("%c %d", ch, 36) + // return SyntaxError + } + + var b strings.Builder + for ch, _, err = r.ReadRune(); ch != '"'; ch, _, err = r.ReadRune() { + if err != nil { + return fmt.Errorf("%c %d", ch, 32) + } + b.WriteRune(ch) + } + + if ch != '"' { + return fmt.Errorf("%c %d", ch, 45) + // return SyntaxError + } + + ch, _, err = r.ReadRune() + + if ch != ']' || err != nil { + return fmt.Errorf("%c %d, %w", ch, 50, err) + // return SyntaxError + } + + sub.Name = b.String() + + for ch, _, err = r.ReadRune(); ; ch, _, _ = r.ReadRune() { + if err == io.EOF { + return nil + } + if !unicode.IsSpace(ch) { + return SyntaxError + } + } +} + +func (s *Submodule) parseKeyValue(line string) error { + eqLoc := strings.Index(line, "=") + if eqLoc < 0 || eqLoc == len(line)-1 { return SyntaxError } - sub.Name = sub.Name[1 : len(sub.Name)-1] - s.Scan() - if s.TokenText() != "]" { + + key := strings.ToLower(strings.TrimSpace(line[0:eqLoc])) + val := strings.TrimSpace(line[eqLoc+1:]) + + if len(val) == 0 { return SyntaxError } + + switch key { + case "path": + s.Path = val + } + return nil } func ParseSubmodulesFile(reader io.Reader) ([]Submodule, error) { - ret := make([]Submodule, 0, 100) + data, err := io.ReadAll(reader) + if err != nil { + return nil, err + } - s := new(scanner.Scanner) - s.Init(reader) + var sub *Submodule + ret := []Submodule{} - sub := &Submodule{} - for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() { - t := s.TokenText() - - if t == "[" { - if err := sub.parseSubmoduleName(s); err != nil { + lines := bytes.Split(data, []byte("\n")) + for _, l := range lines { + line := string(bytes.TrimSpace(l)) + if len(line) == 0 { + continue + } + if line[0] == '[' { + if sub != nil { + ret = append(ret, *sub) + } + sub = &Submodule{} + if err := sub.parseSubmoduleName(line[1:]); err != nil { + return nil, err + } + } else if sub == nil { + return nil, SyntaxError + } else { + if err := sub.parseKeyValue(line); err != nil { return nil, err } } + } + if sub != nil { ret = append(ret, *sub) } return ret, nil