Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Compiler construction Bison使用%define api.pure full,不使用%union,但使用C++;改用变体_Compiler Construction_Bison_Yacc_Bisonc++ - Fatal编程技术网

Compiler construction Bison使用%define api.pure full,不使用%union,但使用C++;改用变体

Compiler construction Bison使用%define api.pure full,不使用%union,但使用C++;改用变体,compiler-construction,bison,yacc,bisonc++,Compiler Construction,Bison,Yacc,Bisonc++,我有一个手写扫描仪和一个bison解析器,可以解析这个句子(是问题上下文的缩写): 野牛: %require "3.2" %define api.pure full %code{ #include <stdio.h> #include <string.h> #include "Scanner.h" #include<iostream> } %code{ int yylex(YYSTYPE *lvalp)

我有一个手写扫描仪和一个bison解析器,可以解析这个句子(是问题上下文的缩写):

野牛:

%require "3.2"
%define api.pure full


%code{
#include <stdio.h>
#include <string.h>
#include "Scanner.h"
#include<iostream>
}



%code{
    int yylex(YYSTYPE *lvalp);
    #include<iostream>
    #include<string>
    Scanner scanner;
    void yyerror(const char *error);
}


%union {
int n;
double d;
char s[1000];
}

%token VAR COL ITYPE
%token IDENTIFIER
%token INTEGER
%token EOL

%type <s> type PrimitiveType IDENTIFIER
%type <s> INTEGER    

%%
program:
| program EOL
| program SimpleDeclaration {  }
;

SimpleDeclaration: VariableDeclaration
;

VariableDeclaration: VAR IDENTIFIER COL type {std::cout<<"defined variable " << $2 << " with type " << $4 << std::endl; }

type: IDENTIFIER
| PrimitiveType
;

PrimitiveType: ITYPE { strcpy($$, "int"); }
;

%%
int main()
{
    scanner.set_file("inp.txt");
    return yyparse();
}

void yyerror(const char *error)
{
    std::cout << "syntax error" << std::endl;
}

int yylex(YYSTYPE *lvalp)
{
    return scanner.get_next_token(lvalp);
}
但是我想使用STL容器和智能指针。在中,如果您的令牌的类型不同,则不会告诉您如何使用无联合的
lvalp*
wi。另外,根据我的代码,请将 %%语言“C++”<代码>除<代码> %外定义Ap.Value.Type变体使用C++类型接受语义类型而不是<代码>联合< /COD>。这会导致以下错误:

parser.ypp:3.1-21:错误:%define变量“api.pure”未使用

<> >我想在返回正确的令牌的同时分配值,而不使用联合,这样我就可以使用所有C++特性。 注意:我看到了,但我仍然无法理解函数
make_Number
是否已经存在或已生成?如何从my next_token()向属于已定义%token的$variables添加值

提前感谢。

#定义api。纯
仅适用于使用C api生成的解析器。如果你要求野牛产生一个C++解析器,你不需要那个声明,因为:

解析器通过调用yylex调用扫描器。与C解析器相反,C++解析器总是纯的:使用<代码> %Apple API没有任何意义。 <>但是C++的API与C API有很大的不同。如果你想使用它们,你真的需要阅读整个手册章节(阅读时参考示例)

请注意,Bison创建的variant类型与
std::variant
非常不同,因此它可能是您想要的,也可能不是您想要的。与
std::variant
不同,Bison的变体不存储变量值的当前类型,因为解析器总是知道堆栈值的类型。在解析时这很好,但它会降低变量作为导出值的用处。(在其他应用程序中也是如此。)但是,如果您想使用像
std::string
这样的非平凡类型,它们可以提供帮助,因为Bison可以确保正确调用析构函数。[注1]

如果您打算使用智能指针,您可能会发现自己正在调用
std::move
,以避免复制不可复制的对象。(在解析过程中,Bison堆栈上的对象经常被重复复制。)您还需要使用
std::move
来避免过度复制字符串。您可以请求Bison在每次访问语义值时自动插入对
std::move
的调用,但如果启用此选项,则需要注意仅使用每个语义值一次。(手册中有一个示例。)

<>你一旦决定使用BySon C++的API,你就需要在词汇扫描器的两个调用约定之间进行选择。一个选项是手动调用的,这只是传统的C方法(修改为使用C纯API):lexer返回一个整数(标记类型),并将语义值放在指向参数的STYPE中。如果STYPE是Bison变体,则需要使用
emplace
方法在适当的位置构造一个值(从而避免复制)

野牛手册的链接页中有一些例子。有两个使用
emplace
的例子让人有点困惑;我的理解是,第二个示例(其中
emplace
采用构造函数参数)可用于C++11或更高版本,这些版本现在应该非常通用(IMHO)

或者,您可以使用“完整符号”,这些符号的描述更为详细,并附有更多示例。如果您告诉Bison使用“完整符号”API(使用
%define API.token.constructor
声明),那么Bison将自动生成各种
make_XXX
函数。要使用这些函数,您必须更改扫描仪的
get_next_token
成员函数,以返回
symbol\u type
对象,而不是
int
(然后它不需要yylvalp参数)。这可能是一个比你想做的更大的改变


笔记:
  • 您可以使用
    std::variant
    或具有显式定义的
    api.value.type
    的Boost等价物,但这不会产生
    make*
    调用,而且Bison也不知道如何从变量中提取单个类型,因此整个
    %type
    机制无法工作,因此它不是很有吸引力

  • 我阅读了文档中的许多内容,尝试了3天,但我不知道如何从我的扫描仪中给bison标记和值?如果您给出一个更具体的答案或一个读数,那就太好了。@MohamadZiadAlkabakibi:我在答案中添加了更多信息,试图解释为解析器提供标记的选项。提供特定的代码并不容易,因为我不知道您的特定需求是什么;手册中有一些示例(如我所示)。你需要明白野牛给了你几个(相互排斥的)选择;你必须决定采取哪种方法。然后你应该尝试一个语法部分的小实现,看看它是否适合你。如果遇到具体问题,请提出更详细的问题(作为新问题)。
    %require "3.2"
    %define api.pure full
    
    
    %code{
    #include <stdio.h>
    #include <string.h>
    #include "Scanner.h"
    #include<iostream>
    }
    
    
    
    %code{
        int yylex(YYSTYPE *lvalp);
        #include<iostream>
        #include<string>
        Scanner scanner;
        void yyerror(const char *error);
    }
    
    
    %union {
    int n;
    double d;
    char s[1000];
    }
    
    %token VAR COL ITYPE
    %token IDENTIFIER
    %token INTEGER
    %token EOL
    
    %type <s> type PrimitiveType IDENTIFIER
    %type <s> INTEGER    
    
    %%
    program:
    | program EOL
    | program SimpleDeclaration {  }
    ;
    
    SimpleDeclaration: VariableDeclaration
    ;
    
    VariableDeclaration: VAR IDENTIFIER COL type {std::cout<<"defined variable " << $2 << " with type " << $4 << std::endl; }
    
    type: IDENTIFIER
    | PrimitiveType
    ;
    
    PrimitiveType: ITYPE { strcpy($$, "int"); }
    ;
    
    %%
    int main()
    {
        scanner.set_file("inp.txt");
        return yyparse();
    }
    
    void yyerror(const char *error)
    {
        std::cout << "syntax error" << std::endl;
    }
    
    int yylex(YYSTYPE *lvalp)
    {
        return scanner.get_next_token(lvalp);
    }
    
    defined variable x with type int