func (e *eval) shouldAdd(name string) bool {
	return e.o.shouldAdd != nil && e.o.shouldAdd(name)
}
shouldAdd retruns true if the command given by name should be recursed into.
package main
import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
	"go/constant"
	"go/token"
	"go/types"
	"github.com/kythe/llvmbzlgen/cmakelib/ast"
	"github.com/kythe/llvmbzlgen/cmakelib/bindings"
	bzlpath "github.com/kythe/llvmbzlgen/path"
	"github.com/kythe/llvmbzlgen/writer"
)
type blockCounter struct {
	begin string  
	end   string  
	count int
}
func newCounter(begin string) *blockCounter {
	return &blockCounter{begin, "end" + begin, 0}
}
func (bc *blockCounter) Count(text string) bool {
	matched := true
	if text == bc.begin {
		bc.count += 1
	} else if text == bc.end {
		bc.count -= 1
	} else {
		matched = false
	}
	return matched || bc.count > 0
}
type eval struct {
	p *ast.Parser
	o options
	w    *writer.StarlarkWriter
	v    *bindings.Mapping
	root bzlpath.Path
	path bzlpath.Path
}
type options struct {
	macroName   string
	shouldPrint func(string) bool
	shouldAdd   func(string) bool
	excludePath func(string) bool
}
type Option func(*eval)
func PrintCommands(p func(string) bool) Option {
	return func(e *eval) { e.o.shouldPrint = p }
}
func RecurseCommands(p func(string) bool) Option {
	return func(e *eval) { e.o.shouldAdd = p }
}
func ExcludePaths(p func(string) bool) Option {
	return func(e *eval) { e.o.excludePath = p }
}
func DefineVars(vars map[string]string) Option {
	return func(e *eval) {
		for k, v := range vars {
			e.v.Set(k, v)
		}
	}
}
func Matching(pat string) func(string) bool {
	return regexp.MustCompile(pat).MatchString
}
func NewEvaluator(w io.Writer, opts ...Option) *eval {
	e := &eval{
		p: ast.NewParser(),
		w: writer.NewStarlarkWriter(w),
		v: bindings.New(),
		o: options{
			macroName: "generated_cmake_targets",
			shouldAdd: func(n string) bool { return n == "add_subdirectory" },
		},
	}
	for _, o := range opts {
		o(e)
	}
	e.v.Set("CMAKE_BINARY_DIR", e.ProjectRoot())
	e.v.Set("CMAKE_SOURCE_DIR", e.ProjectRoot())
	return e
}
func (e *eval) parse(input io.Reader) (*ast.CMakeFile, error) {
	return e.p.Parse(input)
}
func (e *eval) parseFile(path string) (*ast.CMakeFile, error) {
	input, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer input.Close()
	return e.parse(input)
}
func (e *eval) walk(paths []bzlpath.Path) error {
	if err := e.w.BeginMacro(e.o.macroName); err != nil {
		return err
	}
	root, paths := bzlpath.SplitCommonRoot(paths)
	e.root = root
	for _, p := range paths {
		if err := e.AddSubdirectory(p.String()); err != nil {
			return err
		}
	}
	return e.w.EndMacro()
}
type dispatchFunc func(*commandList) (dispatchFunc, error)
type commandList []ast.CommandInvocation
func (l *commandList) Advance() bool {
	if len(*l) > 0 {
		*l = (*l)[1:]
		return len(*l) > 0
	}
	return false
}
func (l *commandList) Head() *ast.CommandInvocation {
	if len(*l) > 0 {
		return &(*l)[0]
	}
	return nil
}
func (e *eval) shouldPrint(name string) bool {
	return e.o.shouldPrint != nil && e.o.shouldPrint(name)
}