Source file src/pkg/text/template/parse/node.go
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 // Parse nodes.
6
7 package parse
8
9 import (
10 "bytes"
11 "fmt"
12 "strconv"
13 "strings"
14 )
15
16 // A node is an element in the parse tree. The interface is trivial.
17 type Node interface {
18 Type() NodeType
19 String() string
20 // Copy does a deep copy of the Node and all its components.
21 // To avoid type assertions, some XxxNodes also have specialized
22 // CopyXxx methods that return *XxxNode.
23 Copy() Node
24 }
25
26 // NodeType identifies the type of a parse tree node.
27 type NodeType int
28
29 // Type returns itself and provides an easy default implementation
30 // for embedding in a Node. Embedded in all non-trivial Nodes.
31 func (t NodeType) Type() NodeType {
32 return t
33 }
34
35 const (
36 NodeText NodeType = iota // Plain text.
37 NodeAction // A simple action such as field evaluation.
38 NodeBool // A boolean constant.
39 NodeCommand // An element of a pipeline.
40 NodeDot // The cursor, dot.
41 nodeElse // An else action. Not added to tree.
42 nodeEnd // An end action. Not added to tree.
43 NodeField // A field or method name.
44 NodeIdentifier // An identifier; always a function name.
45 NodeIf // An if action.
46 NodeList // A list of Nodes.
47 NodeNumber // A numerical constant.
48 NodePipe // A pipeline of commands.
49 NodeRange // A range action.
50 NodeString // A string constant.
51 NodeTemplate // A template invocation action.
52 NodeVariable // A $ variable.
53 NodeWith // A with action.
54 )
55
56 // Nodes.
57
58 // ListNode holds a sequence of nodes.
59 type ListNode struct {
60 NodeType
61 Nodes []Node // The element nodes in lexical order.
62 }
63
64 func newList() *ListNode {
65 return &ListNode{NodeType: NodeList}
66 }
67
68 func (l *ListNode) append(n Node) {
69 l.Nodes = append(l.Nodes, n)
70 }
71
72 func (l *ListNode) String() string {
73 b := new(bytes.Buffer)
74 for _, n := range l.Nodes {
75 fmt.Fprint(b, n)
76 }
77 return b.String()
78 }
79
80 func (l *ListNode) CopyList() *ListNode {
81 if l == nil {
82 return l
83 }
84 n := newList()
85 for _, elem := range l.Nodes {
86 n.append(elem.Copy())
87 }
88 return n
89 }
90
91 func (l *ListNode) Copy() Node {
92 return l.CopyList()
93 }
94
95 // TextNode holds plain text.
96 type TextNode struct {
97 NodeType
98 Text []byte // The text; may span newlines.
99 }
100
101 func newText(text string) *TextNode {
102 return &TextNode{NodeType: NodeText, Text: []byte(text)}
103 }
104
105 func (t *TextNode) String() string {
106 return fmt.Sprintf("%q", t.Text)
107 }
108
109 func (t *TextNode) Copy() Node {
110 return &TextNode{NodeType: NodeText, Text: append([]byte{}, t.Text...)}
111 }
112
113 // PipeNode holds a pipeline with optional declaration
114 type PipeNode struct {
115 NodeType
116 Line int // The line number in the input.
117 Decl []*VariableNode // Variable declarations in lexical order.
118 Cmds []*CommandNode // The commands in lexical order.
119 }
120
121 func newPipeline(line int, decl []*VariableNode) *PipeNode {
122 return &PipeNode{NodeType: NodePipe, Line: line, Decl: decl}
123 }
124
125 func (p *PipeNode) append(command *CommandNode) {
126 p.Cmds = append(p.Cmds, command)
127 }
128
129 func (p *PipeNode) String() string {
130 s := ""
131 if len(p.Decl) > 0 {
132 for i, v := range p.Decl {
133 if i > 0 {
134 s += ", "
135 }
136 s += v.String()
137 }
138 s += " := "
139 }
140 for i, c := range p.Cmds {
141 if i > 0 {
142 s += " | "
143 }
144 s += c.String()
145 }
146 return s
147 }
148
149 func (p *PipeNode) CopyPipe() *PipeNode {
150 if p == nil {
151 return p
152 }
153 var decl []*VariableNode
154 for _, d := range p.Decl {
155 decl = append(decl, d.Copy().(*VariableNode))
156 }
157 n := newPipeline(p.Line, decl)
158 for _, c := range p.Cmds {
159 n.append(c.Copy().(*CommandNode))
160 }
161 return n
162 }
163
164 func (p *PipeNode) Copy() Node {
165 return p.CopyPipe()
166 }
167
168 // ActionNode holds an action (something bounded by delimiters).
169 // Control actions have their own nodes; ActionNode represents simple
170 // ones such as field evaluations.
171 type ActionNode struct {
172 NodeType
173 Line int // The line number in the input.
174 Pipe *PipeNode // The pipeline in the action.
175 }
176
177 func newAction(line int, pipe *PipeNode) *ActionNode {
178 return &ActionNode{NodeType: NodeAction, Line: line, Pipe: pipe}
179 }
180
181 func (a *ActionNode) String() string {
182 return fmt.Sprintf("{{%s}}", a.Pipe)
183
184 }
185
186 func (a *ActionNode) Copy() Node {
187 return newAction(a.Line, a.Pipe.CopyPipe())
188
189 }
190
191 // CommandNode holds a command (a pipeline inside an evaluating action).
192 type CommandNode struct {
193 NodeType
194 Args []Node // Arguments in lexical order: Identifier, field, or constant.
195 }
196
197 func newCommand() *CommandNode {
198 return &CommandNode{NodeType: NodeCommand}
199 }
200
201 func (c *CommandNode) append(arg Node) {
202 c.Args = append(c.Args, arg)
203 }
204
205 func (c *CommandNode) String() string {
206 s := ""
207 for i, arg := range c.Args {
208 if i > 0 {
209 s += " "
210 }
211 s += arg.String()
212 }
213 return s
214 }
215
216 func (c *CommandNode) Copy() Node {
217 if c == nil {
218 return c
219 }
220 n := newCommand()
221 for _, c := range c.Args {
222 n.append(c.Copy())
223 }
224 return n
225 }
226
227 // IdentifierNode holds an identifier.
228 type IdentifierNode struct {
229 NodeType
230 Ident string // The identifier's name.
231 }
232
233 // NewIdentifier returns a new IdentifierNode with the given identifier name.
234 func NewIdentifier(ident string) *IdentifierNode {
235 return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident}
236 }
237
238 func (i *IdentifierNode) String() string {
239 return i.Ident
240 }
241
242 func (i *IdentifierNode) Copy() Node {
243 return NewIdentifier(i.Ident)
244 }
245
246 // VariableNode holds a list of variable names. The dollar sign is
247 // part of the name.
248 type VariableNode struct {
249 NodeType
250 Ident []string // Variable names in lexical order.
251 }
252
253 func newVariable(ident string) *VariableNode {
254 return &VariableNode{NodeType: NodeVariable, Ident: strings.Split(ident, ".")}
255 }
256
257 func (v *VariableNode) String() string {
258 s := ""
259 for i, id := range v.Ident {
260 if i > 0 {
261 s += "."
262 }
263 s += id
264 }
265 return s
266 }
267
268 func (v *VariableNode) Copy() Node {
269 return &VariableNode{NodeType: NodeVariable, Ident: append([]string{}, v.Ident...)}
270 }
271
272 // DotNode holds the special identifier '.'. It is represented by a nil pointer.
273 type DotNode bool
274
275 func newDot() *DotNode {
276 return nil
277 }
278
279 func (d *DotNode) Type() NodeType {
280 return NodeDot
281 }
282
283 func (d *DotNode) String() string {
284 return "."
285 }
286
287 func (d *DotNode) Copy() Node {
288 return newDot()
289 }
290
291 // FieldNode holds a field (identifier starting with '.').
292 // The names may be chained ('.x.y').
293 // The period is dropped from each ident.
294 type FieldNode struct {
295 NodeType
296 Ident []string // The identifiers in lexical order.
297 }
298
299 func newField(ident string) *FieldNode {
300 return &FieldNode{NodeType: NodeField, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
301 }
302
303 func (f *FieldNode) String() string {
304 s := ""
305 for _, id := range f.Ident {
306 s += "." + id
307 }
308 return s
309 }
310
311 func (f *FieldNode) Copy() Node {
312 return &FieldNode{NodeType: NodeField, Ident: append([]string{}, f.Ident...)}
313 }
314
315 // BoolNode holds a boolean constant.
316 type BoolNode struct {
317 NodeType
318 True bool // The value of the boolean constant.
319 }
320
321 func newBool(true bool) *BoolNode {
322 return &BoolNode{NodeType: NodeBool, True: true}
323 }
324
325 func (b *BoolNode) String() string {
326 if b.True {
327 return "true"
328 }
329 return "false"
330 }
331
332 func (b *BoolNode) Copy() Node {
333 return newBool(b.True)
334 }
335
336 // NumberNode holds a number: signed or unsigned integer, float, or complex.
337 // The value is parsed and stored under all the types that can represent the value.
338 // This simulates in a small amount of code the behavior of Go's ideal constants.
339 type NumberNode struct {
340 NodeType
341 IsInt bool // Number has an integral value.
342 IsUint bool // Number has an unsigned integral value.
343 IsFloat bool // Number has a floating-point value.
344 IsComplex bool // Number is complex.
345 Int64 int64 // The signed integer value.
346 Uint64 uint64 // The unsigned integer value.
347 Float64 float64 // The floating-point value.
348 Complex128 complex128 // The complex value.
349 Text string // The original textual representation from the input.
350 }
351
352 func newNumber(text string, typ itemType) (*NumberNode, error) {
353 n := &NumberNode{NodeType: NodeNumber, Text: text}
354 switch typ {
355 case itemCharConstant:
356 rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
357 if err != nil {
358 return nil, err
359 }
360 if tail != "'" {
361 return nil, fmt.Errorf("malformed character constant: %s", text)
362 }
363 n.Int64 = int64(rune)
364 n.IsInt = true
365 n.Uint64 = uint64(rune)
366 n.IsUint = true
367 n.Float64 = float64(rune) // odd but those are the rules.
368 n.IsFloat = true
369 return n, nil
370 case itemComplex:
371 // fmt.Sscan can parse the pair, so let it do the work.
372 if _, err := fmt.Sscan(text, &n.Complex128); err != nil {
373 return nil, err
374 }
375 n.IsComplex = true
376 n.simplifyComplex()
377 return n, nil
378 }
379 // Imaginary constants can only be complex unless they are zero.
380 if len(text) > 0 && text[len(text)-1] == 'i' {
381 f, err := strconv.ParseFloat(text[:len(text)-1], 64)
382 if err == nil {
383 n.IsComplex = true
384 n.Complex128 = complex(0, f)
385 n.simplifyComplex()
386 return n, nil
387 }
388 }
389 // Do integer test first so we get 0x123 etc.
390 u, err := strconv.ParseUint(text, 0, 64) // will fail for -0; fixed below.
391 if err == nil {
392 n.IsUint = true
393 n.Uint64 = u
394 }
395 i, err := strconv.ParseInt(text, 0, 64)
396 if err == nil {
397 n.IsInt = true
398 n.Int64 = i
399 if i == 0 {
400 n.IsUint = true // in case of -0.
401 n.Uint64 = u
402 }
403 }
404 // If an integer extraction succeeded, promote the float.
405 if n.IsInt {
406 n.IsFloat = true
407 n.Float64 = float64(n.Int64)
408 } else if n.IsUint {
409 n.IsFloat = true
410 n.Float64 = float64(n.Uint64)
411 } else {
412 f, err := strconv.ParseFloat(text, 64)
413 if err == nil {
414 n.IsFloat = true
415 n.Float64 = f
416 // If a floating-point extraction succeeded, extract the int if needed.
417 if !n.IsInt && float64(int64(f)) == f {
418 n.IsInt = true
419 n.Int64 = int64(f)
420 }
421 if !n.IsUint && float64(uint64(f)) == f {
422 n.IsUint = true
423 n.Uint64 = uint64(f)
424 }
425 }
426 }
427 if !n.IsInt && !n.IsUint && !n.IsFloat {
428 return nil, fmt.Errorf("illegal number syntax: %q", text)
429 }
430 return n, nil
431 }
432
433 // simplifyComplex pulls out any other types that are represented by the complex number.
434 // These all require that the imaginary part be zero.
435 func (n *NumberNode) simplifyComplex() {
436 n.IsFloat = imag(n.Complex128) == 0
437 if n.IsFloat {
438 n.Float64 = real(n.Complex128)
439 n.IsInt = float64(int64(n.Float64)) == n.Float64
440 if n.IsInt {
441 n.Int64 = int64(n.Float64)
442 }
443 n.IsUint = float64(uint64(n.Float64)) == n.Float64
444 if n.IsUint {
445 n.Uint64 = uint64(n.Float64)
446 }
447 }
448 }
449
450 func (n *NumberNode) String() string {
451 return n.Text
452 }
453
454 func (n *NumberNode) Copy() Node {
455 nn := new(NumberNode)
456 *nn = *n // Easy, fast, correct.
457 return nn
458 }
459
460 // StringNode holds a string constant. The value has been "unquoted".
461 type StringNode struct {
462 NodeType
463 Quoted string // The original text of the string, with quotes.
464 Text string // The string, after quote processing.
465 }
466
467 func newString(orig, text string) *StringNode {
468 return &StringNode{NodeType: NodeString, Quoted: orig, Text: text}
469 }
470
471 func (s *StringNode) String() string {
472 return s.Quoted
473 }
474
475 func (s *StringNode) Copy() Node {
476 return newString(s.Quoted, s.Text)
477 }
478
479 // endNode represents an {{end}} action. It is represented by a nil pointer.
480 // It does not appear in the final parse tree.
481 type endNode bool
482
483 func newEnd() *endNode {
484 return nil
485 }
486
487 func (e *endNode) Type() NodeType {
488 return nodeEnd
489 }
490
491 func (e *endNode) String() string {
492 return "{{end}}"
493 }
494
495 func (e *endNode) Copy() Node {
496 return newEnd()
497 }
498
499 // elseNode represents an {{else}} action. Does not appear in the final tree.
500 type elseNode struct {
501 NodeType
502 Line int // The line number in the input.
503 }
504
505 func newElse(line int) *elseNode {
506 return &elseNode{NodeType: nodeElse, Line: line}
507 }
508
509 func (e *elseNode) Type() NodeType {
510 return nodeElse
511 }
512
513 func (e *elseNode) String() string {
514 return "{{else}}"
515 }
516
517 func (e *elseNode) Copy() Node {
518 return newElse(e.Line)
519 }
520
521 // BranchNode is the common representation of if, range, and with.
522 type BranchNode struct {
523 NodeType
524 Line int // The line number in the input.
525 Pipe *PipeNode // The pipeline to be evaluated.
526 List *ListNode // What to execute if the value is non-empty.
527 ElseList *ListNode // What to execute if the value is empty (nil if absent).
528 }
529
530 func (b *BranchNode) String() string {
531 name := ""
532 switch b.NodeType {
533 case NodeIf:
534 name = "if"
535 case NodeRange:
536 name = "range"
537 case NodeWith:
538 name = "with"
539 default:
540 panic("unknown branch type")
541 }
542 if b.ElseList != nil {
543 return fmt.Sprintf("{{%s %s}}%s{{else}}%s{{end}}", name, b.Pipe, b.List, b.ElseList)
544 }
545 return fmt.Sprintf("{{%s %s}}%s{{end}}", name, b.Pipe, b.List)
546 }
547
548 // IfNode represents an {{if}} action and its commands.
549 type IfNode struct {
550 BranchNode
551 }
552
553 func newIf(line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
554 return &IfNode{BranchNode{NodeType: NodeIf, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
555 }
556
557 func (i *IfNode) Copy() Node {
558 return newIf(i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
559 }
560
561 // RangeNode represents a {{range}} action and its commands.
562 type RangeNode struct {
563 BranchNode
564 }
565
566 func newRange(line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
567 return &RangeNode{BranchNode{NodeType: NodeRange, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
568 }
569
570 func (r *RangeNode) Copy() Node {
571 return newRange(r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
572 }
573
574 // WithNode represents a {{with}} action and its commands.
575 type WithNode struct {
576 BranchNode
577 }
578
579 func newWith(line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
580 return &WithNode{BranchNode{NodeType: NodeWith, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
581 }
582
583 func (w *WithNode) Copy() Node {
584 return newWith(w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
585 }
586
587 // TemplateNode represents a {{template}} action.
588 type TemplateNode struct {
589 NodeType
590 Line int // The line number in the input.
591 Name string // The name of the template (unquoted).
592 Pipe *PipeNode // The command to evaluate as dot for the template.
593 }
594
595 func newTemplate(line int, name string, pipe *PipeNode) *TemplateNode {
596 return &TemplateNode{NodeType: NodeTemplate, Line: line, Name: name, Pipe: pipe}
597 }
598
599 func (t *TemplateNode) String() string {
600 if t.Pipe == nil {
601 return fmt.Sprintf("{{template %q}}", t.Name)
602 }
603 return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe)
604 }
605
606 func (t *TemplateNode) Copy() Node {
607 return newTemplate(t.Line, t.Name, t.Pipe.CopyPipe())
608 }