github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/text/template/parse/parse.go (about) 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 [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.stopParse() 214 } 215 *errp = e.(error) 216 } 217 } 218 219 // startParse initializes the parser, using the lexer. 220 func (t *Tree) startParse(funcs []map[string]any, lex *lexer, treeSet map[string]*Tree) { 221 t.Root = nil 222 t.lex = lex 223 t.vars = []string{"$"} 224 t.funcs = funcs 225 t.treeSet = treeSet 226 lex.options = lexOptions{ 227 emitComment: t.Mode&ParseComments != 0, 228 breakOK: !t.hasFunction("break"), 229 continueOK: !t.hasFunction("continue"), 230 } 231 } 232 233 // stopParse terminates parsing. 234 func (t *Tree) stopParse() { 235 t.lex = nil 236 t.vars = nil 237 t.funcs = nil 238 t.treeSet = nil 239 } 240 241 // Parse parses the template definition string to construct a representation of 242 // the template for execution. If either action delimiter string is empty, the 243 // default ("{{" or "}}") is used. Embedded template definitions are added to 244 // the treeSet map. 245 func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]any) (tree *Tree, err error) { 246 defer t.recover(&err) 247 t.ParseName = t.Name 248 lexer := lex(t.Name, text, leftDelim, rightDelim) 249 t.startParse(funcs, lexer, treeSet) 250 t.text = text 251 t.parse() 252 t.add() 253 t.stopParse() 254 return t, nil 255 } 256 257 // add adds tree to t.treeSet. 258 func (t *Tree) add() { 259 tree := t.treeSet[t.Name] 260 if tree == nil || IsEmptyTree(tree.Root) { 261 t.treeSet[t.Name] = t 262 return 263 } 264 if !IsEmptyTree(t.Root) { 265 t.errorf("template: multiple definition of template %q", t.Name) 266 } 267 } 268 269 // IsEmptyTree reports whether this tree (node) is empty of everything but space or comments. 270 func IsEmptyTree(n Node) bool { 271 switch n := n.(type) { 272 case nil: 273 return true 274 case *ActionNode: 275 case *CommentNode: 276 return true 277 case *IfNode: 278 case *ListNode: 279 for _, node := range n.Nodes { 280 if !IsEmptyTree(node) { 281 return false 282 } 283 } 284 return true 285 case *RangeNode: 286 case *TemplateNode: 287 case *TextNode: 288 return len(bytes.TrimSpace(n.Text)) == 0 289 case *WithNode: 290 default: 291 panic("unknown node: " + n.String()) 292 } 293 return false 294 } 295 296 // parse is the top-level parser for a template, essentially the same 297 // as itemList except it also parses {{define}} actions. 298 // It runs to EOF. 299 func (t *Tree) parse() { 300 t.Root = t.newList(t.peek().pos) 301 for t.peek().typ != itemEOF { 302 if t.peek().typ == itemLeftDelim { 303 delim := t.next() 304 if t.nextNonSpace().typ == itemDefine { 305 newT := New("definition") // name will be updated once we know it. 306 newT.text = t.text 307 newT.Mode = t.Mode 308 newT.ParseName = t.ParseName 309 newT.startParse(t.funcs, t.lex, t.treeSet) 310 newT.parseDefinition() 311 continue 312 } 313 t.backup2(delim) 314 } 315 switch n := t.textOrAction(); n.Type() { 316 case nodeEnd, nodeElse: 317 t.errorf("unexpected %s", n) 318 default: 319 t.Root.append(n) 320 } 321 } 322 } 323 324 // parseDefinition parses a {{define}} ... {{end}} template definition and 325 // installs the definition in t.treeSet. The "define" keyword has already 326 // been scanned. 327 func (t *Tree) parseDefinition() { 328 const context = "define clause" 329 name := t.expectOneOf(itemString, itemRawString, context) 330 var err error 331 t.Name, err = strconv.Unquote(name.val) 332 if err != nil { 333 t.error(err) 334 } 335 t.expect(itemRightDelim, context) 336 var end Node 337 t.Root, end = t.itemList() 338 if end.Type() != nodeEnd { 339 t.errorf("unexpected %s in %s", end, context) 340 } 341 t.add() 342 t.stopParse() 343 } 344 345 // itemList: 346 // 347 // textOrAction* 348 // 349 // Terminates at {{end}} or {{else}}, returned separately. 350 func (t *Tree) itemList() (list *ListNode, next Node) { 351 list = t.newList(t.peekNonSpace().pos) 352 for t.peekNonSpace().typ != itemEOF { 353 n := t.textOrAction() 354 switch n.Type() { 355 case nodeEnd, nodeElse: 356 return list, n 357 } 358 list.append(n) 359 } 360 t.errorf("unexpected EOF") 361 return 362 } 363 364 // textOrAction: 365 // 366 // text | comment | action 367 func (t *Tree) textOrAction() Node { 368 switch token := t.nextNonSpace(); token.typ { 369 case itemText: 370 return t.newText(token.pos, token.val) 371 case itemLeftDelim: 372 t.actionLine = token.line 373 defer t.clearActionLine() 374 return t.action() 375 case itemComment: 376 return t.newComment(token.pos, token.val) 377 default: 378 t.unexpected(token, "input") 379 } 380 return nil 381 } 382 383 func (t *Tree) clearActionLine() { 384 t.actionLine = 0 385 } 386 387 // Action: 388 // 389 // control 390 // command ("|" command)* 391 // 392 // Left delim is past. Now get actions. 393 // First word could be a keyword such as range. 394 func (t *Tree) action() (n Node) { 395 switch token := t.nextNonSpace(); token.typ { 396 case itemBlock: 397 return t.blockControl() 398 case itemBreak: 399 return t.breakControl(token.pos, token.line) 400 case itemContinue: 401 return t.continueControl(token.pos, token.line) 402 case itemElse: 403 return t.elseControl() 404 case itemEnd: 405 return t.endControl() 406 case itemIf: 407 return t.ifControl() 408 case itemRange: 409 return t.rangeControl() 410 case itemTemplate: 411 return t.templateControl() 412 case itemWith: 413 return t.withControl() 414 } 415 t.backup() 416 token := t.peek() 417 // Do not pop variables; they persist until "end". 418 return t.newAction(token.pos, token.line, t.pipeline("command", itemRightDelim)) 419 } 420 421 // Break: 422 // 423 // {{break}} 424 // 425 // Break keyword is past. 426 func (t *Tree) breakControl(pos Pos, line int) Node { 427 if token := t.nextNonSpace(); token.typ != itemRightDelim { 428 t.unexpected(token, "{{break}}") 429 } 430 if t.rangeDepth == 0 { 431 t.errorf("{{break}} outside {{range}}") 432 } 433 return t.newBreak(pos, line) 434 } 435 436 // Continue: 437 // 438 // {{continue}} 439 // 440 // Continue keyword is past. 441 func (t *Tree) continueControl(pos Pos, line int) Node { 442 if token := t.nextNonSpace(); token.typ != itemRightDelim { 443 t.unexpected(token, "{{continue}}") 444 } 445 if t.rangeDepth == 0 { 446 t.errorf("{{continue}} outside {{range}}") 447 } 448 return t.newContinue(pos, line) 449 } 450 451 // Pipeline: 452 // 453 // declarations? command ('|' command)* 454 func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) { 455 token := t.peekNonSpace() 456 pipe = t.newPipeline(token.pos, token.line, nil) 457 // Are there declarations or assignments? 458 decls: 459 if v := t.peekNonSpace(); v.typ == itemVariable { 460 t.next() 461 // Since space is a token, we need 3-token look-ahead here in the worst case: 462 // in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an 463 // argument variable rather than a declaration. So remember the token 464 // adjacent to the variable so we can push it back if necessary. 465 tokenAfterVariable := t.peek() 466 next := t.peekNonSpace() 467 switch { 468 case next.typ == itemAssign, next.typ == itemDeclare: 469 pipe.IsAssign = next.typ == itemAssign 470 t.nextNonSpace() 471 pipe.Decl = append(pipe.Decl, t.newVariable(v.pos, v.val)) 472 t.vars = append(t.vars, v.val) 473 case next.typ == itemChar && next.val == ",": 474 t.nextNonSpace() 475 pipe.Decl = append(pipe.Decl, t.newVariable(v.pos, v.val)) 476 t.vars = append(t.vars, v.val) 477 if context == "range" && len(pipe.Decl) < 2 { 478 switch t.peekNonSpace().typ { 479 case itemVariable, itemRightDelim, itemRightParen: 480 // second initialized variable in a range pipeline 481 goto decls 482 default: 483 t.errorf("range can only initialize variables") 484 } 485 } 486 t.errorf("too many declarations in %s", context) 487 case tokenAfterVariable.typ == itemSpace: 488 t.backup3(v, tokenAfterVariable) 489 default: 490 t.backup2(v) 491 } 492 } 493 for { 494 switch token := t.nextNonSpace(); token.typ { 495 case end: 496 // At this point, the pipeline is complete 497 t.checkPipeline(pipe, context) 498 return 499 case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier, 500 itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen: 501 t.backup() 502 pipe.append(t.command()) 503 default: 504 t.unexpected(token, context) 505 } 506 } 507 } 508 509 func (t *Tree) checkPipeline(pipe *PipeNode, context string) { 510 // Reject empty pipelines 511 if len(pipe.Cmds) == 0 { 512 t.errorf("missing value for %s", context) 513 } 514 // Only the first command of a pipeline can start with a non executable operand 515 for i, c := range pipe.Cmds[1:] { 516 switch c.Args[0].Type() { 517 case NodeBool, NodeDot, NodeNil, NodeNumber, NodeString: 518 // With A|B|C, pipeline stage 2 is B 519 t.errorf("non executable command in pipeline stage %d", i+2) 520 } 521 } 522 } 523 524 func (t *Tree) parseControl(context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) { 525 defer t.popVars(len(t.vars)) 526 pipe = t.pipeline(context, itemRightDelim) 527 if context == "range" { 528 t.rangeDepth++ 529 } 530 var next Node 531 list, next = t.itemList() 532 if context == "range" { 533 t.rangeDepth-- 534 } 535 switch next.Type() { 536 case nodeEnd: //done 537 case nodeElse: 538 // Special case for "else if" and "else with". 539 // If the "else" is followed immediately by an "if" or "with", 540 // the elseControl will have left the "if" or "with" token pending. Treat 541 // {{if a}}_{{else if b}}_{{end}} 542 // {{with a}}_{{else with b}}_{{end}} 543 // as 544 // {{if a}}_{{else}}{{if b}}_{{end}}{{end}} 545 // {{with a}}_{{else}}{{with b}}_{{end}}{{end}}. 546 // To do this, parse the "if" or "with" as usual and stop at it {{end}}; 547 // the subsequent{{end}} is assumed. This technique works even for long if-else-if chains. 548 if context == "if" && t.peek().typ == itemIf { 549 t.next() // Consume the "if" token. 550 elseList = t.newList(next.Position()) 551 elseList.append(t.ifControl()) 552 } else if context == "with" && t.peek().typ == itemWith { 553 t.next() 554 elseList = t.newList(next.Position()) 555 elseList.append(t.withControl()) 556 } else { 557 elseList, next = t.itemList() 558 if next.Type() != nodeEnd { 559 t.errorf("expected end; found %s", next) 560 } 561 } 562 } 563 return pipe.Position(), pipe.Line, pipe, list, elseList 564 } 565 566 // If: 567 // 568 // {{if pipeline}} itemList {{end}} 569 // {{if pipeline}} itemList {{else}} itemList {{end}} 570 // 571 // If keyword is past. 572 func (t *Tree) ifControl() Node { 573 return t.newIf(t.parseControl("if")) 574 } 575 576 // Range: 577 // 578 // {{range pipeline}} itemList {{end}} 579 // {{range pipeline}} itemList {{else}} itemList {{end}} 580 // 581 // Range keyword is past. 582 func (t *Tree) rangeControl() Node { 583 r := t.newRange(t.parseControl("range")) 584 return r 585 } 586 587 // With: 588 // 589 // {{with pipeline}} itemList {{end}} 590 // {{with pipeline}} itemList {{else}} itemList {{end}} 591 // 592 // If keyword is past. 593 func (t *Tree) withControl() Node { 594 return t.newWith(t.parseControl("with")) 595 } 596 597 // End: 598 // 599 // {{end}} 600 // 601 // End keyword is past. 602 func (t *Tree) endControl() Node { 603 return t.newEnd(t.expect(itemRightDelim, "end").pos) 604 } 605 606 // Else: 607 // 608 // {{else}} 609 // 610 // Else keyword is past. 611 func (t *Tree) elseControl() Node { 612 peek := t.peekNonSpace() 613 // The "{{else if ... " and "{{else with ..." will be 614 // treated as "{{else}}{{if ..." and "{{else}}{{with ...". 615 // So return the else node here. 616 if peek.typ == itemIf || peek.typ == itemWith { 617 return t.newElse(peek.pos, peek.line) 618 } 619 token := t.expect(itemRightDelim, "else") 620 return t.newElse(token.pos, token.line) 621 } 622 623 // Block: 624 // 625 // {{block stringValue pipeline}} 626 // 627 // Block keyword is past. 628 // The name must be something that can evaluate to a string. 629 // The pipeline is mandatory. 630 func (t *Tree) blockControl() Node { 631 const context = "block clause" 632 633 token := t.nextNonSpace() 634 name := t.parseTemplateName(token, context) 635 pipe := t.pipeline(context, itemRightDelim) 636 637 block := New(name) // name will be updated once we know it. 638 block.text = t.text 639 block.Mode = t.Mode 640 block.ParseName = t.ParseName 641 block.startParse(t.funcs, t.lex, t.treeSet) 642 var end Node 643 block.Root, end = block.itemList() 644 if end.Type() != nodeEnd { 645 t.errorf("unexpected %s in %s", end, context) 646 } 647 block.add() 648 block.stopParse() 649 650 return t.newTemplate(token.pos, token.line, name, pipe) 651 } 652 653 // Template: 654 // 655 // {{template stringValue pipeline}} 656 // 657 // Template keyword is past. The name must be something that can evaluate 658 // to a string. 659 func (t *Tree) templateControl() Node { 660 const context = "template clause" 661 token := t.nextNonSpace() 662 name := t.parseTemplateName(token, context) 663 var pipe *PipeNode 664 if t.nextNonSpace().typ != itemRightDelim { 665 t.backup() 666 // Do not pop variables; they persist until "end". 667 pipe = t.pipeline(context, itemRightDelim) 668 } 669 return t.newTemplate(token.pos, token.line, name, pipe) 670 } 671 672 func (t *Tree) parseTemplateName(token item, context string) (name string) { 673 switch token.typ { 674 case itemString, itemRawString: 675 s, err := strconv.Unquote(token.val) 676 if err != nil { 677 t.error(err) 678 } 679 name = s 680 default: 681 t.unexpected(token, context) 682 } 683 return 684 } 685 686 // command: 687 // 688 // operand (space operand)* 689 // 690 // space-separated arguments up to a pipeline character or right delimiter. 691 // we consume the pipe character but leave the right delim to terminate the action. 692 func (t *Tree) command() *CommandNode { 693 cmd := t.newCommand(t.peekNonSpace().pos) 694 for { 695 t.peekNonSpace() // skip leading spaces. 696 operand := t.operand() 697 if operand != nil { 698 cmd.append(operand) 699 } 700 switch token := t.next(); token.typ { 701 case itemSpace: 702 continue 703 case itemRightDelim, itemRightParen: 704 t.backup() 705 case itemPipe: 706 // nothing here; break loop below 707 default: 708 t.unexpected(token, "operand") 709 } 710 break 711 } 712 if len(cmd.Args) == 0 { 713 t.errorf("empty command") 714 } 715 return cmd 716 } 717 718 // operand: 719 // 720 // term .Field* 721 // 722 // An operand is a space-separated component of a command, 723 // a term possibly followed by field accesses. 724 // A nil return means the next item is not an operand. 725 func (t *Tree) operand() Node { 726 node := t.term() 727 if node == nil { 728 return nil 729 } 730 if t.peek().typ == itemField { 731 chain := t.newChain(t.peek().pos, node) 732 for t.peek().typ == itemField { 733 chain.Add(t.next().val) 734 } 735 // Compatibility with original API: If the term is of type NodeField 736 // or NodeVariable, just put more fields on the original. 737 // Otherwise, keep the Chain node. 738 // Obvious parsing errors involving literal values are detected here. 739 // More complex error cases will have to be handled at execution time. 740 switch node.Type() { 741 case NodeField: 742 node = t.newField(chain.Position(), chain.String()) 743 case NodeVariable: 744 node = t.newVariable(chain.Position(), chain.String()) 745 case NodeBool, NodeString, NodeNumber, NodeNil, NodeDot: 746 t.errorf("unexpected . after term %q", node.String()) 747 default: 748 node = chain 749 } 750 } 751 return node 752 } 753 754 // term: 755 // 756 // literal (number, string, nil, boolean) 757 // function (identifier) 758 // . 759 // .Field 760 // $ 761 // '(' pipeline ')' 762 // 763 // A term is a simple "expression". 764 // A nil return means the next item is not a term. 765 func (t *Tree) term() Node { 766 switch token := t.nextNonSpace(); token.typ { 767 case itemIdentifier: 768 checkFunc := t.Mode&SkipFuncCheck == 0 769 if checkFunc && !t.hasFunction(token.val) { 770 t.errorf("function %q not defined", token.val) 771 } 772 return NewIdentifier(token.val).SetTree(t).SetPos(token.pos) 773 case itemDot: 774 return t.newDot(token.pos) 775 case itemNil: 776 return t.newNil(token.pos) 777 case itemVariable: 778 return t.useVar(token.pos, token.val) 779 case itemField: 780 return t.newField(token.pos, token.val) 781 case itemBool: 782 return t.newBool(token.pos, token.val == "true") 783 case itemCharConstant, itemComplex, itemNumber: 784 number, err := t.newNumber(token.pos, token.val, token.typ) 785 if err != nil { 786 t.error(err) 787 } 788 return number 789 case itemLeftParen: 790 return t.pipeline("parenthesized pipeline", itemRightParen) 791 case itemString, itemRawString: 792 s, err := strconv.Unquote(token.val) 793 if err != nil { 794 t.error(err) 795 } 796 return t.newString(token.pos, token.val, s) 797 } 798 t.backup() 799 return nil 800 } 801 802 // hasFunction reports if a function name exists in the Tree's maps. 803 func (t *Tree) hasFunction(name string) bool { 804 for _, funcMap := range t.funcs { 805 if funcMap == nil { 806 continue 807 } 808 if funcMap[name] != nil { 809 return true 810 } 811 } 812 return false 813 } 814 815 // popVars trims the variable list to the specified length 816 func (t *Tree) popVars(n int) { 817 t.vars = t.vars[:n] 818 } 819 820 // useVar returns a node for a variable reference. It errors if the 821 // variable is not defined. 822 func (t *Tree) useVar(pos Pos, name string) Node { 823 v := t.newVariable(pos, name) 824 for _, varName := range t.vars { 825 if varName == v.Ident[0] { 826 return v 827 } 828 } 829 t.errorf("undefined variable %q", v.Ident[0]) 830 return nil 831 }