hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

parse.go (21556B)

    1 // Copyright 2011 The Go Authors. All rights reserved.
    2 // Use of this source code is governed by a BSD-style
    3 // license that can be found in the LICENSE file.
    4 
    5 // Package parse builds parse trees for templates as defined by text/template
    6 // and html/template. Clients should use those packages to construct templates
    7 // rather than this one, which provides shared internal data structures not
    8 // intended for general use.
    9 package parse
   10 
   11 import (
   12 	"bytes"
   13 	"fmt"
   14 	"runtime"
   15 	"strconv"
   16 	"strings"
   17 )
   18 
   19 // Tree is the representation of a single parsed template.
   20 type Tree struct {
   21 	Name      string    // name of the template represented by the tree.
   22 	ParseName string    // name of the top-level template during parsing, for error messages.
   23 	Root      *ListNode // top-level root of the tree.
   24 	Mode      Mode      // parsing mode.
   25 	text      string    // text parsed to create the template (or its parent)
   26 	// Parsing only; cleared after parse.
   27 	funcs      []map[string]any
   28 	lex        *lexer
   29 	token      [3]item // three-token lookahead for parser.
   30 	peekCount  int
   31 	vars       []string // variables defined at the moment.
   32 	treeSet    map[string]*Tree
   33 	actionLine int // line of left delim starting action
   34 	rangeDepth int
   35 }
   36 
   37 // A mode value is a set of flags (or 0). Modes control parser behavior.
   38 type Mode uint
   39 
   40 const (
   41 	ParseComments Mode = 1 << iota // parse comments and add them to AST
   42 	SkipFuncCheck                  // do not check that functions are defined
   43 )
   44 
   45 // Copy returns a copy of the Tree. Any parsing state is discarded.
   46 func (t *Tree) Copy() *Tree {
   47 	if t == nil {
   48 		return nil
   49 	}
   50 	return &Tree{
   51 		Name:      t.Name,
   52 		ParseName: t.ParseName,
   53 		Root:      t.Root.CopyList(),
   54 		text:      t.text,
   55 	}
   56 }
   57 
   58 // Parse returns a map from template name to parse.Tree, created by parsing the
   59 // templates described in the argument string. The top-level template will be
   60 // given the specified name. If an error is encountered, parsing stops and an
   61 // empty map is returned with the error.
   62 func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]any) (map[string]*Tree, error) {
   63 	treeSet := make(map[string]*Tree)
   64 	t := New(name)
   65 	t.text = text
   66 	_, err := t.Parse(text, leftDelim, rightDelim, treeSet, funcs...)
   67 	return treeSet, err
   68 }
   69 
   70 // next returns the next token.
   71 func (t *Tree) next() item {
   72 	if t.peekCount > 0 {
   73 		t.peekCount--
   74 	} else {
   75 		t.token[0] = t.lex.nextItem()
   76 	}
   77 	return t.token[t.peekCount]
   78 }
   79 
   80 // backup backs the input stream up one token.
   81 func (t *Tree) backup() {
   82 	t.peekCount++
   83 }
   84 
   85 // backup2 backs the input stream up two tokens.
   86 // The zeroth token is already there.
   87 func (t *Tree) backup2(t1 item) {
   88 	t.token[1] = t1
   89 	t.peekCount = 2
   90 }
   91 
   92 // backup3 backs the input stream up three tokens
   93 // The zeroth token is already there.
   94 func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back.
   95 	t.token[1] = t1
   96 	t.token[2] = t2
   97 	t.peekCount = 3
   98 }
   99 
  100 // peek returns but does not consume the next token.
  101 func (t *Tree) peek() item {
  102 	if t.peekCount > 0 {
  103 		return t.token[t.peekCount-1]
  104 	}
  105 	t.peekCount = 1
  106 	t.token[0] = t.lex.nextItem()
  107 	return t.token[0]
  108 }
  109 
  110 // nextNonSpace returns the next non-space token.
  111 func (t *Tree) nextNonSpace() (token item) {
  112 	for {
  113 		token = t.next()
  114 		if token.typ != itemSpace {
  115 			break
  116 		}
  117 	}
  118 	return token
  119 }
  120 
  121 // peekNonSpace returns but does not consume the next non-space token.
  122 func (t *Tree) peekNonSpace() item {
  123 	token := t.nextNonSpace()
  124 	t.backup()
  125 	return token
  126 }
  127 
  128 // Parsing.
  129 
  130 // New allocates a new parse tree with the given name.
  131 func New(name string, funcs ...map[string]any) *Tree {
  132 	return &Tree{
  133 		Name:  name,
  134 		funcs: funcs,
  135 	}
  136 }
  137 
  138 // ErrorContext returns a textual representation of the location of the node in the input text.
  139 // The receiver is only used when the node does not have a pointer to the tree inside,
  140 // which can occur in old code.
  141 func (t *Tree) ErrorContext(n Node) (location, context string) {
  142 	pos := int(n.Position())
  143 	tree := n.tree()
  144 	if tree == nil {
  145 		tree = t
  146 	}
  147 	text := tree.text[:pos]
  148 	byteNum := strings.LastIndex(text, "\n")
  149 	if byteNum == -1 {
  150 		byteNum = pos // On first line.
  151 	} else {
  152 		byteNum++ // After the newline.
  153 		byteNum = pos - byteNum
  154 	}
  155 	lineNum := 1 + strings.Count(text, "\n")
  156 	context = n.String()
  157 	return fmt.Sprintf("%s:%d:%d", tree.ParseName, lineNum, byteNum), context
  158 }
  159 
  160 // errorf formats the error and terminates processing.
  161 func (t *Tree) errorf(format string, args ...any) {
  162 	t.Root = nil
  163 	format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.token[0].line, format)
  164 	panic(fmt.Errorf(format, args...))
  165 }
  166 
  167 // error terminates processing.
  168 func (t *Tree) error(err error) {
  169 	t.errorf("%s", err)
  170 }
  171 
  172 // expect consumes the next token and guarantees it has the required type.
  173 func (t *Tree) expect(expected itemType, context string) item {
  174 	token := t.nextNonSpace()
  175 	if token.typ != expected {
  176 		t.unexpected(token, context)
  177 	}
  178 	return token
  179 }
  180 
  181 // expectOneOf consumes the next token and guarantees it has one of the required types.
  182 func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
  183 	token := t.nextNonSpace()
  184 	if token.typ != expected1 && token.typ != expected2 {
  185 		t.unexpected(token, context)
  186 	}
  187 	return token
  188 }
  189 
  190 // unexpected complains about the token and terminates processing.
  191 func (t *Tree) unexpected(token item, context string) {
  192 	if token.typ == itemError {
  193 		extra := ""
  194 		if t.actionLine != 0 && t.actionLine != token.line {
  195 			extra = fmt.Sprintf(" in action started at %s:%d", t.ParseName, t.actionLine)
  196 			if strings.HasSuffix(token.val, " action") {
  197 				extra = extra[len(" in action"):] // avoid "action in action"
  198 			}
  199 		}
  200 		t.errorf("%s%s", token, extra)
  201 	}
  202 	t.errorf("unexpected %s in %s", token, context)
  203 }
  204 
  205 // recover is the handler that turns panics into returns from the top level of Parse.
  206 func (t *Tree) recover(errp *error) {
  207 	e := recover()
  208 	if e != nil {
  209 		if _, ok := e.(runtime.Error); ok {
  210 			panic(e)
  211 		}
  212 		if t != nil {
  213 			t.lex.drain()
  214 			t.stopParse()
  215 		}
  216 		*errp = e.(error)
  217 	}
  218 }
  219 
  220 // startParse initializes the parser, using the lexer.
  221 func (t *Tree) startParse(funcs []map[string]any, lex *lexer, treeSet map[string]*Tree) {
  222 	t.Root = nil
  223 	t.lex = lex
  224 	t.vars = []string{"$"}
  225 	t.funcs = funcs
  226 	t.treeSet = treeSet
  227 	lex.breakOK = !t.hasFunction("break")
  228 	lex.continueOK = !t.hasFunction("continue")
  229 }
  230 
  231 // stopParse terminates parsing.
  232 func (t *Tree) stopParse() {
  233 	t.lex = nil
  234 	t.vars = nil
  235 	t.funcs = nil
  236 	t.treeSet = nil
  237 }
  238 
  239 // Parse parses the template definition string to construct a representation of
  240 // the template for execution. If either action delimiter string is empty, the
  241 // default ("{{" or "}}") is used. Embedded template definitions are added to
  242 // the treeSet map.
  243 func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]any) (tree *Tree, err error) {
  244 	defer t.recover(&err)
  245 	t.ParseName = t.Name
  246 	emitComment := t.Mode&ParseComments != 0
  247 	t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim, emitComment), treeSet)
  248 	t.text = text
  249 	t.parse()
  250 	t.add()
  251 	t.stopParse()
  252 	return t, nil
  253 }
  254 
  255 // add adds tree to t.treeSet.
  256 func (t *Tree) add() {
  257 	tree := t.treeSet[t.Name]
  258 	if tree == nil || IsEmptyTree(tree.Root) {
  259 		t.treeSet[t.Name] = t
  260 		return
  261 	}
  262 	if !IsEmptyTree(t.Root) {
  263 		t.errorf("template: multiple definition of template %q", t.Name)
  264 	}
  265 }
  266 
  267 // IsEmptyTree reports whether this tree (node) is empty of everything but space or comments.
  268 func IsEmptyTree(n Node) bool {
  269 	switch n := n.(type) {
  270 	case nil:
  271 		return true
  272 	case *ActionNode:
  273 	case *CommentNode:
  274 		return true
  275 	case *IfNode:
  276 	case *ListNode:
  277 		for _, node := range n.Nodes {
  278 			if !IsEmptyTree(node) {
  279 				return false
  280 			}
  281 		}
  282 		return true
  283 	case *RangeNode:
  284 	case *TemplateNode:
  285 	case *TextNode:
  286 		return len(bytes.TrimSpace(n.Text)) == 0
  287 	case *WithNode:
  288 	default:
  289 		panic("unknown node: " + n.String())
  290 	}
  291 	return false
  292 }
  293 
  294 // parse is the top-level parser for a template, essentially the same
  295 // as itemList except it also parses {{define}} actions.
  296 // It runs to EOF.
  297 func (t *Tree) parse() {
  298 	t.Root = t.newList(t.peek().pos)
  299 	for t.peek().typ != itemEOF {
  300 		if t.peek().typ == itemLeftDelim {
  301 			delim := t.next()
  302 			if t.nextNonSpace().typ == itemDefine {
  303 				newT := New("definition") // name will be updated once we know it.
  304 				newT.text = t.text
  305 				newT.Mode = t.Mode
  306 				newT.ParseName = t.ParseName
  307 				newT.startParse(t.funcs, t.lex, t.treeSet)
  308 				newT.parseDefinition()
  309 				continue
  310 			}
  311 			t.backup2(delim)
  312 		}
  313 		switch n := t.textOrAction(); n.Type() {
  314 		case nodeEnd, nodeElse:
  315 			t.errorf("unexpected %s", n)
  316 		default:
  317 			t.Root.append(n)
  318 		}
  319 	}
  320 }
  321 
  322 // parseDefinition parses a {{define}} ...  {{end}} template definition and
  323 // installs the definition in t.treeSet. The "define" keyword has already
  324 // been scanned.
  325 func (t *Tree) parseDefinition() {
  326 	const context = "define clause"
  327 	name := t.expectOneOf(itemString, itemRawString, context)
  328 	var err error
  329 	t.Name, err = strconv.Unquote(name.val)
  330 	if err != nil {
  331 		t.error(err)
  332 	}
  333 	t.expect(itemRightDelim, context)
  334 	var end Node
  335 	t.Root, end = t.itemList()
  336 	if end.Type() != nodeEnd {
  337 		t.errorf("unexpected %s in %s", end, context)
  338 	}
  339 	t.add()
  340 	t.stopParse()
  341 }
  342 
  343 // itemList:
  344 //	textOrAction*
  345 // Terminates at {{end}} or {{else}}, returned separately.
  346 func (t *Tree) itemList() (list *ListNode, next Node) {
  347 	list = t.newList(t.peekNonSpace().pos)
  348 	for t.peekNonSpace().typ != itemEOF {
  349 		n := t.textOrAction()
  350 		switch n.Type() {
  351 		case nodeEnd, nodeElse:
  352 			return list, n
  353 		}
  354 		list.append(n)
  355 	}
  356 	t.errorf("unexpected EOF")
  357 	return
  358 }
  359 
  360 // textOrAction:
  361 //	text | comment | action
  362 func (t *Tree) textOrAction() Node {
  363 	switch token := t.nextNonSpace(); token.typ {
  364 	case itemText:
  365 		return t.newText(token.pos, token.val)
  366 	case itemLeftDelim:
  367 		t.actionLine = token.line
  368 		defer t.clearActionLine()
  369 		return t.action()
  370 	case itemComment:
  371 		return t.newComment(token.pos, token.val)
  372 	default:
  373 		t.unexpected(token, "input")
  374 	}
  375 	return nil
  376 }
  377 
  378 func (t *Tree) clearActionLine() {
  379 	t.actionLine = 0
  380 }
  381 
  382 // Action:
  383 //	control
  384 //	command ("|" command)*
  385 // Left delim is past. Now get actions.
  386 // First word could be a keyword such as range.
  387 func (t *Tree) action() (n Node) {
  388 	switch token := t.nextNonSpace(); token.typ {
  389 	case itemBlock:
  390 		return t.blockControl()
  391 	case itemBreak:
  392 		return t.breakControl(token.pos, token.line)
  393 	case itemContinue:
  394 		return t.continueControl(token.pos, token.line)
  395 	case itemElse:
  396 		return t.elseControl()
  397 	case itemEnd:
  398 		return t.endControl()
  399 	case itemIf:
  400 		return t.ifControl()
  401 	case itemRange:
  402 		return t.rangeControl()
  403 	case itemTemplate:
  404 		return t.templateControl()
  405 	case itemWith:
  406 		return t.withControl()
  407 	}
  408 	t.backup()
  409 	token := t.peek()
  410 	// Do not pop variables; they persist until "end".
  411 	return t.newAction(token.pos, token.line, t.pipeline("command", itemRightDelim))
  412 }
  413 
  414 // Break:
  415 //	{{break}}
  416 // Break keyword is past.
  417 func (t *Tree) breakControl(pos Pos, line int) Node {
  418 	if token := t.nextNonSpace(); token.typ != itemRightDelim {
  419 		t.unexpected(token, "{{break}}")
  420 	}
  421 	if t.rangeDepth == 0 {
  422 		t.errorf("{{break}} outside {{range}}")
  423 	}
  424 	return t.newBreak(pos, line)
  425 }
  426 
  427 // Continue:
  428 //	{{continue}}
  429 // Continue keyword is past.
  430 func (t *Tree) continueControl(pos Pos, line int) Node {
  431 	if token := t.nextNonSpace(); token.typ != itemRightDelim {
  432 		t.unexpected(token, "{{continue}}")
  433 	}
  434 	if t.rangeDepth == 0 {
  435 		t.errorf("{{continue}} outside {{range}}")
  436 	}
  437 	return t.newContinue(pos, line)
  438 }
  439 
  440 // Pipeline:
  441 //	declarations? command ('|' command)*
  442 func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) {
  443 	token := t.peekNonSpace()
  444 	pipe = t.newPipeline(token.pos, token.line, nil)
  445 	// Are there declarations or assignments?
  446 decls:
  447 	if v := t.peekNonSpace(); v.typ == itemVariable {
  448 		t.next()
  449 		// Since space is a token, we need 3-token look-ahead here in the worst case:
  450 		// in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an
  451 		// argument variable rather than a declaration. So remember the token
  452 		// adjacent to the variable so we can push it back if necessary.
  453 		tokenAfterVariable := t.peek()
  454 		next := t.peekNonSpace()
  455 		switch {
  456 		case next.typ == itemAssign, next.typ == itemDeclare:
  457 			pipe.IsAssign = next.typ == itemAssign
  458 			t.nextNonSpace()
  459 			pipe.Decl = append(pipe.Decl, t.newVariable(v.pos, v.val))
  460 			t.vars = append(t.vars, v.val)
  461 		case next.typ == itemChar && next.val == ",":
  462 			t.nextNonSpace()
  463 			pipe.Decl = append(pipe.Decl, t.newVariable(v.pos, v.val))
  464 			t.vars = append(t.vars, v.val)
  465 			if context == "range" && len(pipe.Decl) < 2 {
  466 				switch t.peekNonSpace().typ {
  467 				case itemVariable, itemRightDelim, itemRightParen:
  468 					// second initialized variable in a range pipeline
  469 					goto decls
  470 				default:
  471 					t.errorf("range can only initialize variables")
  472 				}
  473 			}
  474 			t.errorf("too many declarations in %s", context)
  475 		case tokenAfterVariable.typ == itemSpace:
  476 			t.backup3(v, tokenAfterVariable)
  477 		default:
  478 			t.backup2(v)
  479 		}
  480 	}
  481 	for {
  482 		switch token := t.nextNonSpace(); token.typ {
  483 		case end:
  484 			// At this point, the pipeline is complete
  485 			t.checkPipeline(pipe, context)
  486 			return
  487 		case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
  488 			itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen:
  489 			t.backup()
  490 			pipe.append(t.command())
  491 		default:
  492 			t.unexpected(token, context)
  493 		}
  494 	}
  495 }
  496 
  497 func (t *Tree) checkPipeline(pipe *PipeNode, context string) {
  498 	// Reject empty pipelines
  499 	if len(pipe.Cmds) == 0 {
  500 		t.errorf("missing value for %s", context)
  501 	}
  502 	// Only the first command of a pipeline can start with a non executable operand
  503 	for i, c := range pipe.Cmds[1:] {
  504 		switch c.Args[0].Type() {
  505 		case NodeBool, NodeDot, NodeNil, NodeNumber, NodeString:
  506 			// With A|B|C, pipeline stage 2 is B
  507 			t.errorf("non executable command in pipeline stage %d", i+2)
  508 		}
  509 	}
  510 }
  511 
  512 func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
  513 	defer t.popVars(len(t.vars))
  514 	pipe = t.pipeline(context, itemRightDelim)
  515 	if context == "range" {
  516 		t.rangeDepth++
  517 	}
  518 	var next Node
  519 	list, next = t.itemList()
  520 	if context == "range" {
  521 		t.rangeDepth--
  522 	}
  523 	switch next.Type() {
  524 	case nodeEnd: //done
  525 	case nodeElse:
  526 		if allowElseIf {
  527 			// Special case for "else if". If the "else" is followed immediately by an "if",
  528 			// the elseControl will have left the "if" token pending. Treat
  529 			//	{{if a}}_{{else if b}}_{{end}}
  530 			// as
  531 			//	{{if a}}_{{else}}{{if b}}_{{end}}{{end}}.
  532 			// To do this, parse the if as usual and stop at it {{end}}; the subsequent{{end}}
  533 			// is assumed. This technique works even for long if-else-if chains.
  534 			// TODO: Should we allow else-if in with and range?
  535 			if t.peek().typ == itemIf {
  536 				t.next() // Consume the "if" token.
  537 				elseList = t.newList(next.Position())
  538 				elseList.append(t.ifControl())
  539 				// Do not consume the next item - only one {{end}} required.
  540 				break
  541 			}
  542 		}
  543 		elseList, next = t.itemList()
  544 		if next.Type() != nodeEnd {
  545 			t.errorf("expected end; found %s", next)
  546 		}
  547 	}
  548 	return pipe.Position(), pipe.Line, pipe, list, elseList
  549 }
  550 
  551 // If:
  552 //	{{if pipeline}} itemList {{end}}
  553 //	{{if pipeline}} itemList {{else}} itemList {{end}}
  554 // If keyword is past.
  555 func (t *Tree) ifControl() Node {
  556 	return t.newIf(t.parseControl(true, "if"))
  557 }
  558 
  559 // Range:
  560 //	{{range pipeline}} itemList {{end}}
  561 //	{{range pipeline}} itemList {{else}} itemList {{end}}
  562 // Range keyword is past.
  563 func (t *Tree) rangeControl() Node {
  564 	r := t.newRange(t.parseControl(false, "range"))
  565 	return r
  566 }
  567 
  568 // With:
  569 //	{{with pipeline}} itemList {{end}}
  570 //	{{with pipeline}} itemList {{else}} itemList {{end}}
  571 // If keyword is past.
  572 func (t *Tree) withControl() Node {
  573 	return t.newWith(t.parseControl(false, "with"))
  574 }
  575 
  576 // End:
  577 //	{{end}}
  578 // End keyword is past.
  579 func (t *Tree) endControl() Node {
  580 	return t.newEnd(t.expect(itemRightDelim, "end").pos)
  581 }
  582 
  583 // Else:
  584 //	{{else}}
  585 // Else keyword is past.
  586 func (t *Tree) elseControl() Node {
  587 	// Special case for "else if".
  588 	peek := t.peekNonSpace()
  589 	if peek.typ == itemIf {
  590 		// We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ".
  591 		return t.newElse(peek.pos, peek.line)
  592 	}
  593 	token := t.expect(itemRightDelim, "else")
  594 	return t.newElse(token.pos, token.line)
  595 }
  596 
  597 // Block:
  598 //	{{block stringValue pipeline}}
  599 // Block keyword is past.
  600 // The name must be something that can evaluate to a string.
  601 // The pipeline is mandatory.
  602 func (t *Tree) blockControl() Node {
  603 	const context = "block clause"
  604 
  605 	token := t.nextNonSpace()
  606 	name := t.parseTemplateName(token, context)
  607 	pipe := t.pipeline(context, itemRightDelim)
  608 
  609 	block := New(name) // name will be updated once we know it.
  610 	block.text = t.text
  611 	block.Mode = t.Mode
  612 	block.ParseName = t.ParseName
  613 	block.startParse(t.funcs, t.lex, t.treeSet)
  614 	var end Node
  615 	block.Root, end = block.itemList()
  616 	if end.Type() != nodeEnd {
  617 		t.errorf("unexpected %s in %s", end, context)
  618 	}
  619 	block.add()
  620 	block.stopParse()
  621 
  622 	return t.newTemplate(token.pos, token.line, name, pipe)
  623 }
  624 
  625 // Template:
  626 //	{{template stringValue pipeline}}
  627 // Template keyword is past. The name must be something that can evaluate
  628 // to a string.
  629 func (t *Tree) templateControl() Node {
  630 	const context = "template clause"
  631 	token := t.nextNonSpace()
  632 	name := t.parseTemplateName(token, context)
  633 	var pipe *PipeNode
  634 	if t.nextNonSpace().typ != itemRightDelim {
  635 		t.backup()
  636 		// Do not pop variables; they persist until "end".
  637 		pipe = t.pipeline(context, itemRightDelim)
  638 	}
  639 	return t.newTemplate(token.pos, token.line, name, pipe)
  640 }
  641 
  642 func (t *Tree) parseTemplateName(token item, context string) (name string) {
  643 	switch token.typ {
  644 	case itemString, itemRawString:
  645 		s, err := strconv.Unquote(token.val)
  646 		if err != nil {
  647 			t.error(err)
  648 		}
  649 		name = s
  650 	default:
  651 		t.unexpected(token, context)
  652 	}
  653 	return
  654 }
  655 
  656 // command:
  657 //	operand (space operand)*
  658 // space-separated arguments up to a pipeline character or right delimiter.
  659 // we consume the pipe character but leave the right delim to terminate the action.
  660 func (t *Tree) command() *CommandNode {
  661 	cmd := t.newCommand(t.peekNonSpace().pos)
  662 	for {
  663 		t.peekNonSpace() // skip leading spaces.
  664 		operand := t.operand()
  665 		if operand != nil {
  666 			cmd.append(operand)
  667 		}
  668 		switch token := t.next(); token.typ {
  669 		case itemSpace:
  670 			continue
  671 		case itemRightDelim, itemRightParen:
  672 			t.backup()
  673 		case itemPipe:
  674 			// nothing here; break loop below
  675 		default:
  676 			t.unexpected(token, "operand")
  677 		}
  678 		break
  679 	}
  680 	if len(cmd.Args) == 0 {
  681 		t.errorf("empty command")
  682 	}
  683 	return cmd
  684 }
  685 
  686 // operand:
  687 //	term .Field*
  688 // An operand is a space-separated component of a command,
  689 // a term possibly followed by field accesses.
  690 // A nil return means the next item is not an operand.
  691 func (t *Tree) operand() Node {
  692 	node := t.term()
  693 	if node == nil {
  694 		return nil
  695 	}
  696 	if t.peek().typ == itemField {
  697 		chain := t.newChain(t.peek().pos, node)
  698 		for t.peek().typ == itemField {
  699 			chain.Add(t.next().val)
  700 		}
  701 		// Compatibility with original API: If the term is of type NodeField
  702 		// or NodeVariable, just put more fields on the original.
  703 		// Otherwise, keep the Chain node.
  704 		// Obvious parsing errors involving literal values are detected here.
  705 		// More complex error cases will have to be handled at execution time.
  706 		switch node.Type() {
  707 		case NodeField:
  708 			node = t.newField(chain.Position(), chain.String())
  709 		case NodeVariable:
  710 			node = t.newVariable(chain.Position(), chain.String())
  711 		case NodeBool, NodeString, NodeNumber, NodeNil, NodeDot:
  712 			t.errorf("unexpected . after term %q", node.String())
  713 		default:
  714 			node = chain
  715 		}
  716 	}
  717 	return node
  718 }
  719 
  720 // term:
  721 //	literal (number, string, nil, boolean)
  722 //	function (identifier)
  723 //	.
  724 //	.Field
  725 //	$
  726 //	'(' pipeline ')'
  727 // A term is a simple "expression".
  728 // A nil return means the next item is not a term.
  729 func (t *Tree) term() Node {
  730 	switch token := t.nextNonSpace(); token.typ {
  731 	case itemIdentifier:
  732 		checkFunc := t.Mode&SkipFuncCheck == 0
  733 		if checkFunc && !t.hasFunction(token.val) {
  734 			t.errorf("function %q not defined", token.val)
  735 		}
  736 		return NewIdentifier(token.val).SetTree(t).SetPos(token.pos)
  737 	case itemDot:
  738 		return t.newDot(token.pos)
  739 	case itemNil:
  740 		return t.newNil(token.pos)
  741 	case itemVariable:
  742 		return t.useVar(token.pos, token.val)
  743 	case itemField:
  744 		return t.newField(token.pos, token.val)
  745 	case itemBool:
  746 		return t.newBool(token.pos, token.val == "true")
  747 	case itemCharConstant, itemComplex, itemNumber:
  748 		number, err := t.newNumber(token.pos, token.val, token.typ)
  749 		if err != nil {
  750 			t.error(err)
  751 		}
  752 		return number
  753 	case itemLeftParen:
  754 		return t.pipeline("parenthesized pipeline", itemRightParen)
  755 	case itemString, itemRawString:
  756 		s, err := strconv.Unquote(token.val)
  757 		if err != nil {
  758 			t.error(err)
  759 		}
  760 		return t.newString(token.pos, token.val, s)
  761 	}
  762 	t.backup()
  763 	return nil
  764 }
  765 
  766 // hasFunction reports if a function name exists in the Tree's maps.
  767 func (t *Tree) hasFunction(name string) bool {
  768 	for _, funcMap := range t.funcs {
  769 		if funcMap == nil {
  770 			continue
  771 		}
  772 		if funcMap[name] != nil {
  773 			return true
  774 		}
  775 	}
  776 	return false
  777 }
  778 
  779 // popVars trims the variable list to the specified length
  780 func (t *Tree) popVars(n int) {
  781 	t.vars = t.vars[:n]
  782 }
  783 
  784 // useVar returns a node for a variable reference. It errors if the
  785 // variable is not defined.
  786 func (t *Tree) useVar(pos Pos, name string) Node {
  787 	v := t.newVariable(pos, name)
  788 	for _, varName := range t.vars {
  789 		if varName == v.Ident[0] {
  790 			return v
  791 		}
  792 	}
  793 	t.errorf("undefined variable %q", v.Ident[0])
  794 	return nil
  795 }