【发布时间】:2017-06-28 20:00:02
【问题描述】:
我正在使用 Bison 和 lalr1.cc 骨架来生成 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 的标记操作来从堆栈中获取更深层次的值,但这种方法会降低易读性和可维护性。
我在生成的源代码中读到,当使用变体类型时,默认操作{ $$ = $1 } 不会执行。这是这种行为的一个例子还是一个错误?
【问题讨论】: