c++ - Bison C++ 中间规则值因变体而丢失

标签 c++ parsing bison variant

我将 Bison 与 lalr1.cc 一起使用生成 C++ 解析器和 api.value.type variant 的框架.我尝试使用中间规则操作返回将在进一步语义操作中使用的值,但堆栈上的值似乎变为零。下面是一个例子。

解析器.y:

%require "3.0"
%skeleton "lalr1.cc"
%defines
%define api.value.type variant

%code {
#include <iostream>
#include "parser.yy.hpp"
extern int yylex(yy::parser::semantic_type * yylval);
}

%token <int> NUM

%%
expr: NUM | expr { $<int>$ = 42; } '+' NUM { std::cout << $<int>2 << std::endl; };

%%

void yy::parser::error(const std::string & message){
    std::cerr << message << std::endl;
}

int main(){
    yy::parser p;
    return p.parse();
}

词法分析器.flex:

%option noyywrap
%option nounput
%option noinput

%{
#include "parser.yy.hpp"
typedef yy::parser::token token;
#define YY_DECL int yylex(yy::parser::semantic_type * yylval)
%}

%%
[ \n\t]+
[0-9]+      {
                yylval->build(atoi(yytext));
                return token::NUM;
            }
.           {
                return yytext[0];
            }

编译:

bison -o parser.yy.cpp parser.y
flex -o lexer.c lexer.flex
g++ parser.yy.cpp lexer.c -O2 -Wall -o parser

2+2 这样的简单输入应该打印值 42而是出现 0 .当变量类型更改为 %union 时, 打印的值是应该的。作为解决方法,我一直在使用标记操作 $<type>-n从堆栈中获取更深层次的值(value),但这种方法会降低易读性和可维护性。

我在生成的源代码中读到,当使用变体类型时,默认操作 { $$ = $1 }没有被执行。它是这种行为的一个例子还是一个错误?

最佳答案

我投票给“错误”。它与缺少默认操作无关。

我跟踪执行直到它试图将 MRA 的值压入堆栈。但是,它没有获得 MRA 的正确类型,结果是对 yypush_ 的调用什么都不做,这显然不是所需的操作。

如果我是你,我会报告问题。

关于c++ - Bison C++ 中间规则值因变体而丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44811550/

相关文章:

c# - P/调用 C# 到 C++

parsing - Chomsky 1 型解析器生成器可能吗?

c - 解析 - 导致移位/归约冲突的运算符

c++ - 使用 Bison 构建 AST

c++ - 独立、操作系统无关、架构中立、多线程库

c++ - Boost Asio udp 解析器返回错误的端点迭代器

C++ 自定义惰性迭代器

调车场算法能否解析POSIX正则表达式?

parsing - 如果从文件中读取,Parsec 将失败且没有错误

c - 在 bison/yacc 中处理变量名列表