ginger/gg/decoder_test.go

366 lines
7.0 KiB
Go
Raw Normal View History

package gg
import (
"bytes"
"strconv"
"testing"
2023-10-28 07:53:37 +00:00
. "code.betamike.com/mediocregopher/ginger/gg/grammar"
"code.betamike.com/mediocregopher/ginger/graph"
"github.com/stretchr/testify/assert"
)
func TestDecoder(t *testing.T) {
type test struct {
in string
exp Located[Value]
expErr string
}
runTests := func(
t *testing.T, name string, sym Symbol[Located[Value]], tests []test,
) {
t.Run(name, func(t *testing.T) {
for i, test := range tests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
r := NewReader(bytes.NewBufferString(test.in))
got, err := sym.Decode(r)
if test.expErr != "" {
assert.Error(t, err)
assert.Equal(t, test.expErr, err.Error())
} else if assert.NoError(t, err) {
assert.True(t,
test.exp.Value.Equal(got.Value),
"\nexp:%v\ngot:%v", test.exp, got,
)
assert.Equal(t, test.exp.Location, got.Location)
}
})
}
})
}
expNum := func(row, col int, n int64) Located[Value] {
2023-10-29 09:20:37 +00:00
return Locate(Location{Row: row, Col: col}, Number(n))
}
runTests(t, "number", number, []test{
{in: `0`, exp: expNum(1, 1, 0)},
{in: `100`, exp: expNum(1, 1, 100)},
{in: `-100`, exp: expNum(1, 1, -100)},
{in: `0foo`, exp: expNum(1, 1, 0)},
{in: `100foo`, exp: expNum(1, 1, 100)},
})
expName := func(row, col int, name string) Located[Value] {
2023-10-29 09:20:37 +00:00
return Locate(Location{Row: row, Col: col}, Name(name))
}
expGraph := func(row, col int, g *Graph) Located[Value] {
2023-10-29 09:20:37 +00:00
return Locate(Location{Row: row, Col: col}, Value{Graph: g})
}
runTests(t, "name", name, []test{
{in: `a`, exp: expName(1, 1, "a")},
{in: `ab`, exp: expName(1, 1, "ab")},
{in: `ab2c`, exp: expName(1, 1, "ab2c")},
{in: `ab2c,`, exp: expName(1, 1, "ab2c")},
2023-10-29 20:42:41 +00:00
{in: `!ab2c,`, exp: expName(1, 1, "!ab2c")},
})
runTests(t, "graph", graphSym, []test{
{in: `{}`, exp: expGraph(1, 1, new(Graph))},
{in: `{`, expErr: `1:2: expected '}' or name`},
{in: `{a}`, expErr: `1:3: expected '='`},
{in: `{a=}`, expErr: `1:4: expected name or number or graph or tuple`},
{
in: `{foo=a}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(Name("foo"), graph.ValueOut(None, Name("a"))),
),
},
{
in: `{ foo = a }`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(Name("foo"), graph.ValueOut(None, Name("a"))),
),
},
{in: `{1=a}`, expErr: `1:2: expected '}' or name`},
{in: `{foo=a ,}`, expErr: `1:8: expected '}' or ';' or '<'`},
{in: `{foo=a`, expErr: `1:7: expected '}' or ';' or '<'`},
{
in: `{foo=a<b}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.ValueOut(Some(Name("a")), Name("b")),
),
),
},
{
in: `{foo=a< b <c}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.TupleOut(
Some(Name("a")),
graph.ValueOut(
Some(Name("b")),
Name("c"),
),
),
),
),
},
{
in: `{foo =a<b<c<1 }`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.TupleOut(
Some(Name("a")),
graph.TupleOut(
Some(Name("b")),
graph.ValueOut(
Some(Name("c")),
Number(1),
),
),
),
),
),
},
{
in: `{foo=a<b ; }`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.ValueOut(
Some(Name("a")),
Name("b"),
),
),
),
},
{
in: `{foo=a<b;bar=c}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.ValueOut(
Some(Name("a")),
Name("b"),
),
).
AddValueIn(
Name("bar"),
graph.ValueOut(None, Name("c")),
),
),
},
{
in: `{foo= a<{ baz=1 } ; bar=c}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.ValueOut(
Some(Name("a")),
Value{Graph: new(Graph).AddValueIn(
Name("baz"),
graph.ValueOut(None, Number(1)),
)},
),
).
AddValueIn(
Name("bar"),
graph.ValueOut(None, Name("c")),
),
),
},
{
in: `{foo= {baz=1} <a; bar=c}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.ValueOut(
Some(Value{Graph: new(Graph).AddValueIn(
Name("baz"),
graph.ValueOut(None, Number(1)),
)}),
Name("a"),
),
).
AddValueIn(
Name("bar"),
graph.ValueOut(None, Name("c")),
),
),
},
})
runTests(t, "tuple", graphSym, []test{
{
in: `{foo=(a)}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.ValueOut(None, Name("a")),
),
),
},
{
in: `{foo=(a<b)}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.ValueOut(
Some(Name("a")),
Name("b"),
),
),
),
},
{
in: `{foo=a<(b)}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.ValueOut(
Some(Name("a")),
Name("b"),
),
),
),
},
{
in: `{foo=a<(b,c)}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.TupleOut(
Some(Name("a")),
graph.ValueOut(None, Name("b")),
graph.ValueOut(None, Name("c")),
),
),
),
},
{
in: `{foo=a<(b<c)}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.TupleOut(
Some(Name("a")),
graph.TupleOut(
Some(Name("b")),
graph.ValueOut(None, Name("c")),
),
),
),
),
},
{
in: `{foo=a<(b<(c))}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.TupleOut(
Some(Name("a")),
graph.TupleOut(
Some(Name("b")),
graph.ValueOut(None, Name("c")),
),
),
),
),
},
{
in: `{foo=a<(b<(c,d<1))}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.TupleOut(
Some(Name("a")),
graph.TupleOut(
Some(Name("b")),
graph.ValueOut(None, Name("c")),
graph.ValueOut(
Some(Name("d")),
Number(1),
),
),
),
),
),
},
{
in: `{foo=a<(b<( ( (c) ) ))}`,
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.TupleOut(
Some(Name("a")),
graph.TupleOut(
Some(Name("b")),
graph.ValueOut(None, Name("c")),
),
),
),
),
},
})
runTests(t, "comment", graphSym, []test{
{
in: "*\n{}",
exp: expGraph(2, 1, new(Graph)),
},
{
in: "* ignore me!\n{}",
exp: expGraph(2, 1, new(Graph)),
},
{
in: "{* ignore me!\n}",
exp: expGraph(1, 1, new(Graph)),
},
{
in: "{foo* ignore me!\n = a}",
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.ValueOut(None, Name("a")),
),
),
},
{
in: "{foo = a* ignore me!\n}",
exp: expGraph(
1, 1, new(Graph).
AddValueIn(
Name("foo"),
graph.ValueOut(None, Name("a")),
),
),
},
})
}