You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
1.9 KiB
104 lines
1.9 KiB
4 months ago
|
package syntax_test
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
|
||
|
"go.starlark.net/syntax"
|
||
|
)
|
||
|
|
||
|
func TestWalk(t *testing.T) {
|
||
|
const src = `
|
||
|
for x in y:
|
||
|
if x:
|
||
|
pass
|
||
|
else:
|
||
|
f([2*x for x in "abc"])
|
||
|
`
|
||
|
// TODO(adonovan): test that it finds all syntax.Nodes
|
||
|
// (compare against a reflect-based implementation).
|
||
|
// TODO(adonovan): test that the result of f is used to prune
|
||
|
// the descent.
|
||
|
f, err := syntax.Parse("hello.go", src, 0)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
var buf bytes.Buffer
|
||
|
var depth int
|
||
|
syntax.Walk(f, func(n syntax.Node) bool {
|
||
|
if n == nil {
|
||
|
depth--
|
||
|
return true
|
||
|
}
|
||
|
fmt.Fprintf(&buf, "%s%s\n",
|
||
|
strings.Repeat(" ", depth),
|
||
|
strings.TrimPrefix(reflect.TypeOf(n).String(), "*syntax."))
|
||
|
depth++
|
||
|
return true
|
||
|
})
|
||
|
got := buf.String()
|
||
|
want := `
|
||
|
File
|
||
|
ForStmt
|
||
|
Ident
|
||
|
Ident
|
||
|
IfStmt
|
||
|
Ident
|
||
|
BranchStmt
|
||
|
ExprStmt
|
||
|
CallExpr
|
||
|
Ident
|
||
|
Comprehension
|
||
|
BinaryExpr
|
||
|
Literal
|
||
|
Ident
|
||
|
ForClause
|
||
|
Ident
|
||
|
Literal`
|
||
|
got = strings.TrimSpace(got)
|
||
|
want = strings.TrimSpace(want)
|
||
|
if got != want {
|
||
|
t.Errorf("got %s, want %s", got, want)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ExampleWalk demonstrates the use of Walk to
|
||
|
// enumerate the identifiers in a Starlark source file
|
||
|
// containing a nonsense program with varied grammar.
|
||
|
func ExampleWalk() {
|
||
|
const src = `
|
||
|
load("library", "a")
|
||
|
|
||
|
def b(c, *, d=e):
|
||
|
f += {g: h}
|
||
|
i = -(j)
|
||
|
return k.l[m + n]
|
||
|
|
||
|
for o in [p for q, r in s if t]:
|
||
|
u(lambda: v, w[x:y:z])
|
||
|
`
|
||
|
f, err := syntax.Parse("hello.star", src, 0)
|
||
|
if err != nil {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
|
||
|
var idents []string
|
||
|
syntax.Walk(f, func(n syntax.Node) bool {
|
||
|
if id, ok := n.(*syntax.Ident); ok {
|
||
|
idents = append(idents, id.Name)
|
||
|
}
|
||
|
return true
|
||
|
})
|
||
|
fmt.Println(strings.Join(idents, " "))
|
||
|
|
||
|
// The identifer 'a' appears in both LoadStmt.From[0] and LoadStmt.To[0].
|
||
|
|
||
|
// Output:
|
||
|
// a a b c d e f g h i j k l m n o p q r s t u v w x y z
|
||
|
}
|