예제 #1
0
// A convenience function for parsing a Stmt by wrapping it in a func literal
func ParseStmt(stmt string) (ast.Stmt, error) {
	// parser.ParseExpr has some quirks, for example it won't parse unused map literals as
	// ExprStmts. Unused map literals are technically illegal, but it would be
	// nice to check them at a later stage. Therefore, we want to parse expressions
	// as expressions, and stmts and stmts. We try both.
	// However, there is a bug in parser.ParseExpr that it does not detect excess input.
	// Therefore, the _ of _ = 1 will be parsed as an expression. To avoid this, attempt
	// to parse the input as a statement first, and fall back to an expression
	expr := "func(){" + stmt + ";}"
	if e, err := parser.ParseExpr(expr); err != nil {
		if e, err := parser.ParseExpr(stmt); err == nil {
			return &ast.ExprStmt{X: e}, nil
		}
		errs := err.(scanner.ErrorList)
		for i := range errs {
			errs[i].Pos.Offset -= 7
			errs[i].Pos.Column -= 7
		}
		return nil, errs
	} else {
		node := e.(*ast.FuncLit).Body.List[0]
		if stmt, ok := node.(Stmt); !ok {
			return nil, fmt.Errorf("%T not supported", node)
		} else {
			return stmt, nil
		}
	}
}
예제 #2
0
파일: goinline.go 프로젝트: charl/go-inline
// Inline replaces each instance of identifier k with v.Ident in ast.File f,
// for k, v := range m.
// For all inlines that were triggeres it also adds imports from v.Imports to f.
// In addition, it removes top level type declarations of the form
// type k ...
// for all k in m.
//
// Every k in m should be a valid identifier.
// Every v.Ident should be a valid expression.
func Inline(fset *token.FileSet, f *ast.File, m map[string]Target) error {
	// Build the inline map.
	im := map[string]reflect.Value{}
	for k, v := range m {
		expr, err := parser.ParseExpr(k)
		if err != nil {
			return fmt.Errorf("failed to parse `%s`: %s", k, err)
		}
		if _, ok := expr.(*ast.Ident); !ok {
			return fmt.Errorf("expected identifier, got %s which is %T", k, expr)
		}
		expr, err = parser.ParseExpr(v.Ident)
		if err != nil {
			return fmt.Errorf("failed to parse `%s`: %s", v.Ident, err)
		}
		s := v.Ident
		if _, ok := expr.(*ast.StarExpr); ok {
			s = fmt.Sprintf("(%s)", s)
		}
		im[k] = reflect.ValueOf(ast.Ident{Name: s})
	}
	// Filter `type XXX ...` declarations out if we are inlining XXX.
	cmap := ast.NewCommentMap(fset, f, f.Comments)
	to := 0
	for _, d := range f.Decls {
		skip := false
		if t, ok := d.(*ast.GenDecl); ok {
			for _, s := range t.Specs {
				ts, ok := s.(*ast.TypeSpec)
				if !ok {
					continue
				}
				if _, ok = im[ts.Name.String()]; ok {
					skip = true
				}
			}
		}
		if !skip {
			f.Decls[to] = d
			to++
		}
	}
	if to != len(f.Decls) {
		f.Decls = f.Decls[:to]
		// Remove comments for the declarations that were filtered out.
		f.Comments = cmap.Filter(f).Comments()
	}
	// Add imports for the inlines that were triggered.
	for k := range inline(im, f) {
		for _, imp := range m[k].Imports {
			astutil.AddImport(fset, f, imp)
		}
	}
	return nil
}
예제 #3
0
파일: parz.go 프로젝트: rtfb/sketchbook
func compareTwoTrees(src string) {
	v1 := &channelPusher{}
	v1.fileSet = token.NewFileSet()
	v1.queue = make(chan *ast.Node)

	v2 := &channelPusher{}
	v2.fileSet = token.NewFileSet()
	v2.queue = make(chan *ast.Node)

	tree1, err := parser.ParseExpr(src)
	if err != nil {
		panic(err)
	}

	src2 := "x + 2*y"
	tree2, err := parser.ParseExpr(src2)
	if err != nil {
		panic(err)
	}
	done := make(chan struct{})
	defer close(done)

	go func() {
		ast.Walk(v1, tree1)
		close(v1.queue)
		done <- struct{}{}
	}()
	go func() {
		ast.Walk(v2, tree2)
		close(v2.queue)
		done <- struct{}{}
	}()

	var n1, n2 *ast.Node
	quit := false
	for !quit {
		select {
		case n1 = <-v1.queue:
		case n2 = <-v2.queue:
		case <-done:
			quit = true
		}
		if n1 != nil && n2 != nil {
			if !equalNodes(n1, n2) {
				println("!equalNodes")
				break
			}
			println("equalNodes")
			n1 = nil
			n2 = nil
		}
	}
}
예제 #4
0
// parseExpr returns an ast expression from the source s
// stolen from http://golang.org/src/cmd/fix/fix.go
func parseExpr(s string) ast.Expr {
	exp, err := parser.ParseExpr(s)
	if err != nil {
		log.Println("Cannot parse expression %s :%s", s, err.Error())
	}
	return exp
}
예제 #5
0
파일: compile.go 프로젝트: callistoaz/3
// compiles source consisting of a number of statements. E.g.:
// 	src = "a = 1; b = sin(x)"
// 	code, err := world.Compile(src)
// 	code.Eval()
func (w *World) Compile(src string) (code *BlockStmt, e error) {
	// parse
	exprSrc := "func(){\n" + src + "\n}" // wrap in func to turn into expression
	tree, err := parser.ParseExpr(exprSrc)
	if err != nil {
		return nil, fmt.Errorf("script line %v: ", err)
	}

	// catch compile errors and decode line number
	if !Debug {
		defer func() {
			err := recover()
			if err == nil {
				return
			}
			if compErr, ok := err.(*compileErr); ok {
				code = nil
				e = fmt.Errorf("script %v: %v", pos2line(compErr.pos, exprSrc), compErr.msg)
			} else {
				panic(err)
			}
		}()
	}

	// compile
	stmts := tree.(*ast.FuncLit).Body.List // strip func again
	if Debug {
		ast.Print(nil, stmts)
	}
	block := new(BlockStmt)
	for _, s := range stmts {
		block.append(w.compile(s), s)
	}
	return block, nil
}
예제 #6
0
파일: compile.go 프로젝트: callistoaz/3
// Compiles an expression, which can then be evaluated. E.g.:
// 	expr, err := world.CompileExpr("1+1")
// 	expr.Eval()   // returns 2
func (w *World) CompileExpr(src string) (code Expr, e error) {
	// parse
	tree, err := parser.ParseExpr(src)
	if err != nil {
		return nil, fmt.Errorf(`parse "%s": %v`, src, err)
	}
	if Debug {
		ast.Print(nil, tree)
	}

	// catch compile errors
	if !Debug {
		defer func() {
			err := recover()
			if err == nil {
				return
			}
			if er, ok := err.(*compileErr); ok {
				code = nil
				e = fmt.Errorf(`parse "%s": %v`, src, er)
			} else {
				panic(err)
			}
		}()
	}
	return w.compile(tree), nil
}
예제 #7
0
파일: bolt.go 프로젝트: tav/bolt
func asExpr(s string) ast.Expr {
	expr, err := parser.ParseExpr(s)
	if err != nil {
		panic(err)
	}
	return expr
}
예제 #8
0
// Parse the arguments string Template(A, B, C)
func parseTemplateAndArgs(s string) (name string, args []string) {
	expr, err := parser.ParseExpr(s)
	if err != nil {
		fatalf("Failed to parse %q: %v", s, err)
	}
	debugf("expr = %#v\n", expr)
	callExpr, ok := expr.(*ast.CallExpr)
	if !ok {
		fatalf("Failed to parse %q: expecting Identifier(...)", s)
	}
	debugf("fun = %#v", callExpr.Fun)
	fn, ok := callExpr.Fun.(*ast.Ident)
	if !ok {
		fatalf("Failed to parse %q: expecting Identifier(...)", s)
	}
	name = fn.Name
	for i, arg := range callExpr.Args {
		var buf bytes.Buffer
		debugf("arg[%d] = %#v", i, arg)
		format.Node(&buf, token.NewFileSet(), arg)
		s := buf.String()
		debugf("parsed = %q", s)
		args = append(args, s)
	}
	return
}
예제 #9
0
파일: fix.go 프로젝트: krasin/go-deflate
func expr(s string) ast.Expr {
	x, err := parser.ParseExpr(s)
	if err != nil {
		panic("parsing " + s + ": " + err.Error())
	}
	return x
}
예제 #10
0
파일: eval.go 프로젝트: xtaci/goeval
// Eval evaluates a string
func (s *Scope) Eval(str string) (interface{}, error) {
	expr, err := parser.ParseExpr("func(){" + str + "}()")
	if err != nil {
		return nil, err
	}
	return s.Interpret(expr.(*ast.CallExpr).Fun.(*ast.FuncLit).Body)
}
예제 #11
0
// This parses an import statement, such as "./foo/bar(int,baz.T(foo.T))",
// returning a list of types and a list of imports that are needed
// (e.g. baz and foo in the above example).
func parseImport(s string) (types []string) {
	// First, I want to cut off any preliminary directories, so the
	// import should look like a function call.
	n := strings.Index(s, "(")
	if n < 1 {
		return
	}
	start := 0
	for i := n - 1; i >= 0; i-- {
		if s[i] == '/' {
			start = i + 1
			break
		}
	}
	s = s[start:]
	// Now we just need to parse the apparent function call...
	x, _ := parser.ParseExpr(s)
	callexpr, ok := x.(*ast.CallExpr)
	if !ok {
		return
	} // FIXME: need error handling?
	for _, texpr := range callexpr.Args {
		types = append(types, pretty(texpr))
	}
	return types
}
예제 #12
0
파일: whatis.go 프로젝트: raff/go-fish
func WhatisCommand(args []string) {
	line := repl.CmdLine[len(args[0]):len(repl.CmdLine)]
	ctx := &eval.Ctx{line}
	if expr, err := parser.ParseExpr(line); err != nil {
		if pair := eval.FormatErrorPos(line, err.Error()); len(pair) == 2 {
			repl.Msg(pair[0])
			repl.Msg(pair[1])
		}
		repl.Errmsg("parse error: %s\n", err)
	} else {
		cexpr, errs := eval.CheckExpr(ctx, expr, repl.Env)
		if len(errs) != 0 {
			for _, cerr := range errs {
				repl.Msg("%v", cerr)
			}
		} else {
			repl.Section(cexpr.String())
			if cexpr.IsConst() {
				repl.Msg("constant:\t%s", cexpr.Const())
			}
			knownTypes := cexpr.KnownType()
			if len(knownTypes) == 1 {
				repl.Msg("type:\t%s", knownTypes[0])
			} else {
				for i, v := range knownTypes {
					repl.Msg("type[%d]:\t%s", i, v)
				}
			}
		}
	}
}
예제 #13
0
// this function is called when the cursor is at the '.' and you need to get the
// declaration before that dot
func (c *auto_complete_context) deduce_cursor_decl(iter *token_iterator) *decl {
	expr, err := parser.ParseExpr(iter.extract_go_expr())
	if err != nil {
		return nil
	}
	return expr_to_decl(expr, c.current.scope)
}
예제 #14
0
파일: expr.go 프로젝트: rocky/ssa-interp
func main() {
	// src is the input for which we want to inspect the AST.
	exprs := []string{
		"\"quoted\" string with backslash \\",
		"f(3.14)*2 + c",
		"-2  ", // trailing spaces to be devius
		" 5 == 6",
		"5\t< 6", // that's a tab in there
		"1+2",
		"(1+2)*3",
		"1 << n",
		"1 << 8",
		"y(",
	}

	for _, expr := range exprs {
		// Create the AST by parsing expr.
		f, err := parser.ParseExpr(expr)
		if err != nil {
			fmt.Printf("Error parsing %s: %s", expr, err.Error())
			continue
		}

		// Inspect the AST and print all identifiers and literals.
		if v := evalAction(f); v != nil {
			fmt.Printf("Eval: '%s' ok; value: %s\n", expr, v)
		} else {
			fmt.Printf("Eval '%s' no good\n", expr)
		}
		fmt.Println("--------------")
	}
}
예제 #15
0
func parse(x string) ast.Expr {
	expr, err := parser.ParseExpr(x)
	if err != nil {
		panic(err)
	}
	return expr
}
예제 #16
0
파일: parse.go 프로젝트: huhoo/vulcand
func (p *predicateParser) Parse(in string) (interface{}, error) {
	expr, err := parser.ParseExpr(in)
	if err != nil {
		return nil, err
	}
	return p.parseNode(expr)
}
예제 #17
0
func TestTypeExpr(t *testing.T) {
	for typeStr, expected := range TypeExprs {
		// Handle arrays and ... myself, since ParseExpr() does not.
		array := strings.HasPrefix(typeStr, "[]")
		if array {
			typeStr = typeStr[2:]
		}

		ellipsis := strings.HasPrefix(typeStr, "...")
		if ellipsis {
			typeStr = typeStr[3:]
		}

		expr, err := parser.ParseExpr(typeStr)
		if err != nil {
			t.Error("Failed to parse test expr:", typeStr)
			continue
		}

		if array {
			expr = &ast.ArrayType{expr.Pos(), nil, expr}
		}
		if ellipsis {
			expr = &ast.Ellipsis{expr.Pos(), expr}
		}

		actual := NewTypeExpr("pkg", expr)
		if !reflect.DeepEqual(expected, actual) {
			t.Error("Fail, expected", expected, ", was", actual)
		}
	}
}
예제 #18
0
func expectConst(t *testing.T, expr string, env *Env, expected interface{}, expectedType reflect.Type) {
	ctx := &Ctx{expr}
	if e, err := parser.ParseExpr(expr); err != nil {
		t.Fatalf("Failed to parse expression '%s' (%v)", expr, err)
	} else if aexpr, errs := CheckExpr(ctx, e, env); errs != nil {
		t.Fatalf("Failed to check expression '%s' (%v)", expr, errs)
	} else if !aexpr.IsConst() {
		t.Fatalf("Expression '%s' did not yield a const node(%+v)", expr, aexpr)
	} else if expectedNumber, ok := expected.(*ConstNumber); ok {
		if actual, ok2 := aexpr.Const().Interface().(*ConstNumber); !ok2 {
			t.Fatalf("Expression '%s' yielded '%v', expected '%v'", expr, aexpr.Const(), expected)
		} else if !actual.Value.Equals(&expectedNumber.Value) {
			t.Fatalf("Expression '%s' yielded '%v', expected '%v'", expr, actual, expected)
		} else if len(aexpr.KnownType()) == 0 {
			t.Fatalf("Expression '%s' expected to have type '%v'", expr, expectedType)
		} else if actual := aexpr.KnownType()[0]; !typesEqual(expectedType, actual) {
			t.Fatalf("Expression '%s' has type '%v', expected '%v'", expr, actual, expectedType)
		}
	} else {
		if actual := aexpr.Const().Interface(); !reflect.DeepEqual(actual, expected) {
			t.Fatalf("Expression '%s' yielded '%+v', expected '%+v'", expr, actual, expected)
		} else if len(aexpr.KnownType()) == 0 {
			t.Fatalf("Expression '%s' expected to have type '%v'", expr, expectedType)
		} else if actual := aexpr.KnownType()[0]; !typesEqual(expectedType, actual) {
			t.Fatalf("Expression '%s' has type '%v', expected '%v'", expr, t, expectedType)
		}
	}
}
예제 #19
0
func expectCheckError(t *testing.T, expr string, env *Env, errorString ...string) {
	ctx := &Ctx{expr}
	if e, err := parser.ParseExpr(expr); err != nil {
		t.Fatalf("Failed to parse expression '%s' (%v)", expr, err)
	} else if _, errs := CheckExpr(ctx, e, env); errs != nil {
		var i int
		out := "\n"
		ok := true
		for i = 0; i < len(errorString); i += 1 {
			if i >= len(errs) {
				out += fmt.Sprintf("%d. Expected `%v` missing\n", i, errorString[i])
				ok = false
			} else if errorString[i] == errs[i].Error() {
				out += fmt.Sprintf("%d. Expected `%v` == `%v`\n", i, errorString[i], errs[i])
			} else {
				out += fmt.Sprintf("%d. Expected `%v` != `%v`\n", i, errorString[i], errs[i])
				ok = false
			}
		}
		for ; i < len(errs); i += 1 {
			out += fmt.Sprintf("%d. Unexpected `%v`\n", i, errs[i])
			ok = false
		}
		if !ok {
			t.Fatalf("%sWrong check errors for expression '%s'", out, expr)
		}
	} else {
		for i, s := range errorString {
			t.Logf("%d. Expected `%v` missing\n", i, s)
		}
		t.Fatalf("Missing check errors for expression '%s'", expr)
	}
}
예제 #20
0
func TestIsPkgAddressable(t *testing.T) {
	env := MakeSimpleEnv()
	env.Pkgs["a"] = MakeSimpleEnv()
	env.Pkgs["a"].(*SimpleEnv).Vars["v"] = reflect.ValueOf(new(int))
	env.Pkgs["a"].(*SimpleEnv).Funcs["f"] = reflect.ValueOf(func() {})
	v, _ := parser.ParseExpr("a.v")
	vv, _ := CheckExpr(v, env)
	if !isAddressable(vv) {
		t.Fatalf("expected package var 'a.v' to be addressible")
	}

	f, _ := parser.ParseExpr("a.f")
	ff, _ := CheckExpr(f, env)
	if isAddressable(ff) {
		t.Fatalf("expected package func 'a.f' to be unaddressible")
	}
}
예제 #21
0
// parseExpr parses s as an expression.
// It might make sense to expand this to allow statement patterns,
// but there are problems with preserving formatting and also
// with what a wildcard for a statement looks like.
func parseExpr(s string, what string) ast.Expr {
	x, err := parser.ParseExpr("input", s, nil)
	if err != nil {
		fmt.Fprintf(os.Stderr, "parsing %s %s: %s\n", what, s, err)
		os.Exit(2)
	}
	return x
}
예제 #22
0
// parseType parses a Golang type string and returns a reflect.Type.
func parseType(typ string) (reflect.Type, error) {
	expr, err := parser.ParseExpr(typ)
	if err != nil {
		return nil, errors.New("parsing error")
	}

	return typeOfExpr(expr)
}
예제 #23
0
// parseExpr parses s as an expression.
// It might make sense to expand this to allow statement patterns,
// but there are problems with preserving formatting and also
// with what a wildcard for a statement looks like.
func parseExpr(s, what string) ast.Expr {
	x, err := parser.ParseExpr(s)
	if err != nil {
		fmt.Fprintf(os.Stderr, "parsing %s %s at %s\n", what, s, err)
		os.Exit(2)
	}
	return x
}
예제 #24
0
파일: parse.go 프로젝트: irasmaster/vulcan
// Parses expression in the go language into Failover predicates
func ParseExpression(in string) (Predicate, error) {
	expr, err := parser.ParseExpr(in)
	if err != nil {
		return nil, err
	}

	return parseNode(expr)
}
예제 #25
0
// ParseString parses go code into the ast nodes.
func (scope *Scope) ParseString(exprStr string) (ast.Node, int, error) {
	exprStr = strings.Trim(exprStr, " \n\t")
	wrappedExpr := "func(){" + exprStr + "}()"
	shifted := 7
	expr, err := parser.ParseExpr(wrappedExpr)
	if err != nil && strings.HasPrefix(err.Error(), "1:8: expected statement, found '") {
		expr, err = parser.ParseExpr(exprStr)
		shifted = 0
		if err != nil {
			return expr, shifted, err
		}
		return expr.(ast.Node), shifted, nil
	} else if err != nil {
		return expr, shifted, err
	} else {
		return expr.(*ast.CallExpr).Fun.(*ast.FuncLit).Body, shifted, nil
	}
}
예제 #26
0
파일: compiler.go 프로젝트: reqshark/amber
func (c *Compiler) visitRawInterpolation(value string) string {
	value = strings.Replace(value, "$", "__DOLLAR__", -1)
	expr, err := gp.ParseExpr(value)
	if err != nil {
		panic("Unable to parse expression.")
	}
	value = strings.Replace(c.visitExpression(expr), "__DOLLAR__", "$", -1)
	return value
}
예제 #27
0
func (t *TupleMatcher) compile() error {
	ast, err := parser.ParseExpr(t.Expr)
	if err != nil {
		return err
	}
	t.ast = &ast
	t.Index = index(ast, nil)
	return nil
}
예제 #28
0
파일: gonav.go 프로젝트: avisagie/gonav
func Parse(expr string) {
	e, err := parser.ParseExpr(expr)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	printer.Fprint(os.Stdout, token.NewFileSet(), e)
	fmt.Println()
}
예제 #29
0
파일: fix.go 프로젝트: h8liu/golang
func expr(s string) ast.Expr {
	x, err := parser.ParseExpr(s)
	if err != nil {
		panic("parsing " + s + ": " + err.Error())
	}
	// Remove position information to avoid spurious newlines.
	killPos(reflect.ValueOf(x))
	return x
}
예제 #30
0
파일: eval.go 프로젝트: zephyrtronium/expr
// Evaluate an expression in a string.
func EvalString(expr string) (*big.Int, error) {
	tree, err := parser.ParseExpr(expr)
	if err != nil {
		return nil, err
	}
	var z *big.Int
	z, err = Eval(tree)
	return z, err
}