github.com/lab47/exprcore@v0.0.0-20210525052339-fb7d6bd9331e/syntax/walk_test.go (about) 1 package syntax_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "reflect" 8 "strings" 9 "testing" 10 11 "github.com/lab47/exprcore/syntax" 12 ) 13 14 func TestWalk(t *testing.T) { 15 const src = ` 16 for x in y { 17 if x { 18 pass 19 } else { 20 f([2*x for x in "abc"]) 21 } 22 } 23 ` 24 // TODO(adonovan): test that it finds all syntax.Nodes 25 // (compare against a reflect-based implementation). 26 // TODO(adonovan): test that the result of f is used to prune 27 // the descent. 28 f, err := syntax.Parse("hello.go", src, 0) 29 if err != nil { 30 t.Fatal(err) 31 } 32 33 var buf bytes.Buffer 34 var depth int 35 syntax.Walk(f, func(n syntax.Node) bool { 36 if n == nil { 37 depth-- 38 return true 39 } 40 fmt.Fprintf(&buf, "%s%s\n", 41 strings.Repeat(" ", depth), 42 strings.TrimPrefix(reflect.TypeOf(n).String(), "*syntax.")) 43 depth++ 44 return true 45 }) 46 got := buf.String() 47 want := ` 48 File 49 ForStmt 50 Ident 51 Ident 52 IfStmt 53 Ident 54 BranchStmt 55 ExprStmt 56 CallExpr 57 Ident 58 Comprehension 59 BinaryExpr 60 Literal 61 Ident 62 ForClause 63 Ident 64 Literal` 65 got = strings.TrimSpace(got) 66 want = strings.TrimSpace(want) 67 if got != want { 68 t.Errorf("got %s, want %s", got, want) 69 } 70 } 71 72 // ExampleWalk demonstrates the use of Walk to 73 // enumerate the identifiers in a exprcore source file 74 // containing a nonsense program with varied grammar. 75 func ExampleWalk() { 76 const src = ` 77 load("library", "a") 78 79 def b(c, *, d=e) { 80 f += %{g: h} 81 i = -(j) 82 return k.l[m + n] 83 } 84 85 for o in [p for q, r in s if t] { 86 u(lambda: v, w[x:y:z]) 87 } 88 ` 89 f, err := syntax.Parse("hello.star", src, 0) 90 if err != nil { 91 log.Fatal(err) 92 } 93 94 var idents []string 95 syntax.Walk(f, func(n syntax.Node) bool { 96 if id, ok := n.(*syntax.Ident); ok { 97 idents = append(idents, id.Name) 98 } 99 return true 100 }) 101 fmt.Println(strings.Join(idents, " ")) 102 103 // The identifer 'a' appears in both LoadStmt.From[0] and LoadStmt.To[0]. 104 105 // Output: 106 // 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 107 }