-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathparse.go
148 lines (129 loc) · 3.15 KB
/
parse.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package jade
import (
"fmt"
"net/http"
"runtime"
)
// Tree is the representation of a single parsed template.
type tree struct {
Name string // name of the template represented by the tree.
Root *listNode // top-level root of the tree.
text string // text parsed to create the template (or its parent)
// Parsing only; cleared after parse.
lex *lexer
token [3]item // three-token lookahead for parser.
peekCount int
mixin map[string]*mixinNode
block map[string]*listNode
fs http.FileSystem // embedded file system
}
// Copy returns a copy of the Tree. Any parsing state is discarded.
func (t *tree) Copy() *tree {
if t == nil {
return nil
}
return &tree{
Name: t.Name,
Root: t.Root.CopyList(),
text: t.text,
}
}
// next returns the next token.
func (t *tree) next() item {
if t.peekCount > 0 {
t.peekCount--
} else {
t.token[0] = t.lex.nextItem()
}
return t.token[t.peekCount]
}
// backup backs the input stream up one token.
func (t *tree) backup() {
t.peekCount++
}
// backup2 backs the input stream up two tokens.
// The zeroth token is already there.
func (t *tree) backup2(t1 item) {
t.token[1] = t1
t.peekCount = 2
}
// backup3 backs the input stream up three tokens
// The zeroth token is already there.
func (t *tree) backup3(t2, t1 item) { // Reverse order: we're pushing back.
t.token[1] = t1
t.token[2] = t2
t.peekCount = 3
}
// peek returns but does not consume the next token.
func (t *tree) peek() item {
if t.peekCount > 0 {
return t.token[t.peekCount-1]
}
t.peekCount = 1
t.token[0] = t.lex.nextItem()
return t.token[0]
}
// nextNonSpace returns the next non-space token.
func (t *tree) nextNonSpace() (token item) {
for {
token = t.next()
if token.typ != itemIdent && token.typ != itemEndL && token.typ != itemEmptyLine {
break
}
}
// fmt.Println("\t\tnextNonSpace", token.val)
return token
}
// peekNonSpace returns but does not consume the next non-space token.
func (t *tree) peekNonSpace() (token item) {
for {
token = t.next()
if token.typ != itemIdent && token.typ != itemEndL && token.typ != itemEmptyLine {
break
}
}
t.backup()
return token
}
// errorf formats the error and terminates processing.
func (t *tree) errorf(format string, args ...interface{}) {
t.Root = nil
format = fmt.Sprintf("template:%d: %s", t.token[0].line, format)
panic(fmt.Errorf(format, args...))
}
//
//
//
// recover is the handler that turns panics into returns from the top level of Parse.
func (t *tree) recover(errp *error) {
e := recover()
if e != nil {
if _, ok := e.(runtime.Error); ok {
panic(e)
}
if t != nil {
t.lex.drain()
t.lex = nil
}
*errp = e.(error)
}
}
func (t *tree) Parse(text []byte) (tree *tree, err error) {
defer t.recover(&err)
t.lex = lex(t.Name, text)
t.text = string(text)
t.topParse()
t.lex = nil
return t, nil
}
// New allocates a new parse tree with the given name.
func New(name string) *tree {
return &tree{
Name: name,
mixin: map[string]*mixinNode{},
block: map[string]*listNode{},
}
}