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

62 lines
1.2 KiB
Plaintext
Raw Normal View History

2017-06-25 22:21:31 +02:00
%{
package main
import (
_ "fmt"
2017-06-26 04:59:33 +02:00
"reflect"
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-26 13:50:53 +02:00
%type <f> expr expr2
%token <val> LITERAL
%token <name> IDENTIFIER RELATION
2017-06-26 13:50:53 +02:00
%left '.'
2017-06-25 22:21:31 +02:00
%%
2017-06-26 13:50:53 +02:00
start: expr ';' { yylex.(*lexer).val = $1 };
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 } }
| IDENTIFIER { name := $1; $$ = func(ctx Context) interface{} { return ctx.Variables[name] } }
| expr '.' IDENTIFIER {
e, attr := $1, $3
2017-06-26 04:59:33 +02:00
$$ = func(ctx Context) interface{} {
input := e(ctx)
ref := reflect.ValueOf(input)
switch ref.Kind() {
case reflect.Map:
2017-06-26 13:50:53 +02:00
return ref.MapIndex(reflect.ValueOf(attr)).Interface()
2017-06-26 04:59:33 +02:00
default:
2017-06-26 13:50:53 +02:00
return nil
}
}
}
| expr '[' expr2 ']' {
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()
}
}
return nil
case reflect.Map:
return ref.MapIndex(reflect.ValueOf(index)).Interface()
default:
return nil
2017-06-26 04:59:33 +02:00
}
}
}
;
2017-06-26 13:50:53 +02:00
expr2: expr