Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.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
C++ 使用Bison解析简单C源代码时出现的问题_C++_C_Parsing_Grammar_Bison - Fatal编程技术网

C++ 使用Bison解析简单C源代码时出现的问题

C++ 使用Bison解析简单C源代码时出现的问题,c++,c,parsing,grammar,bison,C++,C,Parsing,Grammar,Bison,下面是我正在使用的解析器代码 %{ #include <cstdio> #include <iostream> #include <cstring> #include <stdio.h> #include "c.ast.hpp" #include <typeinfo> #define YYDEBUG 1 using namespace std; // stuff from flex that bison need

下面是我正在使用的解析器代码

%{
#include <cstdio>
#include <iostream>
#include <cstring>
#include <stdio.h>
#include "c.ast.hpp"
#include <typeinfo>
#define YYDEBUG 1

using namespace std;

// stuff from flex that bison needs to know about:
extern "C" int yylex();
int yyparse(BlockOfFunctions *ast);
extern "C" FILE *yyin;
 
void yyerror(BlockOfFunctions *ast, const char *s);

#define TRACE printf("reduce at line %d\n", __LINE__);


%}
%token  IDENTIFIER I_CONSTANT F_CONSTANT STRING_LITERAL FUNC_NAME SIZEOF
%token  PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
%token  AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token  SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
%token  XOR_ASSIGN OR_ASSIGN
%token  TYPEDEF_NAME ENUMERATION_CONSTANT

%token  TYPEDEF EXTERN STATIC AUTO REGISTER INLINE
%token  CONST RESTRICT VOLATILE
%token  BOOL CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE VOID
%token  COMPLEX IMAGINARY 
%token  STRUCT UNION ENUM ELLIPSIS

%token  CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN

%token  ALIGNAS ALIGNOF ATOMIC GENERIC NORETURN STATIC_ASSERT THREAD_LOCAL

%start translation_unit
%parse-param {BlockOfFunctions *ast}

%union {
    string *str;
    TypeSpecifier typespec;
    FunctionDefinition *func;
    BlockOfFunctions *blockfunc;
    Declaration *decl;
    vector<Declaration> *decls;
    Signature *sig;
}

%type<typespec> type_specifier declaration_specifiers
%type<str> IDENTIFIER
%type<func> external_declaration function_definition
%type<blockfunc> translation_unit
%type<decl> parameter_declaration
%type<decls> parameter_list parameter_type_list
%type<sig> declarator direct_declarator
%%

declaration_specifiers
    : type_specifier { TRACE $$ = $1; }
    ;

type_specifier
    : VOID {
        cout << "creating void" << endl;
        $$ = TypeSpecifier::Void; }
    | INT { cout << "creating int" << endl; $$ = TypeSpecifier::Int; }
    ;

declarator
    : direct_declarator { $$ = $1; }
    ;

direct_declarator
    : IDENTIFIER {
        Signature sig;
        string name = *$1;
        sig.name = name;
        $$ = &sig;
        cout << "creating identifier " << sig.name << endl;
    }
    | direct_declarator '(' parameter_type_list ')' {
        cout << "with argument" << endl;
        
        cout << "got declarator " << *$1 << endl;
        cout << "creating declaration " << $3->at(0) << endl;
        $$ = $1;
    }
    | direct_declarator '(' ')' {
        $$ = $1;
        cout << "argument less function" << endl; 
    }
    ;

parameter_type_list
    : parameter_list {
        $$ = $1;
        cout << "creating parameter type list " << $$->at(0) << endl; 
    }
    ;

parameter_list
    : parameter_declaration {
        vector<Declaration> params;
        cout << "pushing back " << *$1 << endl;
        params.push_back(*$1);
        $$ = &params;
        cout << "creating parameter declaration " << $$->at(0) << endl;
    }
    ;

parameter_declaration
    : declaration_specifiers declarator {
        cout << "creating param declaration" << endl;
        Declaration decl;
        string name = $2->name;
        decl.type = $1;
        decl.name = name;
        $$ = &decl;
    }
    ;

translation_unit
    : external_declaration { ast->block.push_back(*$1); }
    | translation_unit external_declaration { ast->block.push_back(*$2); }
    ;

external_declaration
    : function_definition  { TRACE $$ = $1; }
    ;

function_definition
    : declaration_specifiers declarator '{' '}' {
        string name = $2->name;
        FunctionDefinition fn;
        fn.ret = $1;
        fn.name = name;
        $$ = &fn;
    }
    ;

%%
#include <stdio.h>

void yyerror(BlockOfFunctions *ast, const char *s)
{
    fflush(stdout);
    fprintf(stderr, "*** %s\n", s);
}
但我得到以下输出

bison -t -v -o c.tab.cpp -d c.y
flex -o c.lex.cpp -l c.l
g++ c.tab.cpp c.lex.cpp cc.cpp -lm -ll -lfl -o cc
./cc examples/test.c
creating void
reduce at line 63
creating identifier empty
creating int
reduce at line 63
creating identifier a
creating param declaration
pushing back declaration: int a

creating parameter declaration declaration: int a

creating parameter type list declaration: void 

with argument
got declarator signature: a

creating declaration declaration: void 

reduce at line 129
retv = 0
function: void a
它错误地将函数名解析为
a
,而函数名应该是
空的
。我已经将错误缩小到一个特定的位置:正确地解析了
参数类型列表
非终端,但当它上移到
参数类型列表
时,它会变成一个完全不同的对象。您可以从运行时打印的信息中看到这一点

很明显我做错了什么,但我不明白。任何帮助都将不胜感激。

此声明(以及其他类似声明)是明确的未定义行为:

$$ = &decl;
您正试图存储指向生存期即将结束的局部变量的指针。当这个悬空指针的值最终被使用时,它不再引用任何东西

我强烈建议您在g++标志中添加
-Wall
。我不知道gcc是否会检测到这个错误,特别是在没有优化标志的情况下,但没有机会警告您是没有意义的


在没有看到flex代码的情况下,我无法判断您是否也在传递悬空指针作为标记的语义值,这是导致语义值神秘变化的另一个常见原因。你也可以检查一下。

这很有趣,我没想到。我对C++没有经验,你能告诉我做这个的正确方法吗?我的意思是在这种特殊情况下返回指向对象的指针。我必须以这样或那样的方式返回指向对象的指针,但据我所知,我做得不对。我使用了
new
操作符,并在以后不再使用对象时使用
delete
d。修复了一切,非常感谢!
$$ = &decl;