1
0
mirror of https://github.com/danog/liquid.git synced 2025-01-22 23:11:25 +01:00

Functional is constructed within parser, not scanner

This commit is contained in:
Oliver Steele 2017-06-25 20:47:31 -04:00
parent 6af4fca71b
commit c02fbd57ac
6 changed files with 57 additions and 40 deletions

View File

@ -33,8 +33,8 @@ type ASTControlTag struct {
branches []*ASTControlTag
}
func (n ASTSeq) String() string {
b, err := yaml.Marshal(n)
func MustYAML(val interface{}) string {
b, err := yaml.Marshal(val)
if err != nil {
panic(err)
}

View File

@ -2,6 +2,7 @@ package main
import (
"bytes"
"fmt"
"testing"
"github.com/stretchr/testify/require"
@ -13,16 +14,18 @@ func TestChunkParser(t *testing.T) {
},
}
for _, test := range chunkTests {
tokens := ScanChunks(test.in, "")
// fmt.Println(tokens)
ast, err := Parse(tokens)
require.NoError(t, err, test.in)
// fmt.Println("%#v", ast)
buf := new(bytes.Buffer)
err = ast.Render(buf, ctx)
require.NoError(t, err, test.in)
require.Equal(t, test.expected, buf.String(), test.in)
for i, test := range chunkTests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
tokens := ScanChunks(test.in, "")
// fmt.Println(tokens)
ast, err := Parse(tokens)
require.NoErrorf(t, err, test.in)
// fmt.Println(MustYAML(ast))
buf := new(bytes.Buffer)
err = ast.Render(buf, ctx)
require.NoErrorf(t, err, test.in)
require.Equalf(t, test.expected, buf.String(), test.in)
})
}
}

View File

@ -6,12 +6,15 @@ import (
%}
%union {
name string
val func(Context) interface{}
val interface{}
f func(Context) interface{}
}
%type <val> expr
%token <val> LITERAL IDENTIFIER
%token <name> RELATION
%type <f> expr
%token <val> LITERAL
%token <name> IDENTIFIER RELATION
%%
top: expr { yylex.(*lexer).val = $1 };
expr: LITERAL | IDENTIFIER;
expr:
LITERAL { $$ = func(_ Context) interface{} { return $1 } }
| IDENTIFIER { $$ = func(ctx Context) interface{} { return ctx.Variables[$1] } }

View File

@ -263,18 +263,18 @@ _eof_trans:
//line scanner.rl:36
lex.act = 2;
case 4:
//line scanner.rl:56
//line scanner.rl:55
lex.act = 4;
case 5:
//line scanner.rl:41
lex.act = 5;
case 6:
//line scanner.rl:56
//line scanner.rl:55
lex.te = ( lex.p)+1
{ tok = RELATION; out.name = string(lex.data[lex.ts:lex.te]); ( lex.p)++; goto _out
}
case 7:
//line scanner.rl:47
//line scanner.rl:46
lex.te = ( lex.p)
( lex.p)--
{
@ -283,12 +283,12 @@ _eof_trans:
if err != nil {
panic(err)
}
out.val = func(_ Context) interface{} { return n }
out.val = n
( lex.p)++; goto _out
}
case 8:
//line scanner.rl:56
//line scanner.rl:55
lex.te = ( lex.p)
( lex.p)--
{ tok = RELATION; out.name = string(lex.data[lex.ts:lex.te]); ( lex.p)++; goto _out
@ -299,13 +299,12 @@ _eof_trans:
( lex.p)--
{
tok = IDENTIFIER
name := string(lex.data[lex.ts:lex.te])
out.val = func(ctx Context) interface{} { return ctx.Variables[name] }
out.name = string(lex.data[lex.ts:lex.te])
( lex.p)++; goto _out
}
case 10:
//line scanner.rl:67
//line scanner.rl:66
lex.te = ( lex.p)
( lex.p)--
@ -316,8 +315,9 @@ _eof_trans:
{( lex.p) = ( lex.te) - 1
tok = LITERAL
val := string(lex.data[lex.ts:lex.te]) == "true"
out.val = func(_ Context) interface{} { return val }
out.val = string(lex.data[lex.ts:lex.te]) == "true"
( lex.p)++; goto _out
}
case 4:
{( lex.p) = ( lex.te) - 1
@ -327,14 +327,13 @@ _eof_trans:
{( lex.p) = ( lex.te) - 1
tok = IDENTIFIER
name := string(lex.data[lex.ts:lex.te])
out.val = func(ctx Context) interface{} { return ctx.Variables[name] }
out.name = string(lex.data[lex.ts:lex.te])
( lex.p)++; goto _out
}
}
//line scanner.go:338
//line scanner.go:337
}
}
@ -348,7 +347,7 @@ _again:
//line NONE:1
lex.ts = 0
//line scanner.go:352
//line scanner.go:351
}
}
@ -370,7 +369,7 @@ _again:
_out: {}
}
//line scanner.rl:71
//line scanner.rl:70
return tok

View File

@ -35,13 +35,12 @@ func (lex *lexer) Lex(out *yySymType) int {
%%{
action Bool {
tok = LITERAL
val := string(lex.data[lex.ts:lex.te]) == "true"
out.val = func(_ Context) interface{} { return val }
out.val = string(lex.data[lex.ts:lex.te]) == "true"
fbreak;
}
action Ident {
tok = IDENTIFIER
name := string(lex.data[lex.ts:lex.te])
out.val = func(ctx Context) interface{} { return ctx.Variables[name] }
out.name = string(lex.data[lex.ts:lex.te])
fbreak;
}
action Number {
@ -50,7 +49,7 @@ func (lex *lexer) Lex(out *yySymType) int {
if err != nil {
panic(err)
}
out.val = func(_ Context) interface{} { return n }
out.val = n
fbreak;
}
action Relation { tok = RELATION; out.name = string(lex.data[lex.ts:lex.te]); fbreak; }

19
y.go
View File

@ -12,7 +12,8 @@ import (
type yySymType struct {
yys int
name string
val func(Context) interface{}
val interface{}
f func(Context) interface{}
}
const LITERAL = 57346
@ -423,9 +424,21 @@ yydefault:
case 1:
yyDollar = yyS[yypt-1 : yypt+1]
//line expression_parser.y:15
//line expression_parser.y:16
{
yylex.(*lexer).val = yyDollar[1].val
yylex.(*lexer).val = yyDollar[1].f
}
case 2:
yyDollar = yyS[yypt-1 : yypt+1]
//line expression_parser.y:19
{
yyVAL.f = func(_ Context) interface{} { return yyDollar[1].val }
}
case 3:
yyDollar = yyS[yypt-1 : yypt+1]
//line expression_parser.y:20
{
yyVAL.f = func(ctx Context) interface{} { return ctx.Variables[yyDollar[1].name] }
}
}
goto yystack /* stack new state and value */