解析Golang变量

时间:2018-10-25 16:53:09

标签: parsing go abstract-syntax-tree

我正在尝试静态分析Go文件。为此,我需要解析以下格式的变量:

$ sudo rm /usr/local/bin/docker-credential-osxkeychain 

我需要找到所有使用点符号访问的变量。例如,我需要知道shape变量具有color属性。并且还需要该颜色变量具有红色属性。 我试图使用go / ast和go / parser程序包,但找不到解决方法。

如果它是诸如shape.color()之类的方法,那么就不应该将其计算在内

3 个答案:

答案 0 :(得分:1)

您似乎正在尝试创建自己的AST,因为您提供的表达式的右侧似乎不是变量,否则我将其假定为结构。但是,这也没有意义,因为将名为red的字段放在名为color的结构中实际上是不合逻辑的。似乎您正在尝试访问包中的变量,但这也不起作用,因为首字母小写表示该实体未导出。

抛开所有这些,我写了一些代码片段来遵守您列出的条件。

  • shape变量具有color属性。
  • 颜色变量具有红色属性。

https://play.golang.org/p/gIpctQ1XSgT,我仅将其改编成一行,并在不满足简短条件时惊慌失措。随时根据需要进行调整。

package main

import (
    "go/ast"
    "go/format"
    "go/parser"
    "go/token"
    "os"
)

func main() {
    expr, err := parser.ParseExpr("shape.color==color.red")
    if err != nil {
        panic(err)
    }

    // Checking if the expression was binary.
    bExpr, ok := expr.(*ast.BinaryExpr)
    if !ok {
        panic("expr is not a binary expr.")
    }

    // If the operation is not “==”, die.
    if bExpr.Op != token.EQL {
        panic("the op should have been ==.")
    }

    // Left must be a selector expr, meaning followed with a selector which is “dot” in this case.
    left, ok := bExpr.X.(*ast.SelectorExpr)
    if !ok {
        panic("left should have been a selector expr.")
    }

    // Same as above.
    right, ok := bExpr.Y.(*ast.SelectorExpr)
    if !ok {
        panic("right should have been a selector expr.")
    }

    // Checking for attributes.
    if left.Sel.Name != "color" {
        panic("left should have had a color attr.")
    }

    // Same as above.
    if right.Sel.Name != "red" {
        panic("right should have had a red attr.")
    }

    // Then we finally gofmt the code and print it to stdout.
    if err := format.Node(os.Stdout, token.NewFileSet(), expr); err != nil {
        panic(err)
    }
}

答案 1 :(得分:1)

啊!以下代码显示所有使用点符号访问的变量!

// No modifiable code
namespace my
{
    template<class T> void swap(T a, T b) { /*.. */ }
    struct Obj { /*..*/ };
}

// Your code:
namespace my
{
    void swap(Obj& lhs, Obj& rhs)
    {
        // my::swap<Obj&>(lhs, rhs);
        std::swap(lhs, rhs);
    }
}

// In namespace you want.
void doSortStuff()
{
    std::vector<my::Obj> arr;
    std::sort(arr.begin(), arr.end());
}

答案 2 :(得分:0)

如果要比较两个事先不知道的go变量,则需要使用反射。这将使您能够反思地比较两个字段:

type color struct {
    Red string
}

type shape struct {
    Color string
}

func main() {
    color := color{Red: "red"}
    shape := shape{Color: "red"}

    colorVal := reflect.ValueOf(color)
    shapeVal := reflect.ValueOf(shape)

    colorRedField := colorVal.FieldByName("Red")
    shapeColorField := shapeVal.FieldByName("Color")

    fmt.Println(colorRedField)
    fmt.Println(shapeColorField)
    fmt.Println(colorRedField.Interface() == shapeColorField.Interface())
}

https://play.golang.org/p/gvTJYwStP1O