2023-10-21 15:42:31 +00:00
|
|
|
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"
|
2023-10-21 15:42:31 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
2023-10-27 14:14:37 +00:00
|
|
|
func TestDecoder(t *testing.T) {
|
2023-10-21 15:42:31 +00:00
|
|
|
type test struct {
|
2023-10-27 14:14:37 +00:00
|
|
|
in string
|
|
|
|
exp Located[Value]
|
|
|
|
expErr string
|
2023-10-21 15:42:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
runTests := func(
|
2023-10-27 14:14:37 +00:00
|
|
|
t *testing.T, name string, sym Symbol[Located[Value]], tests []test,
|
2023-10-21 15:42:31 +00:00
|
|
|
) {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
for i, test := range tests {
|
|
|
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
2023-10-27 14:14:37 +00:00
|
|
|
r := NewReader(bytes.NewBufferString(test.in))
|
|
|
|
got, err := sym.Decode(r)
|
2023-10-21 15:42:31 +00:00
|
|
|
if test.expErr != "" {
|
|
|
|
assert.Error(t, err)
|
|
|
|
assert.Equal(t, test.expErr, err.Error())
|
|
|
|
} else if assert.NoError(t, err) {
|
|
|
|
assert.True(t,
|
2023-10-27 14:14:37 +00:00
|
|
|
test.exp.Value.Equal(got.Value),
|
2023-10-21 15:42:31 +00:00
|
|
|
"\nexp:%v\ngot:%v", test.exp, got,
|
|
|
|
)
|
2023-10-27 14:14:37 +00:00
|
|
|
assert.Equal(t, test.exp.Location, got.Location)
|
2023-10-21 15:42:31 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-10-27 14:14:37 +00:00
|
|
|
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))
|
2023-10-21 15:42:31 +00:00
|
|
|
}
|
|
|
|
|
2023-10-27 14:14:37 +00:00
|
|
|
runTests(t, "number", number, []test{
|
2023-10-21 15:42:31 +00:00
|
|
|
{in: `0`, exp: expNum(1, 1, 0)},
|
|
|
|
{in: `100`, exp: expNum(1, 1, 100)},
|
|
|
|
{in: `-100`, exp: expNum(1, 1, -100)},
|
2023-10-27 14:14:37 +00:00
|
|
|
{in: `0foo`, exp: expNum(1, 1, 0)},
|
|
|
|
{in: `100foo`, exp: expNum(1, 1, 100)},
|
2023-10-21 15:42:31 +00:00
|
|
|
})
|
|
|
|
|
2023-10-27 14:14:37 +00:00
|
|
|
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))
|
2023-10-21 15:42:31 +00:00
|
|
|
}
|
|
|
|
|
2023-10-27 14:14:37 +00:00
|
|
|
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})
|
2023-10-21 15:42:31 +00:00
|
|
|
}
|
|
|
|
|
2023-10-27 14:14:37 +00:00
|
|
|
runTests(t, "name", name, []test{
|
2023-10-21 15:42:31 +00:00
|
|
|
{in: `a`, exp: expName(1, 1, "a")},
|
|
|
|
{in: `ab`, exp: expName(1, 1, "ab")},
|
|
|
|
{in: `ab2c`, exp: expName(1, 1, "ab2c")},
|
2023-10-27 14:14:37 +00:00
|
|
|
{in: `ab2c,`, exp: expName(1, 1, "ab2c")},
|
2023-10-29 20:42:41 +00:00
|
|
|
{in: `!ab2c,`, exp: expName(1, 1, "!ab2c")},
|
2023-10-21 15:42:31 +00:00
|
|
|
})
|
|
|
|
|
2023-10-27 14:14:37 +00:00
|
|
|
runTests(t, "graph", graphSym, []test{
|
2023-10-21 15:42:31 +00:00
|
|
|
{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).
|
2023-10-27 14:14:37 +00:00
|
|
|
AddValueIn(Name("foo"), graph.ValueOut(None, Name("a"))),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{ foo = a }`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
2023-10-27 14:14:37 +00:00
|
|
|
AddValueIn(Name("foo"), graph.ValueOut(None, Name("a"))),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
},
|
|
|
|
{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(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
|
|
|
graph.ValueOut(Some(Name("a")), Name("b")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo=a< b <c}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.ValueOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("b")),
|
|
|
|
Name("c"),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo =a<b<c<1 }`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("b")),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.ValueOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("c")),
|
|
|
|
Number(1),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo=a<b ; }`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.ValueOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
|
|
|
Name("b"),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo=a<b;bar=c}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.ValueOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
|
|
|
Name("b"),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("bar"),
|
|
|
|
graph.ValueOut(None, Name("c")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo= a<{ baz=1 } ; bar=c}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.ValueOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
|
|
|
Value{Graph: new(Graph).AddValueIn(
|
|
|
|
Name("baz"),
|
|
|
|
graph.ValueOut(None, Number(1)),
|
|
|
|
)},
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("bar"),
|
|
|
|
graph.ValueOut(None, Name("c")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo= {baz=1} <a; bar=c}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.ValueOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Value{Graph: new(Graph).AddValueIn(
|
|
|
|
Name("baz"),
|
|
|
|
graph.ValueOut(None, Number(1)),
|
|
|
|
)}),
|
|
|
|
Name("a"),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("bar"),
|
|
|
|
graph.ValueOut(None, Name("c")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2023-10-27 14:14:37 +00:00
|
|
|
runTests(t, "tuple", graphSym, []test{
|
2023-10-21 15:42:31 +00:00
|
|
|
{
|
|
|
|
in: `{foo=(a)}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
|
|
|
graph.ValueOut(None, Name("a")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo=(a<b)}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.ValueOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
|
|
|
Name("b"),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo=a<(b)}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.ValueOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
|
|
|
Name("b"),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo=a<(b,c)}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
|
|
|
graph.ValueOut(None, Name("b")),
|
|
|
|
graph.ValueOut(None, Name("c")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo=a<(b<c)}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("b")),
|
|
|
|
graph.ValueOut(None, Name("c")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo=a<(b<(c))}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("b")),
|
|
|
|
graph.ValueOut(None, Name("c")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo=a<(b<(c,d<1))}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("b")),
|
|
|
|
graph.ValueOut(None, Name("c")),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.ValueOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("d")),
|
|
|
|
Number(1),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: `{foo=a<(b<( ( (c) ) ))}`,
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("a")),
|
2023-10-21 15:42:31 +00:00
|
|
|
graph.TupleOut(
|
2023-10-27 14:14:37 +00:00
|
|
|
Some(Name("b")),
|
|
|
|
graph.ValueOut(None, Name("c")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2023-10-27 14:14:37 +00:00
|
|
|
runTests(t, "comment", graphSym, []test{
|
2023-10-21 15:42:31 +00:00
|
|
|
{
|
|
|
|
in: "*\n{}",
|
2023-10-27 14:14:37 +00:00
|
|
|
exp: expGraph(2, 1, new(Graph)),
|
2023-10-21 15:42:31 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
in: "* ignore me!\n{}",
|
2023-10-27 14:14:37 +00:00
|
|
|
exp: expGraph(2, 1, new(Graph)),
|
2023-10-21 15:42:31 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
in: "{* ignore me!\n}",
|
|
|
|
exp: expGraph(1, 1, new(Graph)),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: "{foo* ignore me!\n = a}",
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
|
|
|
graph.ValueOut(None, Name("a")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
in: "{foo = a* ignore me!\n}",
|
|
|
|
exp: expGraph(
|
|
|
|
1, 1, new(Graph).
|
|
|
|
AddValueIn(
|
2023-10-27 14:14:37 +00:00
|
|
|
Name("foo"),
|
|
|
|
graph.ValueOut(None, Name("a")),
|
2023-10-21 15:42:31 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|