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  }