package parser
import (
"fmt"
"strconv"
"strings"
"unicode"
)
func (node *Node) Dump() string {
str := ""
str += node.Value
if len(node.Flags) > 0 {
str += fmt.Sprintf(" %q", node.Flags)
}
for _, n := range node.Children {
str += "(" + n.Dump() + ")\n"
}
if node.Next != nil {
for n := node.Next; n != nil; n = n.Next {
if len(n.Children) > 0 {
str += " " + n.Dump()
} else {
str += " " + strconv.Quote(n.Value)
}
}
}
return strings.TrimSpace(str)
}
func fullDispatch(cmd, args string, d *Directive) (*Node, map[string]bool, error) {
fn := dispatch[cmd]
if fn == nil {
fn = parseIgnore
}
sexp, attrs, err := fn(args, d)
if err != nil {
return nil, nil, err
}
return sexp, attrs, nil
}
func splitCommand(line string) (string, []string, string, error) {
var args string
var flags []string
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 stripComments(line string) string {
if tokenComment.MatchString(line) {
return tokenComment.ReplaceAllString(line, "")
}
return line
}
func extractBuilderFlags(line string) (string, []string, error) {
const (
inSpaces = iota
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 {
if pos == len(line) {
break
}
if unicode.IsSpace(ch) {
continue
}
if ch != '-' || pos+1 == len(line) || rune(line[pos+1]) != '-' {
return line[pos:], words, nil
}
phase = inWord
}
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
}
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
}
pos++
ch = rune(line[pos])
}
word += string(ch)
}
}
return "", words, nil
}