首页 > 解决方案 > golang 中的问题 yacc:语法错误:意外 $end

问题描述

亲切的问候。

我在 golang 中学习 yacc 并创建了这个文件:

%{

package main

import (
    "fmt"
)

%}

%union{
    ex string
}

%token <ex> DB OTHER_DB

%% 
query:  other
        |
        db
        ;

db:     DB
        {
            fmt.Printf("\tDB: %s\n", $1 )
        }
        ;

other:  OTHER_DB
        {
            fmt.Printf("\tOTHER_DB: %s\n", $1 )
        }
        ;
%% 

type mlex struct {
    expr   string
    result int
}

func (f *mlex) Lex(lval *yySymType) int {
    yyErrorVerbose = true
    return 0
}

func (f *mlex) Error(s string) {
    fmt.Printf("syntax error: %s\n", s)
}

func Parse(expr string) int {
    m := &mlex{expr, 0}
    yyParse(m)
    return m.result
}

但是在执行它时我得到这个错误:

语法错误:语法错误:意外 $end,期待 DB 或 OTHER_DB

我一直在用这段代码测试这个 yacc 文件:

package main

import (
    "fmt"
)

func main() {

    res := Parse("db")
    fmt.Println(res)
}

会是什么呢 ?我还需要 yacc 文件中的其他内容吗?

我正在尝试制作一个非常简单、功能齐全的示例来很好地理解它。

谢谢你的时间。

标签: gocompiler-constructionyacclex

解决方案


当您的解析器需要知道下一个输入符号(“令牌”)是什么时,它会调用yyLexer'Lex方法。您的实现不会尝试读取令牌。相反,它只返回 0:

func (f *mlex) Lex(lval *yySymType) int {
    yyErrorVerbose = true
    return 0
}

因此,从解析器的角度来看,它被赋予了一个空输入流,而不管您实际提供了什么输入。然后它会尝试解析这个空输入,但您的语法不允许这样做。唯一有效的输入以标记DB或开头OTHER_DB,并且它看不到这些东西中的任何一个。

所以它会产生错误消息,详细说明它的问题是什么。(解析器用内部伪令牌表示输入的结束$end,以防让您感到困惑。)


推荐阅读