我正在尝试使用golang's yacc tool创建解析器。我找到nex来简化创建词法分析器以给出解析器。我现在的问题是生成的解析器没有方法或字段来授予我访问解析结果的权限。我可以将解析结果存储在全局变量中,但这似乎是错误的。
目前我已将以下内容添加为我的parser.y文件顶部的初始尝试:
type ResultParser interface {
yyParser // Generated parser interface
Result() s.Expr // s.Expr is an interface for the parsed result
}
func (p *yyParserImpl) Result() s.Expr {
return p.stack[1].expr
}
func NewResultParser() ResultParser {
return &yyParserImpl{}
}
是否有推荐/更好的方式从解析器获取结果?
(因为这感觉有点滥用发电机......)
答案 0 :(得分:5)
不,访问stack[1]
无效。一旦堆栈需要增长到超过16的初始大小,它就不包含任何结果。 (见#16163。)
if
标签之后的yystack
语句会创建一个新堆栈并完全忘记yyParserImpl
中保存的那个。
我做了以下事情。
在词法分析器类型中添加result
字段:
type ShellLexer struct {
/* … */
result *ShellProgram
}
在一开始就通过以下规则扩展语法:
start : program {
shyylex.(*ShellLexer).result = $$
}
(这取决于Parse
方法的参数名称(可以有自定义前缀),但我认为没问题。)
答案 1 :(得分:1)
替代解决方案:使用sed将其他字段插入生成的解析器中。然后,在语法操作中,指定值。
go tool yacc -o parser.go -p Filter parser.y
sed -i '/type FilterParserImpl struct/a tree *treeNode' parser.go
生成的解析器:
type FilterParserImpl struct {
tree *treeNode
lval FilterSymType
stack [FilterInitialStackSize]FilterSymType
char int
}
语法动作:
filter { Filterrcvr.tree = $1 }