OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [text/] [template/] [parse/] [node.go] - Blame information for rev 747

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.