mirror of
https://github.com/danog/liquid.git
synced 2024-12-02 14:57:49 +01:00
Start #2 cycle tag
This commit is contained in:
parent
3c242c40f1
commit
a637d2710a
@ -30,7 +30,8 @@ The [feature parity board](https://github.com/osteele/liquid/projects/1) lists d
|
|||||||
|
|
||||||
In brief, these aren't implemented:
|
In brief, these aren't implemented:
|
||||||
|
|
||||||
- The `cycle` and `tablerow` tags
|
- The group property of the `cycle` tag
|
||||||
|
- The `tablerow` tag
|
||||||
- `{% when a or b %}`
|
- `{% when a or b %}`
|
||||||
- Loop ranges `{% for a in 1...10 %}`
|
- Loop ranges `{% for a in 1...10 %}`
|
||||||
- Error modes
|
- Error modes
|
||||||
|
@ -16,15 +16,17 @@ func init() {
|
|||||||
name string
|
name string
|
||||||
val interface{}
|
val interface{}
|
||||||
f func(Context) interface{}
|
f func(Context) interface{}
|
||||||
|
arglist []func(Context) interface{}
|
||||||
loopmods loopModifiers
|
loopmods loopModifiers
|
||||||
filter_params []valueFn
|
filter_params []valueFn
|
||||||
}
|
}
|
||||||
%type <f> expr rel filtered cond loop
|
%type <f> expr rel filtered cond loop
|
||||||
%type<filter_params> filter_params
|
%type<filter_params> filter_params
|
||||||
%type<loopmods> loop_modifiers
|
%type<loopmods> loop_modifiers
|
||||||
|
%type<arglist> arglist moreargs
|
||||||
%token <val> LITERAL
|
%token <val> LITERAL
|
||||||
%token <name> IDENTIFIER KEYWORD PROPERTY
|
%token <name> IDENTIFIER KEYWORD PROPERTY
|
||||||
%token ASSIGN LOOP
|
%token ARGLIST ASSIGN LOOP
|
||||||
%token EQ NEQ GE LE FOR IN AND OR CONTAINS
|
%token EQ NEQ GE LE FOR IN AND OR CONTAINS
|
||||||
%left '.' '|'
|
%left '.' '|'
|
||||||
%left '<' '>'
|
%left '<' '>'
|
||||||
@ -38,10 +40,27 @@ start:
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| LOOP loop { yylex.(*lexer).val = $2 }
|
| ARGLIST arglist ';' {
|
||||||
|
args := $2
|
||||||
|
yylex.(*lexer).val = func(ctx Context) interface{} {
|
||||||
|
result := make([]interface{}, len(args))
|
||||||
|
for i, fn := range args {
|
||||||
|
result[i] = fn(ctx)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| LOOP loop ';' { yylex.(*lexer).val = $2 }
|
||||||
;
|
;
|
||||||
|
|
||||||
loop: IDENTIFIER IN filtered loop_modifiers ';' {
|
arglist:
|
||||||
|
expr moreargs { $$ = append([]func(Context) interface{}{$1}, $2...) };
|
||||||
|
|
||||||
|
moreargs : /* empty */ { $$ = []func(Context) interface{}{}}
|
||||||
|
| ',' expr moreargs { $$ = append([]func(Context) interface{}{$2}, $3...) }
|
||||||
|
;
|
||||||
|
|
||||||
|
loop: IDENTIFIER IN filtered loop_modifiers {
|
||||||
name, expr, mods := $1, $3, $4
|
name, expr, mods := $1, $3, $4
|
||||||
$$ = func(ctx Context) interface{} {
|
$$ = func(ctx Context) interface{} {
|
||||||
return &Loop{name, expr(ctx), mods}
|
return &Loop{name, expr(ctx), mods}
|
||||||
|
@ -7,8 +7,14 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var parseTests = []struct{ in, expected string }{
|
var parseTests = []struct {
|
||||||
{"a | filter: b", "parse error"},
|
in string
|
||||||
|
expect interface{}
|
||||||
|
}{
|
||||||
|
{`a | filter: b`, 3},
|
||||||
|
{`%assign a = 3`, nil},
|
||||||
|
{`{%cycle 'a'`, []interface{}{"a"}},
|
||||||
|
{`{%cycle 'a', 'b'`, []interface{}{"a", "b"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
var parseErrorTests = []struct{ in, expected string }{
|
var parseErrorTests = []struct{ in, expected string }{
|
||||||
@ -25,7 +31,7 @@ func TestParse(t *testing.T) {
|
|||||||
require.NoError(t, err, test.in)
|
require.NoError(t, err, test.in)
|
||||||
value, err := expr.Evaluate(ctx)
|
value, err := expr.Evaluate(ctx)
|
||||||
require.NoError(t, err, test.in)
|
require.NoError(t, err, test.in)
|
||||||
require.Equal(t, 3, value, test.in)
|
require.Equal(t, test.expect, value, test.in)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,186 +10,207 @@ var _expression_actions []byte = []byte{
|
|||||||
1, 16, 1, 17, 1, 18, 1, 19,
|
1, 16, 1, 17, 1, 18, 1, 19,
|
||||||
1, 20, 1, 21, 1, 22, 1, 23,
|
1, 20, 1, 21, 1, 22, 1, 23,
|
||||||
1, 24, 1, 25, 1, 26, 1, 27,
|
1, 24, 1, 25, 1, 26, 1, 27,
|
||||||
1, 28, 2, 2, 3, 2, 2, 4,
|
1, 28, 1, 29, 2, 2, 3, 2,
|
||||||
2, 2, 5, 2, 2, 6, 2, 2,
|
2, 4, 2, 2, 5, 2, 2, 6,
|
||||||
7, 2, 2, 8, 2, 2, 9, 2,
|
2, 2, 7, 2, 2, 8, 2, 2,
|
||||||
2, 10,
|
9, 2, 2, 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_key_offsets []int16 = []int16{
|
var _expression_key_offsets []int16 = []int16{
|
||||||
0, 1, 2, 3, 4, 5, 6, 7,
|
0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
8, 9, 10, 12, 38, 41, 42, 43,
|
8, 9, 10, 11, 12, 14, 15, 16,
|
||||||
45, 46, 49, 51, 54, 62, 71, 80,
|
17, 18, 19, 20, 47, 50, 51, 52,
|
||||||
81, 82, 83, 93, 94, 105, 116, 127,
|
54, 55, 58, 60, 63, 71, 80, 89,
|
||||||
138, 149, 160, 171, 182, 193, 205, 216,
|
90, 91, 92, 102, 103, 114, 125, 136,
|
||||||
227, 238, 249, 260, 271, 282, 293, 304,
|
147, 158, 169, 180, 191, 202, 214, 225,
|
||||||
|
236, 247, 258, 269, 280, 291, 302, 313,
|
||||||
|
324,
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_trans_keys []byte = []byte{
|
var _expression_trans_keys []byte = []byte{
|
||||||
34, 115, 115, 105, 103, 110, 111, 111,
|
34, 115, 115, 105, 103, 110, 32, 111,
|
||||||
112, 39, 48, 57, 32, 33, 34, 37,
|
111, 112, 32, 39, 48, 57, 99, 121,
|
||||||
|
99, 108, 101, 32, 32, 33, 34, 37,
|
||||||
39, 45, 46, 60, 61, 62, 95, 97,
|
39, 45, 46, 60, 61, 62, 95, 97,
|
||||||
99, 102, 105, 110, 111, 116, 9, 13,
|
99, 102, 105, 110, 111, 116, 123, 9,
|
||||||
48, 57, 65, 90, 98, 122, 32, 9,
|
13, 48, 57, 65, 90, 98, 122, 32,
|
||||||
13, 61, 34, 97, 108, 39, 46, 48,
|
9, 13, 61, 34, 97, 108, 39, 46,
|
||||||
57, 48, 57, 46, 48, 57, 45, 95,
|
48, 57, 48, 57, 46, 48, 57, 45,
|
||||||
48, 57, 65, 90, 97, 122, 45, 63,
|
|
||||||
95, 48, 57, 65, 90, 97, 122, 45,
|
95, 48, 57, 65, 90, 97, 122, 45,
|
||||||
63, 95, 48, 57, 65, 90, 97, 122,
|
63, 95, 48, 57, 65, 90, 97, 122,
|
||||||
61, 61, 61, 45, 58, 63, 95, 48,
|
45, 63, 95, 48, 57, 65, 90, 97,
|
||||||
57, 65, 90, 97, 122, 58, 45, 58,
|
122, 61, 61, 61, 45, 58, 63, 95,
|
||||||
63, 95, 110, 48, 57, 65, 90, 97,
|
48, 57, 65, 90, 97, 122, 58, 45,
|
||||||
122, 45, 58, 63, 95, 100, 48, 57,
|
|
||||||
65, 90, 97, 122, 45, 58, 63, 95,
|
|
||||||
111, 48, 57, 65, 90, 97, 122, 45,
|
|
||||||
58, 63, 95, 110, 48, 57, 65, 90,
|
58, 63, 95, 110, 48, 57, 65, 90,
|
||||||
97, 122, 45, 58, 63, 95, 116, 48,
|
97, 122, 45, 58, 63, 95, 100, 48,
|
||||||
57, 65, 90, 97, 122, 45, 58, 63,
|
57, 65, 90, 97, 122, 45, 58, 63,
|
||||||
95, 97, 48, 57, 65, 90, 98, 122,
|
95, 111, 48, 57, 65, 90, 97, 122,
|
||||||
45, 58, 63, 95, 105, 48, 57, 65,
|
45, 58, 63, 95, 110, 48, 57, 65,
|
||||||
90, 97, 122, 45, 58, 63, 95, 110,
|
90, 97, 122, 45, 58, 63, 95, 116,
|
||||||
48, 57, 65, 90, 97, 122, 45, 58,
|
48, 57, 65, 90, 97, 122, 45, 58,
|
||||||
63, 95, 115, 48, 57, 65, 90, 97,
|
63, 95, 97, 48, 57, 65, 90, 98,
|
||||||
122, 45, 58, 63, 95, 97, 111, 48,
|
122, 45, 58, 63, 95, 105, 48, 57,
|
||||||
57, 65, 90, 98, 122, 45, 58, 63,
|
65, 90, 97, 122, 45, 58, 63, 95,
|
||||||
95, 108, 48, 57, 65, 90, 97, 122,
|
110, 48, 57, 65, 90, 97, 122, 45,
|
||||||
45, 58, 63, 95, 115, 48, 57, 65,
|
58, 63, 95, 115, 48, 57, 65, 90,
|
||||||
90, 97, 122, 45, 58, 63, 95, 101,
|
97, 122, 45, 58, 63, 95, 97, 111,
|
||||||
|
48, 57, 65, 90, 98, 122, 45, 58,
|
||||||
|
63, 95, 108, 48, 57, 65, 90, 97,
|
||||||
|
122, 45, 58, 63, 95, 115, 48, 57,
|
||||||
|
65, 90, 97, 122, 45, 58, 63, 95,
|
||||||
|
101, 48, 57, 65, 90, 97, 122, 45,
|
||||||
|
58, 63, 95, 114, 48, 57, 65, 90,
|
||||||
|
97, 122, 45, 58, 63, 95, 110, 48,
|
||||||
|
57, 65, 90, 97, 122, 45, 58, 63,
|
||||||
|
95, 105, 48, 57, 65, 90, 97, 122,
|
||||||
|
45, 58, 63, 95, 108, 48, 57, 65,
|
||||||
|
90, 97, 122, 45, 58, 63, 95, 114,
|
||||||
48, 57, 65, 90, 97, 122, 45, 58,
|
48, 57, 65, 90, 97, 122, 45, 58,
|
||||||
63, 95, 114, 48, 57, 65, 90, 97,
|
63, 95, 114, 48, 57, 65, 90, 97,
|
||||||
122, 45, 58, 63, 95, 110, 48, 57,
|
122, 45, 58, 63, 95, 117, 48, 57,
|
||||||
65, 90, 97, 122, 45, 58, 63, 95,
|
65, 90, 97, 122, 37,
|
||||||
105, 48, 57, 65, 90, 97, 122, 45,
|
|
||||||
58, 63, 95, 108, 48, 57, 65, 90,
|
|
||||||
97, 122, 45, 58, 63, 95, 114, 48,
|
|
||||||
57, 65, 90, 97, 122, 45, 58, 63,
|
|
||||||
95, 114, 48, 57, 65, 90, 97, 122,
|
|
||||||
45, 58, 63, 95, 117, 48, 57, 65,
|
|
||||||
90, 97, 122,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_single_lengths []byte = []byte{
|
var _expression_single_lengths []byte = []byte{
|
||||||
1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 0, 18, 1, 1, 1, 2,
|
1, 1, 1, 1, 0, 1, 1, 1,
|
||||||
|
1, 1, 1, 19, 1, 1, 1, 2,
|
||||||
1, 1, 0, 1, 2, 3, 3, 1,
|
1, 1, 0, 1, 2, 3, 3, 1,
|
||||||
1, 1, 4, 1, 5, 5, 5, 5,
|
1, 1, 4, 1, 5, 5, 5, 5,
|
||||||
5, 5, 5, 5, 5, 6, 5, 5,
|
5, 5, 5, 5, 5, 6, 5, 5,
|
||||||
5, 5, 5, 5, 5, 5, 5, 5,
|
5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
1,
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_range_lengths []byte = []byte{
|
var _expression_range_lengths []byte = []byte{
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 1, 4, 1, 0, 0, 0,
|
0, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
0, 0, 0, 4, 1, 0, 0, 0,
|
||||||
0, 1, 1, 1, 3, 3, 3, 0,
|
0, 1, 1, 1, 3, 3, 3, 0,
|
||||||
0, 0, 3, 0, 3, 3, 3, 3,
|
0, 0, 3, 0, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
0,
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_index_offsets []int16 = []int16{
|
var _expression_index_offsets []int16 = []int16{
|
||||||
0, 2, 4, 6, 8, 10, 12, 14,
|
0, 2, 4, 6, 8, 10, 12, 14,
|
||||||
16, 18, 20, 22, 45, 48, 50, 52,
|
16, 18, 20, 22, 24, 26, 28, 30,
|
||||||
55, 57, 60, 62, 65, 71, 78, 85,
|
32, 34, 36, 38, 62, 65, 67, 69,
|
||||||
87, 89, 91, 99, 101, 110, 119, 128,
|
72, 74, 77, 79, 82, 88, 95, 102,
|
||||||
137, 146, 155, 164, 173, 182, 192, 201,
|
104, 106, 108, 116, 118, 127, 136, 145,
|
||||||
210, 219, 228, 237, 246, 255, 264, 273,
|
154, 163, 172, 181, 190, 199, 209, 218,
|
||||||
|
227, 236, 245, 254, 263, 272, 281, 290,
|
||||||
|
299,
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_indicies []byte = []byte{
|
var _expression_indicies []byte = []byte{
|
||||||
2, 1, 3, 0, 4, 0, 5, 0,
|
2, 1, 3, 0, 4, 0, 5, 0,
|
||||||
6, 0, 7, 0, 8, 0, 9, 0,
|
6, 0, 7, 0, 8, 0, 9, 0,
|
||||||
10, 0, 2, 11, 12, 0, 14, 15,
|
10, 0, 11, 0, 12, 0, 2, 13,
|
||||||
16, 17, 18, 19, 20, 22, 23, 24,
|
14, 0, 15, 0, 16, 0, 17, 0,
|
||||||
25, 26, 27, 28, 29, 30, 31, 32,
|
18, 0, 19, 0, 20, 0, 22, 23,
|
||||||
14, 21, 25, 25, 13, 14, 14, 33,
|
24, 25, 26, 27, 28, 30, 31, 32,
|
||||||
35, 34, 2, 1, 36, 37, 34, 2,
|
33, 34, 35, 36, 37, 38, 39, 40,
|
||||||
11, 38, 21, 34, 12, 39, 12, 21,
|
41, 22, 29, 33, 33, 21, 22, 22,
|
||||||
40, 41, 41, 42, 41, 41, 34, 41,
|
42, 44, 43, 2, 1, 45, 46, 43,
|
||||||
44, 41, 41, 41, 41, 43, 41, 44,
|
2, 13, 47, 29, 43, 14, 48, 14,
|
||||||
41, 42, 41, 41, 39, 45, 34, 46,
|
29, 49, 50, 50, 51, 50, 50, 43,
|
||||||
34, 47, 34, 25, 49, 50, 25, 25,
|
50, 53, 50, 50, 50, 50, 52, 50,
|
||||||
25, 25, 48, 49, 51, 25, 49, 50,
|
53, 50, 51, 50, 50, 48, 54, 43,
|
||||||
25, 52, 25, 25, 25, 51, 25, 49,
|
55, 43, 56, 43, 33, 58, 59, 33,
|
||||||
50, 25, 53, 25, 25, 25, 51, 25,
|
33, 33, 33, 57, 58, 60, 33, 58,
|
||||||
49, 50, 25, 54, 25, 25, 25, 51,
|
59, 33, 61, 33, 33, 33, 60, 33,
|
||||||
25, 49, 50, 25, 55, 25, 25, 25,
|
58, 59, 33, 62, 33, 33, 33, 60,
|
||||||
51, 25, 49, 50, 25, 56, 25, 25,
|
33, 58, 59, 33, 63, 33, 33, 33,
|
||||||
25, 51, 25, 49, 50, 25, 57, 25,
|
60, 33, 58, 59, 33, 64, 33, 33,
|
||||||
25, 25, 51, 25, 49, 50, 25, 58,
|
33, 60, 33, 58, 59, 33, 65, 33,
|
||||||
25, 25, 25, 51, 25, 49, 50, 25,
|
33, 33, 60, 33, 58, 59, 33, 66,
|
||||||
59, 25, 25, 25, 51, 25, 49, 50,
|
33, 33, 33, 60, 33, 58, 59, 33,
|
||||||
25, 60, 25, 25, 25, 51, 25, 49,
|
67, 33, 33, 33, 60, 33, 58, 59,
|
||||||
50, 25, 61, 62, 25, 25, 25, 51,
|
33, 68, 33, 33, 33, 60, 33, 58,
|
||||||
25, 49, 50, 25, 63, 25, 25, 25,
|
59, 33, 69, 33, 33, 33, 60, 33,
|
||||||
51, 25, 49, 50, 25, 64, 25, 25,
|
58, 59, 33, 70, 71, 33, 33, 33,
|
||||||
25, 51, 25, 49, 50, 25, 65, 25,
|
60, 33, 58, 59, 33, 72, 33, 33,
|
||||||
25, 25, 51, 25, 49, 50, 25, 66,
|
33, 60, 33, 58, 59, 33, 73, 33,
|
||||||
25, 25, 25, 51, 25, 49, 50, 25,
|
33, 33, 60, 33, 58, 59, 33, 74,
|
||||||
67, 25, 25, 25, 51, 25, 49, 50,
|
33, 33, 33, 60, 33, 58, 59, 33,
|
||||||
25, 68, 25, 25, 25, 51, 25, 49,
|
75, 33, 33, 33, 60, 33, 58, 59,
|
||||||
50, 25, 69, 25, 25, 25, 51, 25,
|
33, 76, 33, 33, 33, 60, 33, 58,
|
||||||
49, 50, 25, 70, 25, 25, 25, 51,
|
59, 33, 77, 33, 33, 33, 60, 33,
|
||||||
25, 49, 50, 25, 71, 25, 25, 25,
|
58, 59, 33, 78, 33, 33, 33, 60,
|
||||||
51, 25, 49, 50, 25, 64, 25, 25,
|
33, 58, 59, 33, 79, 33, 33, 33,
|
||||||
25, 51,
|
60, 33, 58, 59, 33, 80, 33, 33,
|
||||||
|
33, 60, 33, 58, 59, 33, 73, 33,
|
||||||
|
33, 33, 60, 81, 43,
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_trans_targs []byte = []byte{
|
var _expression_trans_targs []byte = []byte{
|
||||||
11, 0, 11, 2, 3, 4, 5, 11,
|
19, 0, 19, 2, 3, 4, 5, 6,
|
||||||
7, 8, 11, 9, 18, 11, 12, 13,
|
19, 8, 9, 10, 19, 11, 26, 14,
|
||||||
14, 15, 16, 17, 20, 19, 23, 24,
|
15, 16, 17, 18, 19, 19, 20, 21,
|
||||||
25, 26, 28, 30, 37, 42, 43, 45,
|
22, 23, 24, 25, 28, 27, 31, 32,
|
||||||
46, 11, 11, 11, 1, 6, 10, 11,
|
33, 34, 36, 38, 45, 50, 51, 53,
|
||||||
11, 21, 22, 11, 11, 11, 11, 11,
|
54, 56, 19, 19, 19, 1, 7, 12,
|
||||||
11, 11, 27, 11, 29, 26, 31, 32,
|
19, 19, 29, 30, 19, 19, 19, 19,
|
||||||
33, 34, 35, 36, 26, 38, 41, 39,
|
19, 19, 19, 35, 19, 37, 34, 39,
|
||||||
40, 26, 26, 26, 44, 26, 26, 47,
|
40, 41, 42, 43, 44, 34, 46, 49,
|
||||||
|
47, 48, 34, 34, 34, 52, 34, 34,
|
||||||
|
55, 13,
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_trans_actions []byte = []byte{
|
var _expression_trans_actions []byte = []byte{
|
||||||
39, 0, 11, 0, 0, 0, 0, 7,
|
41, 0, 13, 0, 0, 0, 0, 0,
|
||||||
0, 0, 9, 0, 0, 25, 0, 0,
|
7, 0, 0, 0, 11, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 9, 27, 0, 0,
|
||||||
5, 5, 5, 5, 0, 0, 0, 0,
|
5, 5, 5, 5, 0, 0, 0, 0,
|
||||||
0, 64, 0, 0, 0, 0, 0, 0,
|
0, 66, 0, 0, 0, 0, 0, 0,
|
||||||
0, 35, 37, 15, 0, 0, 0, 29,
|
0, 5, 37, 39, 17, 0, 0, 0,
|
||||||
27, 0, 0, 33, 23, 19, 13, 17,
|
31, 29, 0, 0, 35, 25, 21, 15,
|
||||||
41, 21, 0, 31, 0, 49, 0, 0,
|
19, 43, 23, 0, 33, 0, 51, 0,
|
||||||
0, 0, 0, 0, 55, 0, 0, 0,
|
0, 0, 0, 0, 0, 57, 0, 0,
|
||||||
0, 43, 58, 61, 0, 46, 52, 0,
|
0, 0, 45, 60, 63, 0, 48, 54,
|
||||||
|
0, 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_to_state_actions []byte = []byte{
|
var _expression_to_state_actions []byte = []byte{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 1, 0, 0, 0, 0,
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0,
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_from_state_actions []byte = []byte{
|
var _expression_from_state_actions []byte = []byte{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 3, 0, 0, 0, 0,
|
0, 0, 0, 3, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0,
|
||||||
}
|
}
|
||||||
|
|
||||||
var _expression_eof_trans []int16 = []int16{
|
var _expression_eof_trans []int16 = []int16{
|
||||||
1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 0, 34, 35, 35, 35,
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
35, 35, 40, 41, 35, 44, 40, 35,
|
1, 1, 1, 0, 43, 44, 44, 44,
|
||||||
35, 35, 49, 52, 52, 52, 52, 52,
|
44, 44, 49, 50, 44, 53, 49, 44,
|
||||||
52, 52, 52, 52, 52, 52, 52, 52,
|
44, 44, 58, 61, 61, 61, 61, 61,
|
||||||
52, 52, 52, 52, 52, 52, 52, 52,
|
61, 61, 61, 61, 61, 61, 61, 61,
|
||||||
|
61, 61, 61, 61, 61, 61, 61, 61,
|
||||||
|
44,
|
||||||
}
|
}
|
||||||
|
|
||||||
const expression_start int = 11
|
const expression_start int = 19
|
||||||
const expression_first_final int = 11
|
const expression_first_final int = 19
|
||||||
const expression_error int = -1
|
const expression_error int = -1
|
||||||
|
|
||||||
const expression_en_main int = 11
|
const expression_en_main int = 19
|
||||||
|
|
||||||
//line scanner.rl:11
|
//line scanner.rl:11
|
||||||
|
|
||||||
@ -210,7 +231,7 @@ func newLexer(data []byte) *lexer {
|
|||||||
pe: len(data),
|
pe: len(data),
|
||||||
}
|
}
|
||||||
|
|
||||||
//line scanner.go:218
|
//line scanner.go:239
|
||||||
{
|
{
|
||||||
lex.cs = expression_start
|
lex.cs = expression_start
|
||||||
lex.ts = 0
|
lex.ts = 0
|
||||||
@ -226,7 +247,7 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
eof := lex.pe
|
eof := lex.pe
|
||||||
tok := 0
|
tok := 0
|
||||||
|
|
||||||
//line scanner.go:235
|
//line scanner.go:256
|
||||||
{
|
{
|
||||||
var _klen int
|
var _klen int
|
||||||
var _trans int
|
var _trans int
|
||||||
@ -247,7 +268,7 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
//line NONE:1
|
//line NONE:1
|
||||||
lex.ts = (lex.p)
|
lex.ts = (lex.p)
|
||||||
|
|
||||||
//line scanner.go:255
|
//line scanner.go:276
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,28 +345,28 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
//line scanner.rl:38
|
//line scanner.rl:38
|
||||||
lex.act = 6
|
|
||||||
case 4:
|
|
||||||
//line scanner.rl:88
|
|
||||||
lex.act = 7
|
lex.act = 7
|
||||||
|
case 4:
|
||||||
|
//line scanner.rl:89
|
||||||
|
lex.act = 8
|
||||||
case 5:
|
case 5:
|
||||||
//line scanner.rl:93
|
|
||||||
lex.act = 12
|
|
||||||
case 6:
|
|
||||||
//line scanner.rl:94
|
//line scanner.rl:94
|
||||||
lex.act = 13
|
lex.act = 13
|
||||||
case 7:
|
case 6:
|
||||||
//line scanner.rl:95
|
//line scanner.rl:95
|
||||||
lex.act = 14
|
lex.act = 14
|
||||||
case 8:
|
case 7:
|
||||||
//line scanner.rl:96
|
//line scanner.rl:96
|
||||||
lex.act = 15
|
lex.act = 15
|
||||||
case 9:
|
case 8:
|
||||||
//line scanner.rl:97
|
//line scanner.rl:97
|
||||||
lex.act = 16
|
lex.act = 16
|
||||||
|
case 9:
|
||||||
|
//line scanner.rl:98
|
||||||
|
lex.act = 17
|
||||||
case 10:
|
case 10:
|
||||||
//line scanner.rl:43
|
//line scanner.rl:43
|
||||||
lex.act = 18
|
lex.act = 19
|
||||||
case 11:
|
case 11:
|
||||||
//line scanner.rl:82
|
//line scanner.rl:82
|
||||||
lex.te = (lex.p) + 1
|
lex.te = (lex.p) + 1
|
||||||
@ -358,11 +379,19 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
//line scanner.rl:83
|
//line scanner.rl:83
|
||||||
lex.te = (lex.p) + 1
|
lex.te = (lex.p) + 1
|
||||||
{
|
{
|
||||||
tok = LOOP
|
tok = ARGLIST
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 13:
|
case 13:
|
||||||
|
//line scanner.rl:84
|
||||||
|
lex.te = (lex.p) + 1
|
||||||
|
{
|
||||||
|
tok = LOOP
|
||||||
|
(lex.p)++
|
||||||
|
goto _out
|
||||||
|
}
|
||||||
|
case 14:
|
||||||
//line scanner.rl:66
|
//line scanner.rl:66
|
||||||
lex.te = (lex.p) + 1
|
lex.te = (lex.p) + 1
|
||||||
{
|
{
|
||||||
@ -373,19 +402,11 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
goto _out
|
goto _out
|
||||||
|
|
||||||
}
|
}
|
||||||
case 14:
|
|
||||||
//line scanner.rl:89
|
|
||||||
lex.te = (lex.p) + 1
|
|
||||||
{
|
|
||||||
tok = EQ
|
|
||||||
(lex.p)++
|
|
||||||
goto _out
|
|
||||||
}
|
|
||||||
case 15:
|
case 15:
|
||||||
//line scanner.rl:90
|
//line scanner.rl:90
|
||||||
lex.te = (lex.p) + 1
|
lex.te = (lex.p) + 1
|
||||||
{
|
{
|
||||||
tok = NEQ
|
tok = EQ
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
@ -393,7 +414,7 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
//line scanner.rl:91
|
//line scanner.rl:91
|
||||||
lex.te = (lex.p) + 1
|
lex.te = (lex.p) + 1
|
||||||
{
|
{
|
||||||
tok = GE
|
tok = NEQ
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
@ -401,12 +422,20 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
//line scanner.rl:92
|
//line scanner.rl:92
|
||||||
lex.te = (lex.p) + 1
|
lex.te = (lex.p) + 1
|
||||||
{
|
{
|
||||||
tok = LE
|
tok = GE
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 18:
|
case 18:
|
||||||
//line scanner.rl:98
|
//line scanner.rl:93
|
||||||
|
lex.te = (lex.p) + 1
|
||||||
|
{
|
||||||
|
tok = LE
|
||||||
|
(lex.p)++
|
||||||
|
goto _out
|
||||||
|
}
|
||||||
|
case 19:
|
||||||
|
//line scanner.rl:99
|
||||||
lex.te = (lex.p) + 1
|
lex.te = (lex.p) + 1
|
||||||
{
|
{
|
||||||
tok = KEYWORD
|
tok = KEYWORD
|
||||||
@ -414,8 +443,8 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 19:
|
case 20:
|
||||||
//line scanner.rl:100
|
//line scanner.rl:101
|
||||||
lex.te = (lex.p) + 1
|
lex.te = (lex.p) + 1
|
||||||
{
|
{
|
||||||
tok = PROPERTY
|
tok = PROPERTY
|
||||||
@ -423,15 +452,15 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 20:
|
case 21:
|
||||||
//line scanner.rl:102
|
//line scanner.rl:103
|
||||||
lex.te = (lex.p) + 1
|
lex.te = (lex.p) + 1
|
||||||
{
|
{
|
||||||
tok = int(lex.data[lex.ts])
|
tok = int(lex.data[lex.ts])
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 21:
|
case 22:
|
||||||
//line scanner.rl:48
|
//line scanner.rl:48
|
||||||
lex.te = (lex.p)
|
lex.te = (lex.p)
|
||||||
(lex.p)--
|
(lex.p)--
|
||||||
@ -446,7 +475,7 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
goto _out
|
goto _out
|
||||||
|
|
||||||
}
|
}
|
||||||
case 22:
|
case 23:
|
||||||
//line scanner.rl:57
|
//line scanner.rl:57
|
||||||
lex.te = (lex.p)
|
lex.te = (lex.p)
|
||||||
(lex.p)--
|
(lex.p)--
|
||||||
@ -461,7 +490,7 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
goto _out
|
goto _out
|
||||||
|
|
||||||
}
|
}
|
||||||
case 23:
|
case 24:
|
||||||
//line scanner.rl:43
|
//line scanner.rl:43
|
||||||
lex.te = (lex.p)
|
lex.te = (lex.p)
|
||||||
(lex.p)--
|
(lex.p)--
|
||||||
@ -472,8 +501,8 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
goto _out
|
goto _out
|
||||||
|
|
||||||
}
|
}
|
||||||
case 24:
|
case 25:
|
||||||
//line scanner.rl:100
|
//line scanner.rl:101
|
||||||
lex.te = (lex.p)
|
lex.te = (lex.p)
|
||||||
(lex.p)--
|
(lex.p)--
|
||||||
{
|
{
|
||||||
@ -482,32 +511,32 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 25:
|
|
||||||
//line scanner.rl:101
|
|
||||||
lex.te = (lex.p)
|
|
||||||
(lex.p)--
|
|
||||||
|
|
||||||
case 26:
|
case 26:
|
||||||
//line scanner.rl:102
|
//line scanner.rl:102
|
||||||
lex.te = (lex.p)
|
lex.te = (lex.p)
|
||||||
(lex.p)--
|
(lex.p)--
|
||||||
{
|
|
||||||
tok = int(lex.data[lex.ts])
|
|
||||||
(lex.p)++
|
|
||||||
goto _out
|
|
||||||
}
|
|
||||||
case 27:
|
case 27:
|
||||||
//line scanner.rl:102
|
//line scanner.rl:103
|
||||||
(lex.p) = (lex.te) - 1
|
lex.te = (lex.p)
|
||||||
|
(lex.p)--
|
||||||
{
|
{
|
||||||
tok = int(lex.data[lex.ts])
|
tok = int(lex.data[lex.ts])
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 28:
|
case 28:
|
||||||
|
//line scanner.rl:103
|
||||||
|
(lex.p) = (lex.te) - 1
|
||||||
|
{
|
||||||
|
tok = int(lex.data[lex.ts])
|
||||||
|
(lex.p)++
|
||||||
|
goto _out
|
||||||
|
}
|
||||||
|
case 29:
|
||||||
//line NONE:1
|
//line NONE:1
|
||||||
switch lex.act {
|
switch lex.act {
|
||||||
case 6:
|
case 7:
|
||||||
{
|
{
|
||||||
(lex.p) = (lex.te) - 1
|
(lex.p) = (lex.te) - 1
|
||||||
|
|
||||||
@ -517,7 +546,7 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
goto _out
|
goto _out
|
||||||
|
|
||||||
}
|
}
|
||||||
case 7:
|
case 8:
|
||||||
{
|
{
|
||||||
(lex.p) = (lex.te) - 1
|
(lex.p) = (lex.te) - 1
|
||||||
tok = LITERAL
|
tok = LITERAL
|
||||||
@ -525,42 +554,42 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 12:
|
case 13:
|
||||||
{
|
{
|
||||||
(lex.p) = (lex.te) - 1
|
(lex.p) = (lex.te) - 1
|
||||||
tok = AND
|
tok = AND
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 13:
|
case 14:
|
||||||
{
|
{
|
||||||
(lex.p) = (lex.te) - 1
|
(lex.p) = (lex.te) - 1
|
||||||
tok = OR
|
tok = OR
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 14:
|
case 15:
|
||||||
{
|
{
|
||||||
(lex.p) = (lex.te) - 1
|
(lex.p) = (lex.te) - 1
|
||||||
tok = CONTAINS
|
tok = CONTAINS
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 15:
|
case 16:
|
||||||
{
|
{
|
||||||
(lex.p) = (lex.te) - 1
|
(lex.p) = (lex.te) - 1
|
||||||
tok = FOR
|
tok = FOR
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 16:
|
case 17:
|
||||||
{
|
{
|
||||||
(lex.p) = (lex.te) - 1
|
(lex.p) = (lex.te) - 1
|
||||||
tok = IN
|
tok = IN
|
||||||
(lex.p)++
|
(lex.p)++
|
||||||
goto _out
|
goto _out
|
||||||
}
|
}
|
||||||
case 18:
|
case 19:
|
||||||
{
|
{
|
||||||
(lex.p) = (lex.te) - 1
|
(lex.p) = (lex.te) - 1
|
||||||
|
|
||||||
@ -572,7 +601,7 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//line scanner.go:513
|
//line scanner.go:539
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,7 +616,7 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
//line NONE:1
|
//line NONE:1
|
||||||
lex.ts = 0
|
lex.ts = 0
|
||||||
|
|
||||||
//line scanner.go:527
|
//line scanner.go:553
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,7 +639,7 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//line scanner.rl:106
|
//line scanner.rl:107
|
||||||
|
|
||||||
return tok
|
return tok
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,7 @@ func (lex *lexer) Lex(out *yySymType) int {
|
|||||||
|
|
||||||
main := |*
|
main := |*
|
||||||
"%assign " => { tok = ASSIGN; fbreak; };
|
"%assign " => { tok = ASSIGN; fbreak; };
|
||||||
|
"{%cycle " => { tok = ARGLIST; fbreak; };
|
||||||
"%loop " => { tok = LOOP; fbreak; };
|
"%loop " => { tok = LOOP; fbreak; };
|
||||||
int => Int;
|
int => Int;
|
||||||
float => Float;
|
float => Float;
|
||||||
|
@ -83,4 +83,7 @@ func TestLex(t *testing.T) {
|
|||||||
require.Equal(t, "ab_c", ts[1].typ.name)
|
require.Equal(t, "ab_c", ts[1].typ.name)
|
||||||
require.Equal(t, "ab-c", ts[2].typ.name)
|
require.Equal(t, "ab-c", ts[2].typ.name)
|
||||||
require.Equal(t, "abc?", ts[3].typ.name)
|
require.Equal(t, "abc?", ts[3].typ.name)
|
||||||
|
|
||||||
|
ts, _ = scanExpression(`{%cycle 'a', 'b'`)
|
||||||
|
require.Len(t, ts, 4)
|
||||||
}
|
}
|
||||||
|
241
expression/y.go
241
expression/y.go
@ -21,6 +21,7 @@ type yySymType struct {
|
|||||||
name string
|
name string
|
||||||
val interface{}
|
val interface{}
|
||||||
f func(Context) interface{}
|
f func(Context) interface{}
|
||||||
|
arglist []func(Context) interface{}
|
||||||
loopmods loopModifiers
|
loopmods loopModifiers
|
||||||
filter_params []valueFn
|
filter_params []valueFn
|
||||||
}
|
}
|
||||||
@ -29,17 +30,18 @@ const LITERAL = 57346
|
|||||||
const IDENTIFIER = 57347
|
const IDENTIFIER = 57347
|
||||||
const KEYWORD = 57348
|
const KEYWORD = 57348
|
||||||
const PROPERTY = 57349
|
const PROPERTY = 57349
|
||||||
const ASSIGN = 57350
|
const ARGLIST = 57350
|
||||||
const LOOP = 57351
|
const ASSIGN = 57351
|
||||||
const EQ = 57352
|
const LOOP = 57352
|
||||||
const NEQ = 57353
|
const EQ = 57353
|
||||||
const GE = 57354
|
const NEQ = 57354
|
||||||
const LE = 57355
|
const GE = 57355
|
||||||
const FOR = 57356
|
const LE = 57356
|
||||||
const IN = 57357
|
const FOR = 57357
|
||||||
const AND = 57358
|
const IN = 57358
|
||||||
const OR = 57359
|
const AND = 57359
|
||||||
const CONTAINS = 57360
|
const OR = 57360
|
||||||
|
const CONTAINS = 57361
|
||||||
|
|
||||||
var yyToknames = [...]string{
|
var yyToknames = [...]string{
|
||||||
"$end",
|
"$end",
|
||||||
@ -49,6 +51,7 @@ var yyToknames = [...]string{
|
|||||||
"IDENTIFIER",
|
"IDENTIFIER",
|
||||||
"KEYWORD",
|
"KEYWORD",
|
||||||
"PROPERTY",
|
"PROPERTY",
|
||||||
|
"ARGLIST",
|
||||||
"ASSIGN",
|
"ASSIGN",
|
||||||
"LOOP",
|
"LOOP",
|
||||||
"EQ",
|
"EQ",
|
||||||
@ -66,11 +69,11 @@ var yyToknames = [...]string{
|
|||||||
"'>'",
|
"'>'",
|
||||||
"';'",
|
"';'",
|
||||||
"'='",
|
"'='",
|
||||||
|
"','",
|
||||||
"'['",
|
"'['",
|
||||||
"']'",
|
"']'",
|
||||||
"'('",
|
"'('",
|
||||||
"')'",
|
"')'",
|
||||||
"','",
|
|
||||||
}
|
}
|
||||||
var yyStatenames = [...]string{}
|
var yyStatenames = [...]string{}
|
||||||
|
|
||||||
@ -87,60 +90,67 @@ var yyExca = [...]int{
|
|||||||
|
|
||||||
const yyPrivate = 57344
|
const yyPrivate = 57344
|
||||||
|
|
||||||
const yyLast = 67
|
const yyLast = 77
|
||||||
|
|
||||||
var yyAct = [...]int{
|
var yyAct = [...]int{
|
||||||
|
|
||||||
7, 18, 51, 30, 20, 21, 24, 25, 6, 17,
|
8, 35, 21, 60, 7, 17, 23, 24, 27, 28,
|
||||||
8, 9, 26, 8, 9, 23, 22, 3, 4, 19,
|
9, 10, 33, 37, 29, 9, 10, 26, 25, 4,
|
||||||
34, 35, 36, 37, 38, 39, 40, 41, 18, 12,
|
3, 5, 22, 41, 42, 43, 44, 45, 46, 47,
|
||||||
13, 44, 44, 10, 47, 18, 10, 53, 54, 43,
|
48, 13, 14, 21, 51, 11, 21, 52, 50, 51,
|
||||||
45, 42, 12, 13, 31, 17, 19, 48, 49, 11,
|
11, 55, 21, 53, 49, 34, 20, 2, 13, 14,
|
||||||
5, 2, 55, 19, 16, 52, 32, 33, 14, 56,
|
38, 6, 36, 22, 58, 12, 22, 56, 19, 30,
|
||||||
1, 50, 27, 28, 29, 46, 15,
|
20, 63, 22, 57, 15, 31, 32, 61, 62, 39,
|
||||||
|
40, 64, 1, 16, 59, 54, 18,
|
||||||
}
|
}
|
||||||
var yyPact = [...]int{
|
var yyPact = [...]int{
|
||||||
|
|
||||||
9, -1000, 26, 53, 49, -1000, -11, -6, -1000, -1000,
|
11, -1000, 31, 59, 6, 53, -1000, 25, -5, -1000,
|
||||||
6, -1000, 6, 6, -21, -1000, 29, 51, -1000, 6,
|
-1000, 6, -1000, 6, 6, -13, 21, 26, -11, 34,
|
||||||
6, 6, 6, 6, 6, 6, 6, 13, -1000, -1000,
|
64, -1000, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
6, 6, -1000, 6, 21, 28, 28, 28, 28, 28,
|
14, -1000, -1000, 6, -1000, -1000, 6, -1000, 6, -1000,
|
||||||
28, 28, -1000, 25, 28, -11, -27, 28, -1000, -1000,
|
6, 29, 35, 35, 35, 35, 35, 35, 35, -1000,
|
||||||
32, 6, -1000, -1000, 55, 28, -1000,
|
39, 35, 26, 25, -23, 35, -1000, -1000, -1000, 62,
|
||||||
|
6, -1000, 67, 35, -1000,
|
||||||
}
|
}
|
||||||
var yyPgo = [...]int{
|
var yyPgo = [...]int{
|
||||||
|
|
||||||
0, 0, 50, 8, 51, 66, 65, 61, 60,
|
0, 0, 51, 4, 47, 76, 75, 74, 73, 1,
|
||||||
|
72,
|
||||||
}
|
}
|
||||||
var yyR1 = [...]int{
|
var yyR1 = [...]int{
|
||||||
|
|
||||||
0, 8, 8, 8, 5, 7, 7, 7, 1, 1,
|
0, 10, 10, 10, 10, 8, 9, 9, 5, 7,
|
||||||
1, 1, 1, 3, 3, 3, 6, 6, 2, 2,
|
7, 7, 1, 1, 1, 1, 1, 3, 3, 3,
|
||||||
2, 2, 2, 2, 2, 2, 4, 4, 4,
|
6, 6, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
|
4, 4, 4,
|
||||||
}
|
}
|
||||||
var yyR2 = [...]int{
|
var yyR2 = [...]int{
|
||||||
|
|
||||||
0, 2, 5, 2, 5, 0, 2, 3, 1, 1,
|
0, 2, 5, 3, 3, 2, 0, 3, 4, 0,
|
||||||
2, 4, 3, 1, 3, 4, 1, 3, 1, 3,
|
2, 3, 1, 1, 2, 4, 3, 1, 3, 4,
|
||||||
3, 3, 3, 3, 3, 3, 1, 3, 3,
|
1, 3, 1, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
1, 3, 3,
|
||||||
}
|
}
|
||||||
var yyChk = [...]int{
|
var yyChk = [...]int{
|
||||||
|
|
||||||
-1000, -8, -4, 8, 9, -2, -3, -1, 4, 5,
|
-1000, -10, -4, 9, 8, 10, -2, -3, -1, 4,
|
||||||
27, 23, 16, 17, 5, -5, 5, 20, 7, 25,
|
5, 29, 24, 17, 18, 5, -8, -1, -5, 5,
|
||||||
10, 11, 22, 21, 12, 13, 18, -4, -2, -2,
|
21, 7, 27, 11, 12, 23, 22, 13, 14, 19,
|
||||||
24, 15, 5, 6, -1, -1, -1, -1, -1, -1,
|
-4, -2, -2, 25, 24, -9, 26, 24, 16, 5,
|
||||||
-1, -1, 28, -3, -1, -3, -6, -1, 26, 23,
|
6, -1, -1, -1, -1, -1, -1, -1, -1, 30,
|
||||||
-7, 29, 23, 5, 6, -1, 4,
|
-3, -1, -1, -3, -6, -1, 28, 24, -9, -7,
|
||||||
|
26, 5, 6, -1, 4,
|
||||||
}
|
}
|
||||||
var yyDef = [...]int{
|
var yyDef = [...]int{
|
||||||
|
|
||||||
0, -2, 0, 0, 0, 26, 18, 13, 8, 9,
|
0, -2, 0, 0, 0, 0, 30, 22, 17, 12,
|
||||||
0, 1, 0, 0, 0, 3, 0, 0, 10, 0,
|
13, 0, 1, 0, 0, 0, 0, 6, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 27, 28,
|
0, 14, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 14, 0, 0, 19, 20, 21, 22, 23,
|
0, 31, 32, 0, 3, 5, 0, 4, 0, 18,
|
||||||
24, 25, 12, 0, 13, 5, 15, 16, 11, 2,
|
0, 0, 23, 24, 25, 26, 27, 28, 29, 16,
|
||||||
0, 0, 4, 6, 0, 17, 7,
|
0, 17, 6, 9, 19, 20, 15, 2, 7, 8,
|
||||||
|
0, 10, 0, 21, 11,
|
||||||
}
|
}
|
||||||
var yyTok1 = [...]int{
|
var yyTok1 = [...]int{
|
||||||
|
|
||||||
@ -148,20 +158,20 @@ var yyTok1 = [...]int{
|
|||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
27, 28, 3, 3, 29, 3, 19, 3, 3, 3,
|
29, 30, 3, 3, 26, 3, 20, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 23,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 24,
|
||||||
21, 24, 22, 3, 3, 3, 3, 3, 3, 3,
|
22, 25, 23, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 25, 3, 26, 3, 3, 3, 3, 3, 3,
|
3, 27, 3, 28, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 20,
|
3, 3, 3, 3, 21,
|
||||||
}
|
}
|
||||||
var yyTok2 = [...]int{
|
var yyTok2 = [...]int{
|
||||||
|
|
||||||
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||||
12, 13, 14, 15, 16, 17, 18,
|
12, 13, 14, 15, 16, 17, 18, 19,
|
||||||
}
|
}
|
||||||
var yyTok3 = [...]int{
|
var yyTok3 = [...]int{
|
||||||
0,
|
0,
|
||||||
@ -506,13 +516,13 @@ yydefault:
|
|||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
yyDollar = yyS[yypt-2 : yypt+1]
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
//line expressions.y:33
|
//line expressions.y:35
|
||||||
{
|
{
|
||||||
yylex.(*lexer).val = yyDollar[1].f
|
yylex.(*lexer).val = yyDollar[1].f
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
yyDollar = yyS[yypt-5 : yypt+1]
|
yyDollar = yyS[yypt-5 : yypt+1]
|
||||||
//line expressions.y:34
|
//line expressions.y:36
|
||||||
{
|
{
|
||||||
name, expr := yyDollar[2].name, yyDollar[4].f
|
name, expr := yyDollar[2].name, yyDollar[4].f
|
||||||
yylex.(*lexer).val = func(ctx Context) interface{} {
|
yylex.(*lexer).val = func(ctx Context) interface{} {
|
||||||
@ -521,29 +531,60 @@ yydefault:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
yyDollar = yyS[yypt-2 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:41
|
//line expressions.y:43
|
||||||
|
{
|
||||||
|
args := yyDollar[2].arglist
|
||||||
|
yylex.(*lexer).val = func(ctx Context) interface{} {
|
||||||
|
result := make([]interface{}, len(args))
|
||||||
|
for i, fn := range args {
|
||||||
|
result[i] = fn(ctx)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
|
//line expressions.y:53
|
||||||
{
|
{
|
||||||
yylex.(*lexer).val = yyDollar[2].f
|
yylex.(*lexer).val = yyDollar[2].f
|
||||||
}
|
}
|
||||||
case 4:
|
case 5:
|
||||||
yyDollar = yyS[yypt-5 : yypt+1]
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
//line expressions.y:44
|
//line expressions.y:57
|
||||||
|
{
|
||||||
|
yyVAL.arglist = append([]func(Context) interface{}{yyDollar[1].f}, yyDollar[2].arglist...)
|
||||||
|
}
|
||||||
|
case 6:
|
||||||
|
yyDollar = yyS[yypt-0 : yypt+1]
|
||||||
|
//line expressions.y:59
|
||||||
|
{
|
||||||
|
yyVAL.arglist = []func(Context) interface{}{}
|
||||||
|
}
|
||||||
|
case 7:
|
||||||
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
|
//line expressions.y:60
|
||||||
|
{
|
||||||
|
yyVAL.arglist = append([]func(Context) interface{}{yyDollar[2].f}, yyDollar[3].arglist...)
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
yyDollar = yyS[yypt-4 : yypt+1]
|
||||||
|
//line expressions.y:63
|
||||||
{
|
{
|
||||||
name, expr, mods := yyDollar[1].name, yyDollar[3].f, yyDollar[4].loopmods
|
name, expr, mods := yyDollar[1].name, yyDollar[3].f, yyDollar[4].loopmods
|
||||||
yyVAL.f = func(ctx Context) interface{} {
|
yyVAL.f = func(ctx Context) interface{} {
|
||||||
return &Loop{name, expr(ctx), mods}
|
return &Loop{name, expr(ctx), mods}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 5:
|
case 9:
|
||||||
yyDollar = yyS[yypt-0 : yypt+1]
|
yyDollar = yyS[yypt-0 : yypt+1]
|
||||||
//line expressions.y:52
|
//line expressions.y:71
|
||||||
{
|
{
|
||||||
yyVAL.loopmods = loopModifiers{}
|
yyVAL.loopmods = loopModifiers{}
|
||||||
}
|
}
|
||||||
case 6:
|
case 10:
|
||||||
yyDollar = yyS[yypt-2 : yypt+1]
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
//line expressions.y:53
|
//line expressions.y:72
|
||||||
{
|
{
|
||||||
switch yyDollar[2].name {
|
switch yyDollar[2].name {
|
||||||
case "reversed":
|
case "reversed":
|
||||||
@ -553,9 +594,9 @@ yydefault:
|
|||||||
}
|
}
|
||||||
yyVAL.loopmods = yyDollar[1].loopmods
|
yyVAL.loopmods = yyDollar[1].loopmods
|
||||||
}
|
}
|
||||||
case 7:
|
case 11:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:62
|
//line expressions.y:81
|
||||||
{ // TODO can this be a variable?
|
{ // TODO can this be a variable?
|
||||||
switch yyDollar[2].name {
|
switch yyDollar[2].name {
|
||||||
case "limit":
|
case "limit":
|
||||||
@ -575,65 +616,65 @@ yydefault:
|
|||||||
}
|
}
|
||||||
yyVAL.loopmods = yyDollar[1].loopmods
|
yyVAL.loopmods = yyDollar[1].loopmods
|
||||||
}
|
}
|
||||||
case 8:
|
case 12:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line expressions.y:84
|
//line expressions.y:103
|
||||||
{
|
{
|
||||||
val := yyDollar[1].val
|
val := yyDollar[1].val
|
||||||
yyVAL.f = func(_ Context) interface{} { return val }
|
yyVAL.f = func(_ Context) interface{} { return val }
|
||||||
}
|
}
|
||||||
case 9:
|
case 13:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line expressions.y:85
|
//line expressions.y:104
|
||||||
{
|
{
|
||||||
name := yyDollar[1].name
|
name := yyDollar[1].name
|
||||||
yyVAL.f = func(ctx Context) interface{} { return ctx.Get(name) }
|
yyVAL.f = func(ctx Context) interface{} { return ctx.Get(name) }
|
||||||
}
|
}
|
||||||
case 10:
|
case 14:
|
||||||
yyDollar = yyS[yypt-2 : yypt+1]
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
//line expressions.y:86
|
//line expressions.y:105
|
||||||
{
|
{
|
||||||
yyVAL.f = makeObjectPropertyExpr(yyDollar[1].f, yyDollar[2].name)
|
yyVAL.f = makeObjectPropertyExpr(yyDollar[1].f, yyDollar[2].name)
|
||||||
}
|
}
|
||||||
case 11:
|
case 15:
|
||||||
yyDollar = yyS[yypt-4 : yypt+1]
|
yyDollar = yyS[yypt-4 : yypt+1]
|
||||||
//line expressions.y:87
|
//line expressions.y:106
|
||||||
{
|
{
|
||||||
yyVAL.f = makeIndexExpr(yyDollar[1].f, yyDollar[3].f)
|
yyVAL.f = makeIndexExpr(yyDollar[1].f, yyDollar[3].f)
|
||||||
}
|
}
|
||||||
case 12:
|
case 16:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:88
|
//line expressions.y:107
|
||||||
{
|
{
|
||||||
yyVAL.f = yyDollar[2].f
|
yyVAL.f = yyDollar[2].f
|
||||||
}
|
}
|
||||||
case 14:
|
case 18:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:93
|
//line expressions.y:112
|
||||||
{
|
{
|
||||||
yyVAL.f = makeFilter(yyDollar[1].f, yyDollar[3].name, nil)
|
yyVAL.f = makeFilter(yyDollar[1].f, yyDollar[3].name, nil)
|
||||||
}
|
}
|
||||||
case 15:
|
case 19:
|
||||||
yyDollar = yyS[yypt-4 : yypt+1]
|
yyDollar = yyS[yypt-4 : yypt+1]
|
||||||
//line expressions.y:94
|
//line expressions.y:113
|
||||||
{
|
{
|
||||||
yyVAL.f = makeFilter(yyDollar[1].f, yyDollar[3].name, yyDollar[4].filter_params)
|
yyVAL.f = makeFilter(yyDollar[1].f, yyDollar[3].name, yyDollar[4].filter_params)
|
||||||
}
|
}
|
||||||
case 16:
|
case 20:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line expressions.y:98
|
//line expressions.y:117
|
||||||
{
|
{
|
||||||
yyVAL.filter_params = []valueFn{yyDollar[1].f}
|
yyVAL.filter_params = []valueFn{yyDollar[1].f}
|
||||||
}
|
}
|
||||||
case 17:
|
case 21:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:100
|
//line expressions.y:119
|
||||||
{
|
{
|
||||||
yyVAL.filter_params = append(yyDollar[1].filter_params, yyDollar[3].f)
|
yyVAL.filter_params = append(yyDollar[1].filter_params, yyDollar[3].f)
|
||||||
}
|
}
|
||||||
case 19:
|
case 23:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:104
|
//line expressions.y:123
|
||||||
{
|
{
|
||||||
fa, fb := yyDollar[1].f, yyDollar[3].f
|
fa, fb := yyDollar[1].f, yyDollar[3].f
|
||||||
yyVAL.f = func(ctx Context) interface{} {
|
yyVAL.f = func(ctx Context) interface{} {
|
||||||
@ -641,9 +682,9 @@ yydefault:
|
|||||||
return evaluator.Equal(a, b)
|
return evaluator.Equal(a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 20:
|
case 24:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:111
|
//line expressions.y:130
|
||||||
{
|
{
|
||||||
fa, fb := yyDollar[1].f, yyDollar[3].f
|
fa, fb := yyDollar[1].f, yyDollar[3].f
|
||||||
yyVAL.f = func(ctx Context) interface{} {
|
yyVAL.f = func(ctx Context) interface{} {
|
||||||
@ -651,9 +692,9 @@ yydefault:
|
|||||||
return !evaluator.Equal(a, b)
|
return !evaluator.Equal(a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 21:
|
case 25:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:118
|
//line expressions.y:137
|
||||||
{
|
{
|
||||||
fa, fb := yyDollar[1].f, yyDollar[3].f
|
fa, fb := yyDollar[1].f, yyDollar[3].f
|
||||||
yyVAL.f = func(ctx Context) interface{} {
|
yyVAL.f = func(ctx Context) interface{} {
|
||||||
@ -661,9 +702,9 @@ yydefault:
|
|||||||
return evaluator.Less(b, a)
|
return evaluator.Less(b, a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 22:
|
case 26:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:125
|
//line expressions.y:144
|
||||||
{
|
{
|
||||||
fa, fb := yyDollar[1].f, yyDollar[3].f
|
fa, fb := yyDollar[1].f, yyDollar[3].f
|
||||||
yyVAL.f = func(ctx Context) interface{} {
|
yyVAL.f = func(ctx Context) interface{} {
|
||||||
@ -671,9 +712,9 @@ yydefault:
|
|||||||
return evaluator.Less(a, b)
|
return evaluator.Less(a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 23:
|
case 27:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:132
|
//line expressions.y:151
|
||||||
{
|
{
|
||||||
fa, fb := yyDollar[1].f, yyDollar[3].f
|
fa, fb := yyDollar[1].f, yyDollar[3].f
|
||||||
yyVAL.f = func(ctx Context) interface{} {
|
yyVAL.f = func(ctx Context) interface{} {
|
||||||
@ -681,9 +722,9 @@ yydefault:
|
|||||||
return evaluator.Less(b, a) || evaluator.Equal(a, b)
|
return evaluator.Less(b, a) || evaluator.Equal(a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 24:
|
case 28:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:139
|
//line expressions.y:158
|
||||||
{
|
{
|
||||||
fa, fb := yyDollar[1].f, yyDollar[3].f
|
fa, fb := yyDollar[1].f, yyDollar[3].f
|
||||||
yyVAL.f = func(ctx Context) interface{} {
|
yyVAL.f = func(ctx Context) interface{} {
|
||||||
@ -691,24 +732,24 @@ yydefault:
|
|||||||
return evaluator.Less(a, b) || evaluator.Equal(a, b)
|
return evaluator.Less(a, b) || evaluator.Equal(a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 25:
|
case 29:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:146
|
//line expressions.y:165
|
||||||
{
|
{
|
||||||
yyVAL.f = makeContainsExpr(yyDollar[1].f, yyDollar[3].f)
|
yyVAL.f = makeContainsExpr(yyDollar[1].f, yyDollar[3].f)
|
||||||
}
|
}
|
||||||
case 27:
|
case 31:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:151
|
//line expressions.y:170
|
||||||
{
|
{
|
||||||
fa, fb := yyDollar[1].f, yyDollar[3].f
|
fa, fb := yyDollar[1].f, yyDollar[3].f
|
||||||
yyVAL.f = func(ctx Context) interface{} {
|
yyVAL.f = func(ctx Context) interface{} {
|
||||||
return evaluator.IsTrue(fa(ctx)) && evaluator.IsTrue(fb(ctx))
|
return evaluator.IsTrue(fa(ctx)) && evaluator.IsTrue(fb(ctx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 28:
|
case 32:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line expressions.y:157
|
//line expressions.y:176
|
||||||
{
|
{
|
||||||
fa, fb := yyDollar[1].f, yyDollar[3].f
|
fa, fb := yyDollar[1].f, yyDollar[3].f
|
||||||
yyVAL.f = func(ctx Context) interface{} {
|
yyVAL.f = func(ctx Context) interface{} {
|
||||||
|
@ -15,10 +15,10 @@ func addCompilerTestTags(s Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var compilerErrorTests = []struct{ in, expected string }{
|
var compilerErrorTests = []struct{ in, expected string }{
|
||||||
{"{% unknown_tag %}", "unknown tag"},
|
{`{% unknown_tag %}`, "unknown tag"},
|
||||||
{`{% block %}{% endblock %}`, "block compiler error"},
|
{`{% block %}{% endblock %}`, "block compiler error"},
|
||||||
// {`{% tag %}`, "tag compiler error"},
|
// {`{% tag %}`, "tag compiler error"},
|
||||||
// {"{%for syntax error%}{%endfor%}", "parse error"},
|
// {`{%for syntax error%}{%endfor%}`, "parse error"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompileErrors(t *testing.T) {
|
func TestCompileErrors(t *testing.T) {
|
||||||
|
@ -9,21 +9,54 @@ import (
|
|||||||
"github.com/osteele/liquid/render"
|
"github.com/osteele/liquid/render"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const forloopVarName = "forloop"
|
||||||
|
|
||||||
var errLoopContinueLoop = fmt.Errorf("continue outside a loop")
|
var errLoopContinueLoop = fmt.Errorf("continue outside a loop")
|
||||||
var errLoopBreak = fmt.Errorf("break outside a loop")
|
var errLoopBreak = fmt.Errorf("break outside a loop")
|
||||||
|
|
||||||
func breakTag(parameters string) (func(io.Writer, render.Context) error, error) {
|
func breakTag(string) (func(io.Writer, render.Context) error, error) {
|
||||||
return func(_ io.Writer, ctx render.Context) error {
|
return func(_ io.Writer, ctx render.Context) error {
|
||||||
return ctx.WrapError(errLoopBreak)
|
return ctx.WrapError(errLoopBreak)
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func continueTag(parameters string) (func(io.Writer, render.Context) error, error) {
|
func continueTag(string) (func(io.Writer, render.Context) error, error) {
|
||||||
return func(_ io.Writer, ctx render.Context) error {
|
return func(_ io.Writer, ctx render.Context) error {
|
||||||
return ctx.WrapError(errLoopContinueLoop)
|
return ctx.WrapError(errLoopContinueLoop)
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cycleTag(args string) (func(io.Writer, render.Context) error, error) {
|
||||||
|
return func(w io.Writer, ctx render.Context) error {
|
||||||
|
expr, err := expression.Parse("{%cycle " + args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
value, err := ctx.Evaluate(expr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
array := value.([]interface{})
|
||||||
|
if len(array) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
loopVar := ctx.Get(forloopVarName)
|
||||||
|
if loopVar == nil {
|
||||||
|
return ctx.Errorf("cycle must be within a forloop")
|
||||||
|
}
|
||||||
|
// the next few lines could panic if the user spoofs us by creating their own loop object
|
||||||
|
// “C++ protects against accident, not against fraud.” – Bjarne Stroustrup
|
||||||
|
loopRec := loopVar.(map[string]interface{})
|
||||||
|
cycleMap := loopRec[".cycles"].(map[string]int)
|
||||||
|
group := ""
|
||||||
|
n := cycleMap[group]
|
||||||
|
cycleMap[group] = n + 1
|
||||||
|
fmt.Println(cycleMap)
|
||||||
|
_, err = w.Write([]byte(fmt.Sprint(array[n%len(array)])))
|
||||||
|
return err
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseLoopExpression(source string) (expression.Expression, error) {
|
func parseLoopExpression(source string) (expression.Expression, error) {
|
||||||
expr, err := expression.Parse("%loop " + source)
|
expr, err := expression.Parse("%loop " + source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -69,11 +102,11 @@ func loopTagParser(node render.BlockNode) (func(io.Writer, render.Context) error
|
|||||||
length = rt.Len()
|
length = rt.Len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const forloopName = "forloop"
|
|
||||||
defer func(index, forloop interface{}) {
|
defer func(index, forloop interface{}) {
|
||||||
ctx.Set(forloopName, index)
|
ctx.Set(forloopVarName, index)
|
||||||
ctx.Set(loop.Variable, forloop)
|
ctx.Set(loop.Variable, forloop)
|
||||||
}(ctx.Get(forloopName), ctx.Get(loop.Variable))
|
}(ctx.Get(forloopVarName), ctx.Get(loop.Variable))
|
||||||
|
cycleMap := map[string]int{}
|
||||||
loop:
|
loop:
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
j := i
|
j := i
|
||||||
@ -81,7 +114,7 @@ func loopTagParser(node render.BlockNode) (func(io.Writer, render.Context) error
|
|||||||
j = rt.Len() - 1 - i
|
j = rt.Len() - 1 - i
|
||||||
}
|
}
|
||||||
ctx.Set(loop.Variable, rt.Index(j).Interface())
|
ctx.Set(loop.Variable, rt.Index(j).Interface())
|
||||||
ctx.Set(forloopName, map[string]interface{}{
|
ctx.Set(forloopVarName, map[string]interface{}{
|
||||||
"first": i == 0,
|
"first": i == 0,
|
||||||
"last": i == length-1,
|
"last": i == length-1,
|
||||||
"index": i + 1,
|
"index": i + 1,
|
||||||
@ -89,6 +122,7 @@ func loopTagParser(node render.BlockNode) (func(io.Writer, render.Context) error
|
|||||||
"rindex": length - i,
|
"rindex": length - i,
|
||||||
"rindex0": length - i - 1,
|
"rindex0": length - i - 1,
|
||||||
"length": length,
|
"length": length,
|
||||||
|
".cycles": cycleMap,
|
||||||
})
|
})
|
||||||
err := ctx.RenderChildren(w)
|
err := ctx.RenderChildren(w)
|
||||||
switch {
|
switch {
|
||||||
|
@ -55,7 +55,11 @@ var loopTests = []struct{ in, expected string }{
|
|||||||
{`{% for a in array %}{% if a == 'second' %}{% break %}{% endif %}{{ a }}{% endfor %}`, "first"},
|
{`{% for a in array %}{% if a == 'second' %}{% break %}{% endif %}{{ a }}{% endfor %}`, "first"},
|
||||||
{`{% for a in array %}{% if a == 'second' %}{% continue %}{% endif %}{{ a }}.{% endfor %}`, "first.third."},
|
{`{% for a in array %}{% if a == 'second' %}{% continue %}{% endif %}{{ a }}.{% endfor %}`, "first.third."},
|
||||||
|
|
||||||
|
// hash
|
||||||
{`{% for a in hash %}{{ a }}{% endfor %}`, "a"},
|
{`{% for a in hash %}{{ a }}{% endfor %}`, "a"},
|
||||||
|
|
||||||
|
// cycle
|
||||||
|
{`{% for a in array %}{% cycle 'even', 'odd' %}.{% endfor %}`, "even.odd.even."},
|
||||||
}
|
}
|
||||||
|
|
||||||
var loopErrorTests = []struct{ in, expected string }{
|
var loopErrorTests = []struct{ in, expected string }{
|
||||||
|
@ -19,6 +19,7 @@ func AddStandardTags(c render.Config) {
|
|||||||
// but it ignores any syntax specified here.
|
// but it ignores any syntax specified here.
|
||||||
c.AddTag("break", breakTag)
|
c.AddTag("break", breakTag)
|
||||||
c.AddTag("continue", continueTag)
|
c.AddTag("continue", continueTag)
|
||||||
|
c.AddTag("cycle", cycleTag)
|
||||||
c.AddBlock("capture").Compiler(captureTagParser)
|
c.AddBlock("capture").Compiler(captureTagParser)
|
||||||
c.AddBlock("case").Clause("when").Clause("else").Compiler(caseTagParser)
|
c.AddBlock("case").Clause("when").Clause("else").Compiler(caseTagParser)
|
||||||
c.AddBlock("comment")
|
c.AddBlock("comment")
|
||||||
|
Loading…
Reference in New Issue
Block a user