123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package parser
- import (
- "strings"
- "unicode"
- )
- // splitCommand takes a single line of text and parses out the cmd and args,
- // which are used for dispatching to more exact parsing functions.
- func splitCommand(line string) (string, []string, string, error) {
- var args string
- var flags []string
- // Make sure we get the same results irrespective of leading/trailing spaces
- cmdline := tokenWhitespace.Split(strings.TrimSpace(line), 2)
- cmd := strings.ToLower(cmdline[0])
- if len(cmdline) == 2 {
- var err error
- args, flags, err = extractBuilderFlags(cmdline[1])
- if err != nil {
- return "", nil, "", err
- }
- }
- return cmd, flags, strings.TrimSpace(args), nil
- }
- func extractBuilderFlags(line string) (string, []string, error) {
- // Parses the BuilderFlags and returns the remaining part of the line
- const (
- inSpaces = iota // looking for start of a word
- inWord
- inQuote
- )
- words := []string{}
- phase := inSpaces
- word := ""
- quote := '\000'
- blankOK := false
- var ch rune
- for pos := 0; pos <= len(line); pos++ {
- if pos != len(line) {
- ch = rune(line[pos])
- }
- if phase == inSpaces { // Looking for start of word
- if pos == len(line) { // end of input
- break
- }
- if unicode.IsSpace(ch) { // skip spaces
- continue
- }
- // Only keep going if the next word starts with --
- if ch != '-' || pos+1 == len(line) || rune(line[pos+1]) != '-' {
- return line[pos:], words, nil
- }
- phase = inWord // found something with "--", fall through
- }
- if (phase == inWord || phase == inQuote) && (pos == len(line)) {
- if word != "--" && (blankOK || len(word) > 0) {
- words = append(words, word)
- }
- break
- }
- if phase == inWord {
- if unicode.IsSpace(ch) {
- phase = inSpaces
- if word == "--" {
- return line[pos:], words, nil
- }
- if blankOK || len(word) > 0 {
- words = append(words, word)
- }
- word = ""
- blankOK = false
- continue
- }
- if ch == '\'' || ch == '"' {
- quote = ch
- blankOK = true
- phase = inQuote
- continue
- }
- if ch == '\\' {
- if pos+1 == len(line) {
- continue // just skip \ at end
- }
- pos++
- ch = rune(line[pos])
- }
- word += string(ch)
- continue
- }
- if phase == inQuote {
- if ch == quote {
- phase = inWord
- continue
- }
- if ch == '\\' {
- if pos+1 == len(line) {
- phase = inWord
- continue // just skip \ at end
- }
- pos++
- ch = rune(line[pos])
- }
- word += string(ch)
- }
- }
- return "", words, nil
- }
|