1

我试图从http://gnuu.org/2009/09/18/writing-your-own-toy-compiler编译 并且遇到了一些问题。https://github.com/lsegal/my_toy_compiler

使用自带的make文件的时候报错

C:\New Compile\my_toy_compiler-master\my_toy_compiler-master>make
bison -d -o parser.cpp parser.y
parser.y: warning: 48 shift/reduce conflicts [-Wconflicts-sr]
g++ -c `llvm-config --cppflags` -std=c++11 -o parser.o parser.cpp
g++ -c `llvm-config --cppflags` -std=c++11 -o codegen.o codegen.cpp
g++ -c `llvm-config --cppflags` -std=c++11 -o main.o main.cpp
flex -o tokens.cpp tokens.l parser.hpp
g++ -c `llvm-config --cppflags` -std=c++11 -o tokens.o tokens.cpp
tokens.cpp: In function 'void yy_init_buffer(YY_BUFFER_STATE, FILE*)':
tokens.cpp:1464:48: error: 'fileno' was not declared in this scope

                                                ^
tokens.cpp:1464:48: note: suggested alternative: 'file'

                                                ^
                                                file
make: *** [Makefile:27: tokens.o] Error 1

我查看了词法分析器生成的文件并复制了方法,

    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )

{
    int oerrno = errno;

    yy_flush_buffer( b );

    b->yy_input_file = file;
    b->yy_fill_buffer = 1;

    /* If b is the current buffer, then yy_init_buffer was _probably_
     * called from yyrestart() or through yy_get_next_buffer.
     * In that case, we don't want to reset the lineno or column.
     */
    if (b != YY_CURRENT_BUFFER){
        b->yy_bs_lineno = 1;
        b->yy_bs_column = 0;
    }

        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;

    errno = oerrno;
}

使用博客中给出的常规方式,我得到了大量的错误。

C:\New Compile\my_toy_compiler-master\my_toy_compiler-master>g++ -o parser parser.cpp tokens.cpp main.cpp
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV20NFunctionDeclaration[.refptr._ZTV20NFunctionDeclaration]+0x0): undefined reference to `vtable for NFunctionDeclaration'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV18NExternDeclaration[.refptr._ZTV18NExternDeclaration]+0x0): undefined reference to `vtable for NExternDeclaration'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV20NVariableDeclaration[.refptr._ZTV20NVariableDeclaration]+0x0): undefined reference to `vtable for NVariableDeclaration'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV16NReturnStatement[.refptr._ZTV16NReturnStatement]+0x0): undefined reference to `vtable for NReturnStatement'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV20NExpressionStatement[.refptr._ZTV20NExpressionStatement]+0x0): undefined reference to `vtable for NExpressionStatement'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV6NBlock[.refptr._ZTV6NBlock]+0x0): undefined reference to `vtable for NBlock'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV11NAssignment[.refptr._ZTV11NAssignment]+0x0): undefined reference to `vtable for NAssignment'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV15NBinaryOperator[.refptr._ZTV15NBinaryOperator]+0x0): undefined reference to `vtable for NBinaryOperator'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV11NMethodCall[.refptr._ZTV11NMethodCall]+0x0): undefined reference to `vtable for NMethodCall'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV11NIdentifier[.refptr._ZTV11NIdentifier]+0x0): undefined reference to `vtable for NIdentifier'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV7NDouble[.refptr._ZTV7NDouble]+0x0): undefined reference to `vtable for NDouble'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc6vUDwi.o:parser.cpp:(.rdata$.refptr._ZTV8NInteger[.refptr._ZTV8NInteger]+0x0): undefined reference to `vtable for NInteger'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text+0x24): undefined reference to `LLVMLinkInMCJIT'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text+0x24): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `LLVMLinkInMCJIT'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text+0x9e): undefined reference to `createCoreFunctions(CodeGenContext&)'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text+0x9e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `createCoreFunctions(CodeGenContext&)'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text+0xb4): undefined reference to `CodeGenContext::generateCode(NBlock&)'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text+0xb4): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `CodeGenContext::generateCode(NBlock&)'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text+0xc3): undefined reference to `CodeGenContext::runCode()'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text+0xc3): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `CodeGenContext::runCode()'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text+0x16e): undefined reference to `llvm::LLVMContext::LLVMContext()'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text+0x16e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `llvm::LLVMContext::LLVMContext()'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0x9): undefined reference to `LLVMInitializeX86TargetInfo'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0x9): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `LLVMInitializeX86TargetInfo'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0xe): undefined reference to `LLVMInitializeX86Target'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0xe): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `LLVMInitializeX86Target'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0x13): undefined reference to `LLVMInitializeX86TargetMC'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0x13): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `LLVMInitializeX86TargetMC'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN4llvm32InitializeNativeTargetAsmPrinterEv[_ZN4llvm32InitializeNativeTargetAsmPrinterEv]+0x9): undefined reference to `LLVMInitializeX86AsmPrinter'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN4llvm32InitializeNativeTargetAsmPrinterEv[_ZN4llvm32InitializeNativeTargetAsmPrinterEv]+0x9): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `LLVMInitializeX86AsmPrinter'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN4llvm31InitializeNativeTargetAsmParserEv[_ZN4llvm31InitializeNativeTargetAsmParserEv]+0x9): undefined reference to `LLVMInitializeX86AsmParser'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN4llvm31InitializeNativeTargetAsmParserEv[_ZN4llvm31InitializeNativeTargetAsmParserEv]+0x9): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `LLVMInitializeX86AsmParser'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN14CodeGenContextC1Ev[_ZN14CodeGenContextC1Ev]+0x73): undefined reference to `llvm::Module::Module(llvm::StringRef, llvm::LLVMContext&)'
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.text$_ZN14CodeGenContextC1Ev[_ZN14CodeGenContextC1Ev]+0x73): additional relocation overflows omitted from the output
/cygdrive/c/Users/Joey/AppData/Local/Temp/cc4uUJR7.o:main.cpp:(.rdata$.refptr._ZN4llvm11LLVMContextD1Ev[.refptr._ZN4llvm11LLVMContextD1Ev]+0x0): undefined reference to `llvm::LLVMContext::~LLVMContext()'
collect2: error: ld returned 1 exit status

C:\New Compile\my_toy_compiler-master\my_toy_compiler-master>g++ -o parser `llvm-config --libs core jit native --cxxflags --ldflags` *.cpp
g++: error: `llvm-config: No such file or directory
g++: error: core: No such file or directory
g++: error: jit: No such file or directory
g++: error: native: No such file or directory
g++: error: unrecognized command line option '--libs'
g++: error: unrecognized command line option '--cxxflags'
g++: error: unrecognized command line option '--ldflags`'

C:\New Compile\my_toy_compiler-master\my_toy_compiler-master>

当我使用 Cygwin 和不同的软件包时,我不确定下一步要采取什么步骤。起初我以为它可能是 Github 声明的版本,它只支持 llvm 到 4.0,所以我回溯并安装了 4.0,但仍然遇到同样的问题。

4

1 回答 1

2

Flex 可以生成三种词法分析器:

  • 交互的

  • 非交互式(“批处理”)

  • 有时是交互式的(默认)。

非交互式词法分析器是最有效的;他们一次读取输入缓冲区。这对于解析文件非常有用,但对于解析控制台输入却很烦人,尤其是当意图响应输入的每一行时。交互式词法分析器通过一次读取一个字符来避免这个问题,以便尽快报告一个标记。但这对于大令牌的输入可能效率低下。

默认词法分析器测试其输入是否为控制台,并使用该信息在交互式和非交互式缓冲区处理之间进行选择。这种策略的唯一问题是标准 C 库没有提供任何方法来判断输入流是否是控制台。Unix(-like) 系统确实有一个函数可以回答这个问题,但它不适用于标准 CFILE*流;它需要底层的“文件号”。该fileno函数从 a 中提取底层文件编号FILE*,但它显然不是标准的 C 函数。

所以如果你有一个默认的词法分析器,它需要调用fileno. 但是,fileno除非您#define使用功能测试宏,否则不会在任何标准标头中声明。但是你必须在 C 程序的开头定义这些宏,这在 C 程序自动生成时很难做到。-D最简单的解决方案是使用以下选项在编译器命令行上添加宏定义:

g++ -c `llvm-config --cppflags` -D_POSIX_C_SOURCE -std=c++11 -o tokens.o tokens.cpp

这只是您可以使用的可能宏之一;我在这里选择它是因为它是 中的一个man fileno,但我通常使用-D_XOPEN_SOURCE=700它,它请求更新 Posix 版本的接口。另一种可能性是_GNU_SOURCE,它可以让 Gnu 标头很好地包含所有内容,包括 Gnu 特定的扩展函数。

在我的(linux)系统上,llvm-config --cppflags包括-D_GNU_SOURCE,但这并不重要,因为 g++ 和 clang++ 的当前版本都会自动_GNU_SOURCE为 C++ 目标定义。显然,Cygwin 并非如此。参见,例如:

两者都建议更改-std=c++11-std=gnu++11.

另一种方法是通过请求非交互式词法分析器来回避这个问题,或者使用 flex 命令行选项:

flex --batch -o tokens.cpp tokens.l parser.hpp

或者通过添加

%option batch

到您的 flex 输入文件。请参阅弹性手册

(显然,如果您正在编写交互式计算器,则不要请求批处理词法分析器。在这种情况下,您可能希望请求始终交互式词法分析器。)

于 2019-03-12T17:33:00.677 回答