1
0
mirror of https://github.com/danog/liquid.git synced 2024-11-27 13:24:40 +01:00
liquid/expressions/expressions.y

104 lines
2.1 KiB
Plaintext
Raw Normal View History

2017-06-25 22:21:31 +02:00
%{
2017-06-26 15:33:07 +02:00
package expressions
2017-06-25 22:21:31 +02:00
import (
"fmt"
2017-06-26 04:59:33 +02:00
"reflect"
2017-06-25 22:21:31 +02:00
)
func init() {
_ = fmt.Sprint("")
}
2017-06-25 22:21:31 +02:00
%}
%union {
name string
val interface{}
f func(Context) interface{}
2017-06-25 22:21:31 +02:00
}
2017-06-27 03:32:08 +02:00
%type <f> expr rel expr1
%token <val> LITERAL
2017-06-27 03:32:08 +02:00
%token <name> IDENTIFIER KEYWORD RELATION
2017-06-26 21:36:05 +02:00
%token ASSIGN
2017-06-26 15:06:55 +02:00
%token EQ
2017-06-27 03:32:08 +02:00
%left '.' '|'
2017-06-26 15:06:55 +02:00
%left '<' '>'
2017-06-25 22:21:31 +02:00
%%
2017-06-26 21:36:05 +02:00
start:
rel ';' { yylex.(*lexer).val = $1 }
2017-06-27 03:32:08 +02:00
| ASSIGN IDENTIFIER '=' expr1 ';' {
2017-06-26 21:36:05 +02:00
name, expr := $2, $4
yylex.(*lexer).val = func(ctx Context) interface{} {
ctx.Set(name, expr(ctx))
return nil
}
};
2017-06-25 22:21:31 +02:00
expr:
2017-06-26 13:50:53 +02:00
LITERAL { val := $1; $$ = func(_ Context) interface{} { return val } }
2017-06-26 21:36:05 +02:00
| IDENTIFIER { name := $1; $$ = func(ctx Context) interface{} { return ctx.Get(name) } }
2017-06-26 13:50:53 +02:00
| expr '.' IDENTIFIER {
e, attr := $1, $3
2017-06-26 04:59:33 +02:00
$$ = func(ctx Context) interface{} {
obj := e(ctx)
ref := reflect.ValueOf(obj)
2017-06-26 04:59:33 +02:00
switch ref.Kind() {
case reflect.Map:
val := ref.MapIndex(reflect.ValueOf(attr))
if val.Kind()!= reflect.Invalid {
return val.Interface()
}
2017-06-26 13:50:53 +02:00
}
return nil
2017-06-26 13:50:53 +02:00
}
}
| expr '[' expr ']' {
2017-06-26 13:50:53 +02:00
e, i := $1, $3
$$ = func(ctx Context) interface{} {
ref := reflect.ValueOf(e(ctx))
index := reflect.ValueOf(i(ctx))
switch ref.Kind() {
case reflect.Array, reflect.Slice:
switch index.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n := int(index.Int())
if 0 <= n && n < ref.Len() {
return ref.Index(n).Interface()
}
}
2017-06-26 04:59:33 +02:00
}
return nil
2017-06-26 04:59:33 +02:00
}
}
2017-06-27 03:32:08 +02:00
expr1:
expr
| expr1 '|' IDENTIFIER { $$ = makeFilter($1, $3, nil) }
| expr1 '|' KEYWORD expr { $$ = makeFilter($1, $3, $4) }
2017-06-26 04:59:33 +02:00
;
2017-06-26 13:50:53 +02:00
2017-06-26 15:06:55 +02:00
rel:
2017-06-27 03:32:08 +02:00
expr1
2017-06-26 15:06:55 +02:00
| expr EQ expr {
a, b := $1, $3
$$ = func(ctx Context) interface{} {
aref, bref := reflect.ValueOf(a(ctx)), reflect.ValueOf(b(ctx))
return GenericCompare(aref, bref) == 0
}
}
| expr '<' expr {
a, b := $1, $3
$$ = func(ctx Context) interface{} {
aref, bref := reflect.ValueOf(a(ctx)), reflect.ValueOf(b(ctx))
return GenericCompare(aref, bref) < 0
}
}
| expr '>' expr {
a, b := $1, $3
$$ = func(ctx Context) interface{} {
aref, bref := reflect.ValueOf(a(ctx)), reflect.ValueOf(b(ctx))
return GenericCompare(aref, bref) > 0
}
}
;