c++ - 编译我的 flex 和 bison 代码时,G++ 无法识别我的 C++ 类

标签 c++ bison

我正在编写一个词法分析器和解析器组合,将 arm8 汇编代码存储在数据结构中以供进一步测试。但是,在编译代码时,编译器不会将我导入的类识别为合法的数据类型。

我一直在关注这个指南:https://gnuu.org/2009/09/18/writing-your-own-toy-compiler/在某种程度上。我尝试更改 bison 的输出设置以生成一个 c++ 文件,它修复了部分问题,但它打开了我希望避免的一整套蠕虫病毒。我看过的所有指南都在这个过程中使用了 C++ 代码,我真的不明白为什么它在这里失败了。

assembly_bison.y:

%{
    #include <cstdio>
    #include <iostream>
    #include <string>
    #include "instructionds.h"
    #include "AssemblyBlock.h"
    using namespace std;

    extern int yylex();
    extern int yyparse();
    extern FILE *yyin;

    AssemblyBlock *assembly = new AssemblyBlock();
    STP *input;
    void yyerror(const char *s);
%}

%union {
    long long imm;
    std::string *string;
    int token;
}

%token STP INSTRUCTION 
%token STACKPOINTER "sp"

%token <imm> IMMEDIATE
%token <string> DIRECTIVE LABEL INLINELABEL
%token <token> REGISTER64 REGISTER32
%token <token> COMMA ","
%token <token> BANG "!"
%token <token> OPENBRACKET "["
%token <token> CLOSEBRACKET "]"

%%
document:
    document line
    | /* empty */
;

line:
    LABEL
    | DIRECTIVE {/* */}
    | LABEL instruction
    | instruction
;

instruction:
    stp
;

stp:
    STP REGISTER64 "," REGISTER64 "," "[" "sp" "," IMMEDIATE "]" "!"
        {
            input = new STP(true, true, $2, $4, -1, $9);
            assembly->insert(input);
        }
%%

int main(int, char**) {
  // Open a file handle to a particular file:
  FILE *myfile = fopen("Hello_World_Assembly_Code.asm", "r");
  // Make sure it is valid:
  if (!myfile) {
    cout << "I can't open a.snazzle.file!" << endl;
    return -1;
  }
  // Set Flex to read from it instead of defaulting to STDIN:
  yyin = myfile;

  // Parse through the input:
  yyparse();

}

void yyerror(const char *s) {
  cout << "EEK, parse error!  Message: " << s << endl;
  // might as well halt now:
  exit(-1);
}

assembly_lexer.l

%{
    #include <cstdio>
    #include <string>
    #include "instructionds.h"
    #include "AssemblyBlock.h"
    #include "parser.hpp"
    #define SAVE_TOKEN yylval.string = new std::string(yytext, yyleng)
    #define TOKEN(t) (yylval.token = t)
%}
%option noyywrap

delim   [ \t\n]
ws      [delim+]
letter  [A-Za-z]
digit   [0-9]
id      {letter}({letter}|{digit})*
alphanumeric [A-Za-z0-9]
%%
{delim} {/* no action and return */}
\.L[A-Z0-9]*: { SAVE_TOKEN; return LABEL; }
\.[a-z0-9_]+.* { SAVE_TOKEN; return DIRECTIVE; }
{alphanumeric}+\: { SAVE_TOKEN; return LABEL; }
stp { return STP; }
add { return INSTRUCTION; }
adrp { return INSTRUCTION; }
bl { return INSTRUCTION; }
mov { return INSTRUCTION; }
ldp { return INSTRUCTION; }
ret { return INSTRUCTION; }
sp { return STACKPOINTER; }
x{digit}+ { yylval.register = stoi(yytext.substr(1,yytext.length())); return REGISTER64; }
w{digit}+ { yylval.register = stoi(yytext.substr(1,yytext.length())); return REGISTER32; }
, { return TOKEN(COMMA); }
\.L[A-Z0-9]* { yylval.sval = strdup(yytext); return INLINELABEL; } //Needs revision
\[ { return TOKEN(OPENBRACKET); }
\] { return TOKEN(CLOSEBRACKET); }
:{id}: { }
#?[+-]?{digit}+ { if(yytext[0] == '#') yytext.erase(0); yylval.imm = stoll(yytext); return IMMEDIATE } //Needs revision
{alphanumeric}+ { SAVE_TOKEN; return LABEL; }
! { return TOKEN(BANG); }
%%

instructionds.h:

#pragma once
class Instruction {
    public:
        virtual void print();
};

class STP : public Instruction{
    private: 

        //Possible inputs
        int Rn1;
        int Rn2;
        int Xn;
        bool SP;
        long long immediate;

        //Instruction Modes
        bool is64;
        bool isPreindex;
    public:
        STP(bool is64, bool isPreindex, int n1, int n2, int Xn, long long immediate);
        void print();
};

程序 block .h:

#pragma once
#include "instructionds.h"

struct InstStruct {
    Instruction* line;
    struct InstStruct *prev;
    struct InstStruct *next;
};

class AssemblyBlock {
    private:
        struct InstStruct *head;

    public:
        AssemblyBlock();
        void insert(Instruction *inst);
        void display();
};

如有必要,我可以稍后为这些类添加 .cpp 文件。

当我使用以下命令编译代码时,出现了这些错误。编译器似乎没有读取标题。我使用了一个测试文件来确保我构建的类在 bison 之外工作并且一切正常。如果有人对此有更多了解,我非常感谢您的帮助。

mattersonline@mattersonline-VirtualBox:~/Documents/flex/soonergy$ bison -d -o parser.cpp assembly_bison.y
assembly_bison.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
mattersonline@mattersonline-VirtualBox:~/Documents/flex/soonergy$ flex -o tokens.cpp assembly_lexer.l
mattersonline@mattersonline-VirtualBox:~/Documents/flex/soonergy$ g++ -o parser parser.cpp tokens.cpp AssemblyBlock.cpp instructionds.cpp
assembly_bison.y:15:5: error: ‘STP’ does not name a type
     STP *input;
     ^~~
assembly_bison.y: In function ‘int yyparse()’:
assembly_bison.y:56:13: error: ‘input’ was not declared in this scope
             input = new STP(true, true, $2, $4, -1, $9);
             ^~~~~
assembly_bison.y:56:13: note: suggested alternative: ‘ino_t’
             input = new STP(true, true, $2, $4, -1, $9);
             ^~~~~
             ino_t
assembly_bison.y:56:25: error: expected type-specifier before ‘STP’
             input = new STP(true, true, $2, $4, -1, $9);
                         ^~~
};

最佳答案

问题似乎是 STP 在语法中既是类型的名称又是标记的名称。将您的类型或 token 重命名为其他内容应该可以解决此问题。

希望这对您有所帮助!

关于c++ - 编译我的 flex 和 bison 代码时,G++ 无法识别我的 C++ 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56638351/

相关文章:

c++ - 为什么将未使用的返回值强制转换为 void?

c - bison 和 flex 的 Typedef 问题

c++ - 模板函数中引用类型的推导

c++ - 为什么一个简单的 CUDA 函数需要这么多本地内存?

C++ 模板类和 Matlab Mex

c - 如何编写构建标记树等的 YACC 语法?

c++ - ld : symbol(s) not found for architecture x86_64 error

c++ 数据对齐/成员顺序和继承

makefile - Make 添加意外的 mv 命令

c - 我如何让 yacc/bison 和/或 lex/flex 在 token 替换后重新开始扫描?