utils.go 2.0 KB

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