2014-08-05 16:17:40 -04:00
|
|
|
package parser
|
|
|
|
|
2014-10-14 23:33:11 -04:00
|
|
|
import (
|
|
|
|
"fmt"
|
2015-01-03 00:36:58 -05:00
|
|
|
"strconv"
|
2014-10-14 23:33:11 -04:00
|
|
|
"strings"
|
|
|
|
)
|
2014-08-05 16:17:40 -04:00
|
|
|
|
|
|
|
// dumps the AST defined by `node` as a list of sexps. Returns a string
|
|
|
|
// suitable for printing.
|
|
|
|
func (node *Node) Dump() string {
|
|
|
|
str := ""
|
|
|
|
str += node.Value
|
|
|
|
|
|
|
|
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 {
|
2015-01-03 00:36:58 -05:00
|
|
|
str += " " + strconv.Quote(n.Value)
|
2014-08-05 16:17:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.TrimSpace(str)
|
|
|
|
}
|
|
|
|
|
|
|
|
// performs the dispatch based on the two primal strings, cmd and args. Please
|
|
|
|
// look at the dispatch table in parser.go to see how these dispatchers work.
|
2014-08-13 06:07:41 -04:00
|
|
|
func fullDispatch(cmd, args string) (*Node, map[string]bool, error) {
|
2014-10-06 23:24:43 -04:00
|
|
|
fn := dispatch[cmd]
|
|
|
|
|
|
|
|
// Ignore invalid Dockerfile instructions
|
|
|
|
if fn == nil {
|
|
|
|
fn = parseIgnore
|
2014-08-05 16:17:40 -04:00
|
|
|
}
|
|
|
|
|
2014-10-06 23:24:43 -04:00
|
|
|
sexp, attrs, err := fn(args)
|
2014-08-05 16:17:40 -04:00
|
|
|
if err != nil {
|
2014-08-13 06:07:41 -04:00
|
|
|
return nil, nil, err
|
2014-08-05 16:17:40 -04:00
|
|
|
}
|
|
|
|
|
2014-08-13 06:07:41 -04:00
|
|
|
return sexp, attrs, nil
|
2014-08-05 16:17:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// splitCommand takes a single line of text and parses out the cmd and args,
|
|
|
|
// which are used for dispatching to more exact parsing functions.
|
2014-10-14 23:33:11 -04:00
|
|
|
func splitCommand(line string) (string, string, error) {
|
2015-01-15 09:49:48 -05:00
|
|
|
// Make sure we get the same results irrespective of leading/trailing spaces
|
|
|
|
cmdline := TOKEN_WHITESPACE.Split(strings.TrimSpace(line), 2)
|
2014-10-14 23:33:11 -04:00
|
|
|
|
|
|
|
if len(cmdline) != 2 {
|
2014-10-15 14:08:23 -04:00
|
|
|
return "", "", fmt.Errorf("We do not understand this file. Please ensure it is a valid Dockerfile. Parser error at %q", line)
|
2014-10-14 23:33:11 -04:00
|
|
|
}
|
|
|
|
|
2014-08-05 16:17:40 -04:00
|
|
|
cmd := strings.ToLower(cmdline[0])
|
|
|
|
// the cmd should never have whitespace, but it's possible for the args to
|
|
|
|
// have trailing whitespace.
|
2014-10-14 23:33:11 -04:00
|
|
|
return cmd, strings.TrimSpace(cmdline[1]), nil
|
2014-08-05 16:17:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// covers comments and empty lines. Lines should be trimmed before passing to
|
|
|
|
// this function.
|
|
|
|
func stripComments(line string) string {
|
|
|
|
// string is already trimmed at this point
|
|
|
|
if TOKEN_COMMENT.MatchString(line) {
|
|
|
|
return TOKEN_COMMENT.ReplaceAllString(line, "")
|
|
|
|
}
|
|
|
|
|
|
|
|
return line
|
|
|
|
}
|