Bison C ++中规则值随变体而丢失

问题描述 投票:1回答:2

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

parser.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();
}

lexer.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的标记操作来从堆栈中获取更深层的值,但这种方法可能会降低易读性和可维护性。

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

c++ parsing bison variant
2个回答
1
投票

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

我追踪执行到它试图将MRA的值推入堆栈的程度。但是,它没有为MRA获得正确的类型,结果是对yypush_的调用什么都不做,这显然不是理想的操作。

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


0
投票

这确实是Bison 3.0.5中的一个错误,但使用$<foo>1本质上也是错误的(但没有其他选择!)。

考虑:

// 1.y
%nterm <int> exp
%%
exp: { $<int>$ = 42; }    { $$ = $<int>1; }

它被翻译成如下:

// 2.y
%nterm <int> exp
%%
@1: %empty { $<int>$ = 42; }
exp: @1    { $$ = $<int>1; }

这里有什么问题,我们没有告诉Bison @1的语义值是什么类型,因此它无法正确处理这个语义值(通常,不会应用%printer%destructor)。更糟糕的是:在这里,因为它不知道这里实际存储了什么值,它无法正确操作它:它不知道如何将它从局部变量$$复制到堆栈,这就是值丢失的原因。 (在C中,语义值的位是盲目复制的,因此它可以工作。在C ++中使用Bison变体,我们使用与当前类型相对应的精确赋值/复制运算符,这需要知道类型是什么。)

显然,更好的翻译应该是:

// 3.y
%nterm <int> exp @1
%%
@1: %empty { $$ = 42; }
exp: @1    { $$ = $1; }

这实际上是任何人都会写的。

感谢您的问题,Bison 3.1现在以typed midrule actions为特色:

// 4.y
%nterm <int> exp
%%
exp: <int>{ $$ = 42; }    { $$ = $1; }

Desugared,4.y的生成与3.y完全相同。

有关详细信息,请参阅http://lists.gnu.org/archive/html/bug-bison/2017-06/msg00000.htmlhttp://lists.gnu.org/archive/html/bug-bison/2018-06/msg00001.html

© www.soinside.com 2019 - 2024. All rights reserved.