OSDN Git Service

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