golang 分词恐慌,带有“恐慌:意外标记 XXX”

时间:2021-04-16 02:14:39

标签: go parsing lexer

我正在学习 participle,一个基于 golang 的解析器。看完教程后,我决定创建一个简单的数组解析器,这是我的构造。

首先,我需要一个 AST 来表示这个数组。为了简单起见,我只解析没有引号的字符串数组。 ({value1, value_two, value_3_here},例如)

type SimpleArray struct {
    Arr []Values `"{" @@* "}"`
}

type Values struct {
    Str string `@Ident`
}

现在我为输入字符串创建一个词法分析器

var Lexer = stateful.MustSimple([]stateful.Rule{
    {`Ident`, `[a-zA-Z][a-zA-Z_\d]*`, nil},
    {`punct`, `[}{,]`, nil},
    {`whitespace`, `\s+`, nil},
})

下面有我的主要功能,有一个简单的测试用例 s := "{key, value}"

func main() {
    var parser = participle.MustBuild(&SimpleArray{},
        participle.Lexer(Lexer),
    )
    b := &SimpleArray{}
    s := "{key, value}"
    err := parser.ParseString("", s, b)
    if err != nil {panic(err)}
    repr.Println(b, repr.Indent("  "), repr.OmitEmpty(true))
}

但我很恐慌。

panic: 1:2: unexpected token "key"

我认为 @Ident 结构中的 Values 会捕获“键”,但它不是,为什么?我该如何解决这个问题?

谢谢!

1 个答案:

答案 0 :(得分:2)

我发现有两个问题,第一个是规则定义语法错误,第二个是规则本身的错误。

解析器无法解析任何内容,因为解析器仍需要获取 { 标记来开始第一个规则 SimpleArray。词法分析器没有传递第一个 { 标记的原因是规则的名称 punct 应该大写 Punct。小写规则中的标记(如 whitespace)由词法分析器读取,但不会传递给解析器。

此外,还有一个问题就是不让你解析逗号。您需要修改规则以允许包含分隔逗号的其他项目。

更改以下内容:

type SimpleArray struct {
    Arr []Values `"{" @@* "}"`
}

到:

type SimpleArray struct {
    Arr []Values `"{" (@@ ("," @@)*)? "}"`
}

新规则的解释:

  • "{" 解析 {
  • (...)? 使列表成为可选(如果这是您真正想要的,如果不删除此部分)
  • @@ ("," @@)* 递归解析一个或多个项目,以逗号分隔
  • "}" 解析 }