func NodeFromLabels(labels map[string]string) *Node {
	keys := []string{}
	for key := range labels {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	labelPairs := []string{}
	var rootNode *Node
	var prevNode *Node
	for _, key := range keys {
		value := labels[key]
		labelPairs = append(labelPairs, fmt.Sprintf("%q='%s'", key, value))
		node := newKeyValueNode(key, "'"+value+"'")
		rootNode, prevNode = appendKeyValueNode(node, rootNode, prevNode)
	}
	return &Node{
		Value:    command.Label,
		Original: commandLabel + " " + strings.Join(labelPairs, " "),
		Next:     rootNode,
	}
}
NodeFromLabels returns a Node for the injected labels
package parser
import (
	"encoding/json"
	"errors"
	"fmt"
	"sort"
	"strings"
	"unicode"
	"unicode/utf8"
	"github.com/openshift/imagebuilder/dockerfile/command"
)
var (
	errDockerfileNotStringArray = errors.New("when using JSON array syntax, arrays must be comprised of strings only")
)
const (
	commandLabel = "LABEL"
)
func parseIgnore(rest string, d *Directive) (*Node, map[string]bool, error) {
	return &Node{}, nil, nil
}
func parseSubCommand(rest string, d *Directive) (*Node, map[string]bool, error) {
	if rest == "" {
		return nil, nil, nil
	}
	child, err := newNodeFromLine(rest, d)
	if err != nil {
		return nil, nil, err
	}
	return &Node{Children: []*Node{child}}, nil, nil
}
func parseWords(rest string, d *Directive) []string {
	const (
		inSpaces = iota  
		inWord
		inQuote
	)
	words := []string{}
	phase := inSpaces
	word := ""
	quote := '\000'
	blankOK := false
	var ch rune
	var chWidth int
	for pos := 0; pos <= len(rest); pos += chWidth {
		if pos != len(rest) {
			ch, chWidth = utf8.DecodeRuneInString(rest[pos:])
		}
		if phase == inSpaces {  
			if pos == len(rest) {  
				break
			}
			if unicode.IsSpace(ch) {  
				continue
			}
			phase = inWord  
		}
		if (phase == inWord || phase == inQuote) && (pos == len(rest)) {
			if blankOK || len(word) > 0 {
				words = append(words, word)
			}
			break
		}
		if phase == inWord {
			if unicode.IsSpace(ch) {
				phase = inSpaces
				if blankOK || len(word) > 0 {
					words = append(words, word)
				}
				word = ""
				blankOK = false
				continue
			}
			if ch == '\'' || ch == '"' {
				quote = ch
				blankOK = true
				phase = inQuote
			}
			if ch == d.escapeToken {
				if pos+chWidth == len(rest) {
					continue  
				}
				word += string(ch)
				pos += chWidth
				ch, chWidth = utf8.DecodeRuneInString(rest[pos:])
			}
			word += string(ch)
			continue
		}
		if phase == inQuote {
			if ch == quote {
				phase = inWord
			}
			if ch == d.escapeToken && quote != '\'' {
				if pos+chWidth == len(rest) {
					phase = inWord
					continue  
				}
				pos += chWidth
				word += string(ch)
				ch, chWidth = utf8.DecodeRuneInString(rest[pos:])
			}
			word += string(ch)
		}
	}
	return words
}
func parseNameVal(rest string, key string, d *Directive) (*Node, error) {
	words := parseWords(rest, d)
	if len(words) == 0 {
		return nil, nil
	}
	if !strings.Contains(words[0], "=") {
		parts := tokenWhitespace.Split(rest, 2)
		if len(parts) < 2 {
			return nil, fmt.Errorf(key + " must have two arguments")
		}
		return newKeyValueNode(parts[0], parts[1]), nil
	}
	var rootNode *Node
	var prevNode *Node
	for _, word := range words {
		if !strings.Contains(word, "=") {
			return nil, fmt.Errorf("Syntax error - can't find = in %q. Must be of the form: name=value", word)
		}
		parts := strings.SplitN(word, "=", 2)
		node := newKeyValueNode(parts[0], parts[1])
		rootNode, prevNode = appendKeyValueNode(node, rootNode, prevNode)
	}
	return rootNode, nil
}
func newKeyValueNode(key, value string) *Node {
	return &Node{
		Value: key,
		Next:  &Node{Value: value},
	}
}
func appendKeyValueNode(node, rootNode, prevNode *Node) (*Node, *Node) {
	if rootNode == nil {
		rootNode = node
	}
	if prevNode != nil {
		prevNode.Next = node
	}
	prevNode = node.Next
	return rootNode, prevNode
}
func parseEnv(rest string, d *Directive) (*Node, map[string]bool, error) {
	node, err := parseNameVal(rest, "ENV", d)
	return node, nil, err
}
func parseLabel(rest string, d *Directive) (*Node, map[string]bool, error) {
	node, err := parseNameVal(rest, commandLabel, d)
	return node, nil, err
}