【问题标题】:Using variant in Bison and Flex在 Bison 和 Flex 中使用变体
【发布时间】:2019-10-26 09:20:27
【问题描述】:

我一直在将解析器从 c 重写为 c++,因此我正在尝试在我的代码中使用变体。但是,我不确定如何将它与 flex 集成,并且我不断收到深奥的错误消息。

我的野牛文件看起来像

%require "3"
%language "c++"

%{
    // declarations
%}

%define api.value.type {std::variant<double, std::string>}

%token COMMENT
%token <double> DOUBLE
%token <std::string> STRING

// grammar

我的词法分析器看起来像

%{
#include "y.tab.h"
%}
%option noyywrap

ID [a-zA-Z][a-zA-Z0-9_]*


%%
[ \t\n ]+ ;

\-?[0-9]+ |
\-?[0-9]+\. |
\-?[0-9]+\.[0-9]+ |
\-?\.[0-9]+ { yylval.emplace<double>(std::atof(yytext)); return DOUBLE;}
// other tokens
zA-Z][\.a-zA-Z0-9_]* { yylval.emplace<std::string>(yytext); return STRING;}
%%

我不确定我是否使用了 yylval,我正在尝试访问变体,就像使用 %union 一样。

我收到以下错误:

y.tab.h:125:18: error: ‘variant’ in namespace ‘std’ does not name a template type
     typedef std::variant<double, std::string> semantic_type;
                  ^~~~~~~
y.tab.h:197:27: error: ‘semantic_type’ does not name a type
                     const semantic_type& v);
                           ^~~~~~~~~~~~~
y.tab.h:212:7: error: ‘semantic_type’ does not name a type
       semantic_type value;
       ^~~~~~~~~~~~~
my_mdl.l: In function ‘int yylex()’:
my_mdl.l:16:3: error: ‘yylval’ was not declared in this scope
 \-?\.[0-9]+ { yylval.emplace<double>(std::atof(yytext)); return DOUBLE;}
   ^~~~~~
my_mdl.l:16:3: note: suggested alternative: ‘yylex’
 \-?\.[0-9]+ { yylval.emplace<double>(std::atof(yytext)); return DOUBLE;}
   ^~~~~~
   yylex
my_mdl.l:16:18: error: expected primary-expression before ‘double’
 \-?\.[0-9]+ { yylval.emplace<double>(std::atof(yytext)); return DOUBLE;}
                  ^~~~~~
my_mdl.l:16:53: error: ‘DOUBLE’ was not declared in this scope
 \-?\.[0-9]+ { yylval.emplace<double>(std::atof(yytext)); return DOUBLE;}
                                                     ^~~~~~
my_mdl.l:18:10: error: ‘COMMENT’ was not declared in this scope
 "//".* { return COMMENT;}
          ^~~~~~~
my_mdl.l:37:29: error: expected primary-expression before ‘>’ token
 [a-zA-Z][\.a-zA-Z0-9_]* { yylval.emplace<std::string>(yytext); return STRING;}
                             ^
my_mdl.l:37:47: error: ‘STRING’ was not declared in this scope
 [a-zA-Z][\.a-zA-Z0-9_]* { yylval.emplace<std::string>(yytext); return STRING;}
                                               ^~~~~~

我的.y 文件也有几百行错误,例如

my_mdl.y:88:79: error: no matching function for call to ‘MOVE::MOVE(<brace-enclosed initializer list>)’
     p.add_command(Command{in_place_index<5>, MOVE( {{$2, $3, $4}}, $5)});
                                                                               ^
In file included from parsing/symt.h:7:0,
                 from my_mdl.y:10:
parsing/cmd.h:44:5: note: candidate: MOVE::MOVE(const Scalable<double, 3>&, const string&)
     MOVE(const Scalable<double, 3> &params, const std::string &scaleFactorName);
     ^~~~

MOVE 是一个结构体,定义为

struct MOVE {
    MOVE(const Scalable<double, 3> &params, const std::string &scaleFactorName);

    Scalable<double, 3> params; // todo equationify
    std::string scale_factor_name;
};

它是变体中的一种类型 (std::variant&lt;MOVE, etc...&gt; Command)。奇怪的是,如果我写,这在我的代码中正常工作 p.add_command(Command{in_place_index&lt;5&gt;, MOVE{{{x, y, z}}, "asdfads"}});

【问题讨论】:

标签: c++ c++17 bison lex variant


【解决方案1】:

您的程序包含的内容不够多,无法提供准确的答案。请参阅有关准备 [mcse] 的 SO 帮助页面。但是您似乎很可能会收到错误

y.tab.h:125:18: error: ‘variant’ in namespace ‘std’ does not name a template type

因为你还没有安排#include &lt;variant&gt; 在你的弹性文件中。

typedef 本身来自 bison 生成的头文件中的生成代码,但 bison 无法猜测它可能需要什么 #include 指令,因此由您来插入它们。您必须确保在 #include 野牛生成的标头之前定义了语义类型所需的所有类型。您可以在 flex 文件的序言块中插入适当的 #include 指令,或者您可以在野牛文件中使用 %code requires 块。 (由于您使用的是 bison 3,因此后者可能是最好的解决方案。)

我不知道您的野牛文件中的错误中的SAVE 是什么意思。我假设它是您拥有(或未定义)的宏,因此错误将是宏扩展的结果。

【讨论】:

  • 定义变体有效!我将更新有关 SAVE 错误的问题详细信息
  • @Simon:我很确定 bison 会插入一个 case 操作来将变体类型转换为每个语法符号的特定类型。这适用于工会,但不适用于std::variant。老实说,我不知道你会如何解决这个问题,但如果我有什么事情发生,我会留下一个便条。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
  • 1970-01-01
  • 1970-01-01
  • 2011-08-17
相关资源
最近更新 更多