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