// 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 } } }
// 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 }
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 } } }
// 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 }
// 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 }
// 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 }
func asExpr(s string) ast.Expr { expr, err := parser.ParseExpr(s) if err != nil { panic(err) } return expr }
// 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 }
func expr(s string) ast.Expr { x, err := parser.ParseExpr(s) if err != nil { panic("parsing " + s + ": " + err.Error()) } return x }
// 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) }
// 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 }
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) } } } } }
// 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) }
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("--------------") } }
func parse(x string) ast.Expr { expr, err := parser.ParseExpr(x) if err != nil { panic(err) } return expr }
func (p *predicateParser) Parse(in string) (interface{}, error) { expr, err := parser.ParseExpr(in) if err != nil { return nil, err } return p.parseNode(expr) }
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) } } }
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) } } }
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) } }
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") } }
// 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 }
// 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) }
// 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 }
// 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) }
// 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 } }
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 }
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 }
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() }
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 }
// 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 }