-
-
Notifications
You must be signed in to change notification settings - Fork 238
/
ifexpressionparser.go
135 lines (105 loc) · 3.72 KB
/
ifexpressionparser.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
package parser
import (
"github.com/a-h/parse"
"github.com/a-h/templ/parser/v2/goexpression"
)
var ifExpression ifExpressionParser
var untilElseIfElseOrEnd = parse.Any(StripType(elseIfExpression), StripType(elseExpression), StripType(closeBraceWithOptionalPadding))
type ifExpressionParser struct{}
func (ifExpressionParser) Parse(pi *parse.Input) (n Node, ok bool, err error) {
var r IfExpression
start := pi.Index()
if !peekPrefix(pi, "if ") {
return r, false, nil
}
// Parse the Go if expresion.
if r.Expression, err = parseGo("if", pi, goexpression.If); err != nil {
return r, false, err
}
// Eat " {\n".
if _, ok, err = parse.All(openBraceWithOptionalPadding, parse.NewLine).Parse(pi); err != nil || !ok {
err = parse.Error("if: "+unterminatedMissingCurly, pi.PositionAt(start))
return
}
// Once we've had the start of an if block, we must conclude the block.
// Read the 'Then' nodes.
// If there's no match, there's a problem in the template nodes.
np := newTemplateNodeParser(untilElseIfElseOrEnd, "else expression or closing brace")
var thenNodes Nodes
if thenNodes, ok, err = np.Parse(pi); err != nil || !ok {
err = parse.Error("if: expected nodes, but none were found", pi.Position())
return
}
r.Then = thenNodes.Nodes
// Read the optional 'ElseIf' Nodes.
if r.ElseIfs, _, err = parse.ZeroOrMore(elseIfExpression).Parse(pi); err != nil {
return
}
// Read the optional 'Else' Nodes.
var elseNodes Nodes
if elseNodes, _, err = elseExpression.Parse(pi); err != nil {
return
}
r.Else = elseNodes.Nodes
// Read the required closing brace.
if _, ok, err = closeBraceWithOptionalPadding.Parse(pi); err != nil || !ok {
err = parse.Error("if: "+unterminatedMissingEnd, pi.Position())
return
}
return r, true, nil
}
var elseIfExpression parse.Parser[ElseIfExpression] = elseIfExpressionParser{}
type elseIfExpressionParser struct{}
func (elseIfExpressionParser) Parse(pi *parse.Input) (r ElseIfExpression, ok bool, err error) {
start := pi.Index()
// Check the prefix first.
if _, ok, err = parse.All(parse.OptionalWhitespace, closeBrace, parse.OptionalWhitespace, parse.String("else if")).Parse(pi); err != nil || !ok {
pi.Seek(start)
return
}
// Rewind to the start of the `if` statement.
pi.Seek(pi.Index() - 2)
// Parse the Go if expresion.
if r.Expression, err = parseGo("else if", pi, goexpression.If); err != nil {
return r, false, err
}
// Eat " {\n".
if _, ok, err = parse.All(openBraceWithOptionalPadding, parse.NewLine).Parse(pi); err != nil || !ok {
err = parse.Error("else if: "+unterminatedMissingCurly, pi.PositionAt(start))
return
}
// Once we've had the start of an if block, we must conclude the block.
// Read the 'Then' nodes.
// If there's no match, there's a problem in the template nodes.
np := newTemplateNodeParser(untilElseIfElseOrEnd, "else expression or closing brace")
var thenNodes Nodes
if thenNodes, ok, err = np.Parse(pi); err != nil || !ok {
err = parse.Error("if: expected nodes, but none were found", pi.Position())
return
}
r.Then = thenNodes.Nodes
return r, true, nil
}
var endElseParser = parse.All(
parse.Rune('}'),
parse.OptionalWhitespace,
parse.String("else"),
parse.OptionalWhitespace,
parse.Rune('{'),
parse.OptionalWhitespace)
var elseExpression parse.Parser[Nodes] = elseExpressionParser{}
type elseExpressionParser struct{}
func (elseExpressionParser) Parse(in *parse.Input) (r Nodes, ok bool, err error) {
start := in.Index()
// } else {
if _, ok, err = endElseParser.Parse(in); err != nil || !ok {
in.Seek(start)
return
}
// Else contents
if r, ok, err = newTemplateNodeParser(closeBraceWithOptionalPadding, "else expression closing brace").Parse(in); err != nil || !ok {
in.Seek(start)
return
}
return r, true, nil
}