92 lines
2.1 KiB
Go
92 lines
2.1 KiB
Go
package schema
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
"unsafe"
|
|
|
|
gv "github.com/dominikbraun/graph"
|
|
"github.com/dominikbraun/graph/draw"
|
|
)
|
|
|
|
func TestParse(t *testing.T) {
|
|
in := "()" +
|
|
"(test)" +
|
|
"(test a)" +
|
|
"(test a b)" +
|
|
"(test a b c)" +
|
|
"(test (a b c))" +
|
|
"(test (a b c d))" +
|
|
"(\"hello world\")" +
|
|
"(concat \"hello\" \"world\")" +
|
|
"(+ 1 2)"
|
|
want := "( <nil> <nil>)\n" +
|
|
"(test <nil> <nil>)\n" +
|
|
"(test [n'a'] <nil>)\n" +
|
|
"(test [n'a'] [n'b'])\n" +
|
|
"(. [n'test'] (. [n'a'] (. [n'b'] [n'c'])))\n" +
|
|
"(test (a [n'b'] [n'c']) <nil>)\n" +
|
|
"(test (. [n'a'] (. [n'b'] (. [n'c'] [n'd']))) <nil>)\n" +
|
|
"[l'hello world']\n" +
|
|
"(concat [l'hello'] [l'world'])\n" +
|
|
"(+ [l1] [l2])\n"
|
|
tokens, err := Tokenize([]byte(in))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
parse, err := Parse(tokens)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
test := strings.Builder{}
|
|
for _, line := range parse {
|
|
test.Write([]byte(fmt.Sprintf("%s\n", line)))
|
|
}
|
|
if test.String() != want {
|
|
t.Errorf("\ngot:\n%s\nwant:\n%s", test.String(), want)
|
|
}
|
|
if os.Getenv("AZALEA_TEST_VISUALIZE") == "1" {
|
|
Visualize(parse)
|
|
}
|
|
}
|
|
func hash(n *Node) uintptr {
|
|
return uintptr(unsafe.Pointer(n))
|
|
}
|
|
func Visualize(nodes []*Node) {
|
|
g := gv.New(hash, gv.Tree(), gv.Directed())
|
|
for _, node := range nodes {
|
|
addNode(node, g)
|
|
}
|
|
dot, _ := os.CreateTemp("", "azalea-graph-*.gv")
|
|
_ = draw.DOT(g, dot)
|
|
_ = exec.Command("dot", "-Tsvg", "-O", dot.Name()).Run()
|
|
_ = exec.Command("qimgv", dot.Name()+".svg").Run()
|
|
_ = os.Remove(dot.Name())
|
|
_ = os.Remove(dot.Name() + ".svg")
|
|
}
|
|
func addNode(node *Node, g gv.Graph[uintptr, *Node]) *Node {
|
|
str := ""
|
|
if node.Function != "" {
|
|
str = node.Function
|
|
} else {
|
|
if node.Token != nil {
|
|
str = node.Token.String()
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
_ = g.AddVertex(node, gv.VertexAttribute("label", str))
|
|
if node.Left != nil {
|
|
left := addNode(node.Left, g)
|
|
_ = g.AddEdge(hash(node), hash(left), gv.EdgeAttribute("splines", "line"))
|
|
}
|
|
if node.Right != nil {
|
|
right := addNode(node.Right, g)
|
|
_ = g.AddEdge(hash(node), hash(right), gv.EdgeAttribute("splines", "line"))
|
|
}
|
|
return node
|
|
}
|