1 package parser
2
3 import (
4 "github.com/noirbizarre/gonja/nodes"
5 "github.com/noirbizarre/gonja/tokens"
6 log "github.com/sirupsen/logrus"
7 )
8
9 var compareOps = []tokens.Type{
10 tokens.Eq, tokens.Ne,
11 tokens.Gt, tokens.Gteq,
12 tokens.Lt, tokens.Lteq,
13
14 }
15
16 func BinOp(token *tokens.Token) *nodes.BinOperator {
17 return &nodes.BinOperator{token}
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 func (p *Parser) ParseLogicalExpression() (nodes.Expression, error) {
49 log.WithFields(log.Fields{
50 "current": p.Current(),
51 }).Trace("ParseLogicalExpression")
52 return p.parseOr()
53 }
54
55 func (p *Parser) parseOr() (nodes.Expression, error) {
56 log.WithFields(log.Fields{
57 "current": p.Current(),
58 }).Trace("parseOr")
59
60 var expr nodes.Expression
61
62 expr, err := p.parseAnd()
63 if err != nil {
64 return nil, err
65 }
66
67 for p.PeekName("or") != nil {
68 op := BinOp(p.Pop())
69 right, err := p.parseAnd()
70 if err != nil {
71 return nil, err
72 }
73 expr = &nodes.BinaryExpression{
74 Left: expr,
75 Right: right,
76 Operator: op,
77 }
78 }
79
80 log.WithFields(log.Fields{
81 "expr": expr,
82 }).Trace("parseOr return")
83 return expr, nil
84 }
85
86 func (p *Parser) parseAnd() (nodes.Expression, error) {
87 log.WithFields(log.Fields{
88 "current": p.Current(),
89 }).Trace("parseAnd")
90
91 var expr nodes.Expression
92
93 expr, err := p.parseNot()
94 if err != nil {
95 return nil, err
96 }
97
98 for p.PeekName("and") != nil {
99 op := BinOp(p.Pop())
100
101
102 right, err := p.parseNot()
103 if err != nil {
104 return nil, err
105 }
106
107 expr = &nodes.BinaryExpression{
108 Left: expr,
109 Right: right,
110 Operator: op,
111 }
112 }
113
114 log.WithFields(log.Fields{
115 "expr": expr,
116 }).Trace("parseAnd return")
117 return expr, nil
118 }
119
120 func (p *Parser) parseNot() (nodes.Expression, error) {
121 log.WithFields(log.Fields{
122 "current": p.Current(),
123 }).Trace("parseNot")
124
125 op := p.MatchName("not")
126 expr, err := p.parseCompare()
127 if err != nil {
128 return nil, err
129 }
130
131 if op != nil {
132 expr = &nodes.Negation{
133 Operator: op,
134 Term: expr,
135 }
136 }
137
138 log.WithFields(log.Fields{
139 "expr": expr,
140 }).Trace("parseNot return")
141 return expr, nil
142 }
143
144 func (p *Parser) parseCompare() (nodes.Expression, error) {
145 log.WithFields(log.Fields{
146 "current": p.Current(),
147 }).Trace("parseCompare")
148
149 var expr nodes.Expression
150
151 expr, err := p.ParseMath()
152 if err != nil {
153 return nil, err
154 }
155
156
157 for p.Peek(compareOps...) != nil || p.PeekName("in", "not") != nil {
158
159 op := p.Pop()
160
161
162
163
164
165
166 right, err := p.ParseMath()
167 if err != nil {
168 return nil, err
169 }
170
171 if right != nil {
172 expr = &nodes.BinaryExpression{
173 Left: expr,
174 Operator: BinOp(op),
175 Right: right,
176 }
177 }
178 }
179
180 expr, err = p.ParseTest(expr)
181 if err != nil {
182 return nil, err
183 }
184
185 log.WithFields(log.Fields{
186 "expr": expr,
187 }).Trace("parseCompare return")
188 return expr, nil
189 }
190
View as plain text