func TestWalk(t *testing.T) { g := ast.Grammar([]*ast.Production{ { Name: &ast.Name{Name: "E"}, Expr: ast.Alternative([]ast.Expression{ ast.Sequence([]ast.Expression{ &ast.Name{Name: "T"}, &ast.Terminal{Terminal: "+"}, &ast.Name{Name: "T"}, }), &ast.Name{Name: "T"}, &ast.Epsilon{Epsilon: "e"}, }), }, { Name: &ast.Name{Name: "T"}, Expr: ast.Alternative([]ast.Expression{ ast.Sequence([]ast.Expression{ &ast.Terminal{Terminal: "("}, &ast.Name{Name: "T"}, &ast.Terminal{Terminal: ")"}, }), &ast.Name{Name: "T"}, }), }, }) order := []string{ "ast.Grammar", "*ast.Production", "*ast.Name", "ast.Alternative", "ast.Sequence", "*ast.Name", "*ast.Terminal", "*ast.Name", "*ast.Name", "*ast.Epsilon", "*ast.Production", "*ast.Name", "ast.Alternative", "ast.Sequence", "*ast.Terminal", "*ast.Name", "*ast.Terminal", "*ast.Name", } i := 0 ast.Walk(func(n ast.Node) bool { if n == nil { return false } if typ := reflect.TypeOf(n).String(); order[i] != typ { t.Errorf("got %q want %q", typ, order[i]) } i++ return true }, g) }
// check checks whether all productions // used are defined. func (p *parser) check() { prods := make(map[string]bool) for _, p := range p.grammar { prods[p.Name.Name] = true } ast.Walk(func(n ast.Node) bool { if n, ok := n.(*ast.Name); ok { if _, ok := prods[n.Name]; !ok { p.errs = append(p.errs, fmt.Errorf("%v undefined %q", n.Pos(), n.Name)) } } return true }, p.grammar) }