Source file src/text/template/parse/parse.go
1
2
3
4
5
6
7
8
9 package parse
10
11 import (
12 "bytes"
13 "fmt"
14 "runtime"
15 "strconv"
16 "strings"
17 )
18
19
20 type Tree struct {
21 Name string
22 ParseName string
23 Root *ListNode
24 text string
25
26 funcs []map[string]interface{}
27 lex *lexer
28 token [3]item
29 peekCount int
30 vars []string
31 treeSet map[string]*Tree
32 }
33
34
35 func (t *Tree) Copy() *Tree {
36 if t == nil {
37 return nil
38 }
39 return &Tree{
40 Name: t.Name,
41 ParseName: t.ParseName,
42 Root: t.Root.CopyList(),
43 text: t.text,
44 }
45 }
46
47
48
49
50
51 func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (map[string]*Tree, error) {
52 treeSet := make(map[string]*Tree)
53 t := New(name)
54 t.text = text
55 _, err := t.Parse(text, leftDelim, rightDelim, treeSet, funcs...)
56 return treeSet, err
57 }
58
59
60 func (t *Tree) next() item {
61 if t.peekCount > 0 {
62 t.peekCount--
63 } else {
64 t.token[0] = t.lex.nextItem()
65 }
66 return t.token[t.peekCount]
67 }
68
69
70 func (t *Tree) backup() {
71 t.peekCount++
72 }
73
74
75
76 func (t *Tree) backup2(t1 item) {
77 t.token[1] = t1
78 t.peekCount = 2
79 }
80
81
82
83 func (t *Tree) backup3(t2, t1 item) {
84 t.token[1] = t1
85 t.token[2] = t2
86 t.peekCount = 3
87 }
88
89
90 func (t *Tree) peek() item {
91 if t.peekCount > 0 {
92 return t.token[t.peekCount-1]
93 }
94 t.peekCount = 1
95 t.token[0] = t.lex.nextItem()
96 return t.token[0]
97 }
98
99
100 func (t *Tree) nextNonSpace() (token item) {
101 for {
102 token = t.next()
103 if token.typ != itemSpace {
104 break
105 }
106 }
107 return token
108 }
109
110
111 func (t *Tree) peekNonSpace() (token item) {
112 for {
113 token = t.next()
114 if token.typ != itemSpace {
115 break
116 }
117 }
118 t.backup()
119 return token
120 }
121
122
123
124
125 func New(name string, funcs ...map[string]interface{}) *Tree {
126 return &Tree{
127 Name: name,
128 funcs: funcs,
129 }
130 }
131
132
133
134
135 func (t *Tree) ErrorContext(n Node) (location, context string) {
136 pos := int(n.Position())
137 tree := n.tree()
138 if tree == nil {
139 tree = t
140 }
141 text := tree.text[:pos]
142 byteNum := strings.LastIndex(text, "\n")
143 if byteNum == -1 {
144 byteNum = pos
145 } else {
146 byteNum++
147 byteNum = pos - byteNum
148 }
149 lineNum := 1 + strings.Count(text, "\n")
150 context = n.String()
151 return fmt.Sprintf("%s:%d:%d", tree.ParseName, lineNum, byteNum), context
152 }
153
154
155 func (t *Tree) errorf(format string, args ...interface{}) {
156 t.Root = nil
157 format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.token[0].line, format)
158 panic(fmt.Errorf(format, args...))
159 }
160
161
162 func (t *Tree) error(err error) {
163 t.errorf("%s", err)
164 }
165
166
167 func (t *Tree) expect(expected itemType, context string) item {
168 token := t.nextNonSpace()
169 if token.typ != expected {
170 t.unexpected(token, context)
171 }
172 return token
173 }
174
175
176 func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
177 token := t.nextNonSpace()
178 if token.typ != expected1 && token.typ != expected2 {
179 t.unexpected(token, context)
180 }
181 return token
182 }
183
184
185 func (t *Tree) unexpected(token item, context string) {
186 t.errorf("unexpected %s in %s", token, context)
187 }
188
189
190 func (t *Tree) recover(errp *error) {
191 e := recover()
192 if e != nil {
193 if _, ok := e.(runtime.Error); ok {
194 panic(e)
195 }
196 if t != nil {
197 t.lex.drain()
198 t.stopParse()
199 }
200 *errp = e.(error)
201 }
202 }
203
204
205 func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer, treeSet map[string]*Tree) {
206 t.Root = nil
207 t.lex = lex
208 t.vars = []string{"$"}
209 t.funcs = funcs
210 t.treeSet = treeSet
211 }
212
213
214 func (t *Tree) stopParse() {
215 t.lex = nil
216 t.vars = nil
217 t.funcs = nil
218 t.treeSet = nil
219 }
220
221
222
223
224
225 func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
226 defer t.recover(&err)
227 t.ParseName = t.Name
228 t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim), treeSet)
229 t.text = text
230 t.parse()
231 t.add()
232 t.stopParse()
233 return t, nil
234 }
235
236
237 func (t *Tree) add() {
238 tree := t.treeSet[t.Name]
239 if tree == nil || IsEmptyTree(tree.Root) {
240 t.treeSet[t.Name] = t
241 return
242 }
243 if !IsEmptyTree(t.Root) {
244 t.errorf("template: multiple definition of template %q", t.Name)
245 }
246 }
247
248
249 func IsEmptyTree(n Node) bool {
250 switch n := n.(type) {
251 case nil:
252 return true
253 case *ActionNode:
254 case *IfNode:
255 case *ListNode:
256 for _, node := range n.Nodes {
257 if !IsEmptyTree(node) {
258 return false
259 }
260 }
261 return true
262 case *RangeNode:
263 case *TemplateNode:
264 case *TextNode:
265 return len(bytes.TrimSpace(n.Text)) == 0
266 case *WithNode:
267 default:
268 panic("unknown node: " + n.String())
269 }
270 return false
271 }
272
273
274
275
276 func (t *Tree) parse() {
277 t.Root = t.newList(t.peek().pos)
278 for t.peek().typ != itemEOF {
279 if t.peek().typ == itemLeftDelim {
280 delim := t.next()
281 if t.nextNonSpace().typ == itemDefine {
282 newT := New("definition")
283 newT.text = t.text
284 newT.ParseName = t.ParseName
285 newT.startParse(t.funcs, t.lex, t.treeSet)
286 newT.parseDefinition()
287 continue
288 }
289 t.backup2(delim)
290 }
291 switch n := t.textOrAction(); n.Type() {
292 case nodeEnd, nodeElse:
293 t.errorf("unexpected %s", n)
294 default:
295 t.Root.append(n)
296 }
297 }
298 }
299
300
301
302
303 func (t *Tree) parseDefinition() {
304 const context = "define clause"
305 name := t.expectOneOf(itemString, itemRawString, context)
306 var err error
307 t.Name, err = strconv.Unquote(name.val)
308 if err != nil {
309 t.error(err)
310 }
311 t.expect(itemRightDelim, context)
312 var end Node
313 t.Root, end = t.itemList()
314 if end.Type() != nodeEnd {
315 t.errorf("unexpected %s in %s", end, context)
316 }
317 t.add()
318 t.stopParse()
319 }
320
321
322
323
324 func (t *Tree) itemList() (list *ListNode, next Node) {
325 list = t.newList(t.peekNonSpace().pos)
326 for t.peekNonSpace().typ != itemEOF {
327 n := t.textOrAction()
328 switch n.Type() {
329 case nodeEnd, nodeElse:
330 return list, n
331 }
332 list.append(n)
333 }
334 t.errorf("unexpected EOF")
335 return
336 }
337
338
339
340 func (t *Tree) textOrAction() Node {
341 switch token := t.nextNonSpace(); token.typ {
342 case itemText:
343 return t.newText(token.pos, token.val)
344 case itemLeftDelim:
345 return t.action()
346 default:
347 t.unexpected(token, "input")
348 }
349 return nil
350 }
351
352
353
354
355
356
357 func (t *Tree) action() (n Node) {
358 switch token := t.nextNonSpace(); token.typ {
359 case itemBlock:
360 return t.blockControl()
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 token := t.peek()
376
377 return t.newAction(token.pos, token.line, t.pipeline("command"))
378 }
379
380
381
382 func (t *Tree) pipeline(context string) (pipe *PipeNode) {
383 token := t.peekNonSpace()
384 pipe = t.newPipeline(token.pos, token.line, nil)
385
386 decls:
387 if v := t.peekNonSpace(); v.typ == itemVariable {
388 t.next()
389
390
391
392
393 tokenAfterVariable := t.peek()
394 next := t.peekNonSpace()
395 switch {
396 case next.typ == itemAssign, next.typ == itemDeclare:
397 pipe.IsAssign = next.typ == itemAssign
398 t.nextNonSpace()
399 pipe.Decl = append(pipe.Decl, t.newVariable(v.pos, v.val))
400 t.vars = append(t.vars, v.val)
401 case next.typ == itemChar && next.val == ",":
402 t.nextNonSpace()
403 pipe.Decl = append(pipe.Decl, t.newVariable(v.pos, v.val))
404 t.vars = append(t.vars, v.val)
405 if context == "range" && len(pipe.Decl) < 2 {
406 switch t.peekNonSpace().typ {
407 case itemVariable, itemRightDelim, itemRightParen:
408
409 goto decls
410 default:
411 t.errorf("range can only initialize variables")
412 }
413 }
414 t.errorf("too many declarations in %s", context)
415 case tokenAfterVariable.typ == itemSpace:
416 t.backup3(v, tokenAfterVariable)
417 default:
418 t.backup2(v)
419 }
420 }
421 for {
422 switch token := t.nextNonSpace(); token.typ {
423 case itemRightDelim, itemRightParen:
424
425 t.checkPipeline(pipe, context)
426 if token.typ == itemRightParen {
427 t.backup()
428 }
429 return
430 case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
431 itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen:
432 t.backup()
433 pipe.append(t.command())
434 default:
435 t.unexpected(token, context)
436 }
437 }
438 }
439
440 func (t *Tree) checkPipeline(pipe *PipeNode, context string) {
441
442 if len(pipe.Cmds) == 0 {
443 t.errorf("missing value for %s", context)
444 }
445
446 for i, c := range pipe.Cmds[1:] {
447 switch c.Args[0].Type() {
448 case NodeBool, NodeDot, NodeNil, NodeNumber, NodeString:
449
450 t.errorf("non executable command in pipeline stage %d", i+2)
451 }
452 }
453 }
454
455 func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
456 defer t.popVars(len(t.vars))
457 pipe = t.pipeline(context)
458 var next Node
459 list, next = t.itemList()
460 switch next.Type() {
461 case nodeEnd:
462 case nodeElse:
463 if allowElseIf {
464
465
466
467
468
469
470
471
472 if t.peek().typ == itemIf {
473 t.next()
474 elseList = t.newList(next.Position())
475 elseList.append(t.ifControl())
476
477 break
478 }
479 }
480 elseList, next = t.itemList()
481 if next.Type() != nodeEnd {
482 t.errorf("expected end; found %s", next)
483 }
484 }
485 return pipe.Position(), pipe.Line, pipe, list, elseList
486 }
487
488
489
490
491
492 func (t *Tree) ifControl() Node {
493 return t.newIf(t.parseControl(true, "if"))
494 }
495
496
497
498
499
500 func (t *Tree) rangeControl() Node {
501 return t.newRange(t.parseControl(false, "range"))
502 }
503
504
505
506
507
508 func (t *Tree) withControl() Node {
509 return t.newWith(t.parseControl(false, "with"))
510 }
511
512
513
514
515 func (t *Tree) endControl() Node {
516 return t.newEnd(t.expect(itemRightDelim, "end").pos)
517 }
518
519
520
521
522 func (t *Tree) elseControl() Node {
523
524 peek := t.peekNonSpace()
525 if peek.typ == itemIf {
526
527 return t.newElse(peek.pos, peek.line)
528 }
529 token := t.expect(itemRightDelim, "else")
530 return t.newElse(token.pos, token.line)
531 }
532
533
534
535
536
537
538 func (t *Tree) blockControl() Node {
539 const context = "block clause"
540
541 token := t.nextNonSpace()
542 name := t.parseTemplateName(token, context)
543 pipe := t.pipeline(context)
544
545 block := New(name)
546 block.text = t.text
547 block.ParseName = t.ParseName
548 block.startParse(t.funcs, t.lex, t.treeSet)
549 var end Node
550 block.Root, end = block.itemList()
551 if end.Type() != nodeEnd {
552 t.errorf("unexpected %s in %s", end, context)
553 }
554 block.add()
555 block.stopParse()
556
557 return t.newTemplate(token.pos, token.line, name, pipe)
558 }
559
560
561
562
563
564 func (t *Tree) templateControl() Node {
565 const context = "template clause"
566 token := t.nextNonSpace()
567 name := t.parseTemplateName(token, context)
568 var pipe *PipeNode
569 if t.nextNonSpace().typ != itemRightDelim {
570 t.backup()
571
572 pipe = t.pipeline(context)
573 }
574 return t.newTemplate(token.pos, token.line, name, pipe)
575 }
576
577 func (t *Tree) parseTemplateName(token item, context string) (name string) {
578 switch token.typ {
579 case itemString, itemRawString:
580 s, err := strconv.Unquote(token.val)
581 if err != nil {
582 t.error(err)
583 }
584 name = s
585 default:
586 t.unexpected(token, context)
587 }
588 return
589 }
590
591
592
593
594
595 func (t *Tree) command() *CommandNode {
596 cmd := t.newCommand(t.peekNonSpace().pos)
597 for {
598 t.peekNonSpace()
599 operand := t.operand()
600 if operand != nil {
601 cmd.append(operand)
602 }
603 switch token := t.next(); token.typ {
604 case itemSpace:
605 continue
606 case itemError:
607 t.errorf("%s", token.val)
608 case itemRightDelim, itemRightParen:
609 t.backup()
610 case itemPipe:
611 default:
612 t.errorf("unexpected %s in operand", token)
613 }
614 break
615 }
616 if len(cmd.Args) == 0 {
617 t.errorf("empty command")
618 }
619 return cmd
620 }
621
622
623
624
625
626
627 func (t *Tree) operand() Node {
628 node := t.term()
629 if node == nil {
630 return nil
631 }
632 if t.peek().typ == itemField {
633 chain := t.newChain(t.peek().pos, node)
634 for t.peek().typ == itemField {
635 chain.Add(t.next().val)
636 }
637
638
639
640
641
642 switch node.Type() {
643 case NodeField:
644 node = t.newField(chain.Position(), chain.String())
645 case NodeVariable:
646 node = t.newVariable(chain.Position(), chain.String())
647 case NodeBool, NodeString, NodeNumber, NodeNil, NodeDot:
648 t.errorf("unexpected . after term %q", node.String())
649 default:
650 node = chain
651 }
652 }
653 return node
654 }
655
656
657
658
659
660
661
662
663
664
665 func (t *Tree) term() Node {
666 switch token := t.nextNonSpace(); token.typ {
667 case itemError:
668 t.errorf("%s", token.val)
669 case itemIdentifier:
670 if !t.hasFunction(token.val) {
671 t.errorf("function %q not defined", token.val)
672 }
673 return NewIdentifier(token.val).SetTree(t).SetPos(token.pos)
674 case itemDot:
675 return t.newDot(token.pos)
676 case itemNil:
677 return t.newNil(token.pos)
678 case itemVariable:
679 return t.useVar(token.pos, token.val)
680 case itemField:
681 return t.newField(token.pos, token.val)
682 case itemBool:
683 return t.newBool(token.pos, token.val == "true")
684 case itemCharConstant, itemComplex, itemNumber:
685 number, err := t.newNumber(token.pos, token.val, token.typ)
686 if err != nil {
687 t.error(err)
688 }
689 return number
690 case itemLeftParen:
691 pipe := t.pipeline("parenthesized pipeline")
692 if token := t.next(); token.typ != itemRightParen {
693 t.errorf("unclosed right paren: unexpected %s", token)
694 }
695 return pipe
696 case itemString, itemRawString:
697 s, err := strconv.Unquote(token.val)
698 if err != nil {
699 t.error(err)
700 }
701 return t.newString(token.pos, token.val, s)
702 }
703 t.backup()
704 return nil
705 }
706
707
708 func (t *Tree) hasFunction(name string) bool {
709 for _, funcMap := range t.funcs {
710 if funcMap == nil {
711 continue
712 }
713 if funcMap[name] != nil {
714 return true
715 }
716 }
717 return false
718 }
719
720
721 func (t *Tree) popVars(n int) {
722 t.vars = t.vars[:n]
723 }
724
725
726
727 func (t *Tree) useVar(pos Pos, name string) Node {
728 v := t.newVariable(pos, name)
729 for _, varName := range t.vars {
730 if varName == v.Ident[0] {
731 return v
732 }
733 }
734 t.errorf("undefined variable %q", v.Ident[0])
735 return nil
736 }
737
View as plain text