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