utils.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package parser
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. // QuoteString walks characters (after trimming), escapes any quotes and
  7. // escapes, then wraps the whole thing in quotes. Very useful for generating
  8. // argument output in nodes.
  9. func QuoteString(str string) string {
  10. result := ""
  11. chars := strings.Split(strings.TrimSpace(str), "")
  12. for _, char := range chars {
  13. switch char {
  14. case `"`:
  15. result += `\"`
  16. case `\`:
  17. result += `\\`
  18. default:
  19. result += char
  20. }
  21. }
  22. return `"` + result + `"`
  23. }
  24. // dumps the AST defined by `node` as a list of sexps. Returns a string
  25. // suitable for printing.
  26. func (node *Node) Dump() string {
  27. str := ""
  28. str += node.Value
  29. for _, n := range node.Children {
  30. str += "(" + n.Dump() + ")\n"
  31. }
  32. if node.Next != nil {
  33. for n := node.Next; n != nil; n = n.Next {
  34. if len(n.Children) > 0 {
  35. str += " " + n.Dump()
  36. } else {
  37. str += " " + QuoteString(n.Value)
  38. }
  39. }
  40. }
  41. return strings.TrimSpace(str)
  42. }
  43. // performs the dispatch based on the two primal strings, cmd and args. Please
  44. // look at the dispatch table in parser.go to see how these dispatchers work.
  45. func fullDispatch(cmd, args string) (*Node, map[string]bool, error) {
  46. if _, ok := dispatch[cmd]; !ok {
  47. return nil, nil, fmt.Errorf("'%s' is not a valid dockerfile command", cmd)
  48. }
  49. sexp, attrs, err := dispatch[cmd](args)
  50. if err != nil {
  51. return nil, nil, err
  52. }
  53. return sexp, attrs, nil
  54. }
  55. // splitCommand takes a single line of text and parses out the cmd and args,
  56. // which are used for dispatching to more exact parsing functions.
  57. func splitCommand(line string) (string, string) {
  58. cmdline := TOKEN_WHITESPACE.Split(line, 2)
  59. cmd := strings.ToLower(cmdline[0])
  60. // the cmd should never have whitespace, but it's possible for the args to
  61. // have trailing whitespace.
  62. return cmd, strings.TrimSpace(cmdline[1])
  63. }
  64. // covers comments and empty lines. Lines should be trimmed before passing to
  65. // this function.
  66. func stripComments(line string) string {
  67. // string is already trimmed at this point
  68. if TOKEN_COMMENT.MatchString(line) {
  69. return TOKEN_COMMENT.ReplaceAllString(line, "")
  70. }
  71. return line
  72. }