由 bison 创建的解析器代码的 g++ 编译失败,因为“yytokentype”枚举值不可见
Compilation by g++ of parser code created by bison fails because `yytokentype` enum values are not visible
我正在尝试使用
在 Linux 上编译 chuffed
- gcc-c++-10.3.1-1.fc33.x86_64
- flex-2.6.4-5.fc33.x86_64
- bison-3.6.4-3.fc33.x86_64
这是 CMAKE 管理的安装。
如 the README 中所述,从发行版的顶层目录开始,我 运行:
mkdir build
cd build
cmake ..
cmake --build . --verbose
此时出现错误。解析器代码的创建似乎有效。然后使用选项 -std=gnu++11
调用 /usr/bin/c++
。它终止于:
parser.tab.cpp: In function ‘int yyparse(void*)’:
parser.tab.cpp:1963:12: error: ‘YYEMPTY’ was not declared in this scope
1963 | yychar = YYEMPTY; /* Cause a token to be read. */
| ^~~~~~~
parser.tab.cpp:2077:17: error: ‘YYEOF’ was not declared in this scope
2077 | if (yychar <= YYEOF)
| ^~~~~
parser.tab.cpp:2083:22: error: ‘YYerror’ was not declared in this scope; did you mean ‘yyerror’?
2083 | else if (yychar == YYerror)
| ^~~~~~~
| yyerror
parser.tab.cpp:2089:16: error: ‘YYUNDEF’ was not declared in this scope; did you mean ‘YYUSE’?
2089 | yychar = YYUNDEF;
| ^~~~~~~
| YYUSE
parser.tab.cpp:3650:21: error: ‘YYEOF’ was not declared in this scope
3650 | if (yychar <= YYEOF)
| ^~~~~
在源代码中,编译器正在查找的常量在枚举中定义:
/* Token kinds. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
YYEMPTY = -2,
YYEOF = 0, /* "end of file" */
YYerror = 256, /* error */
YYUNDEF = 257, /* "invalid token" */
INT_LIT = 258, /* INT_LIT */
BOOL_LIT = 259, /* BOOL_LIT */
FLOAT_LIT = 260, /* FLOAT_LIT */
ID = 261, /* ID */
STRING_LIT = 262, /* STRING_LIT */
...
WHERE = 301 /* WHERE */
};
typedef enum yytokentype yytoken_kind_t;
#endif
并在 yyparse(void *parm)
中使用这样的例子:
YYDPRINTF ((stderr, "Starting parse\n"));
yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
乍一看,编译器似乎没有理由抱怨。但是,可能有一些特定于 C++ 版本或此处使用的语法。我的 C++ 很生疏,这可能是直截了当的事情。
我尝试将行更改为
yychar = yytokentype::YYEMPTY; /* Cause a token to be read. */
但后来我得到:
parser.tab.cpp:1963:25: error: ‘YYEMPTY’ is not a member of ‘yytokentype’
1963 | yychar = yytokentype::YYEMPTY; /* Cause a token to be read. */
那就更令人费解了。
在n-1-8e9-wheres-my-share-m的建议下,
假设
CHUFFED_TOPDIR=... # toplevel of the distribution
我们发现有一个现有的 parser.tab.h
使用旧式 GNU Bison 3.0.4 创建:
"$CHUFFED_TOPDIR"/chuffed/flatzinc/parser.tab.h
这个文件在编译的时候确实被包含了,这样编译的时候就可以确定,导致打印出包含树:
cd "$CHUFFED_TOPDIR"
rm -rf build/
mkdir build
cd build/
cmake -E env CXXFLAGS="-H" cmake .. # using cmake to run cmake
cmake --build . --verbose
Note
The usual command line for running cmake
would be:
cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR ..
Definitely consider switching on debug mode for a first try.
This is important for running the examples, which do not check
their commandline arguments and segfault if these are
missing . With debugging on, you at least get assertion
error messages:
cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR \
-DCMAKE_BUILD_TYPE=Debug ..
So, altogether
cmake -E env CXXFLAGS="-H" \
cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR
-DCMAKE_BUILD_TYPE=Debug ..
因此,请尝试删除 parser.tab.h
并确保随附的 parser.tab.cpp
:
mv "$CHUFFED_TOPDIR"/chuffed/flatzinc/parser.tab.h \
"$CHUFFED_TOPDIR"/chuffed/flatzinc/parser.tab.h.bak
mv "$CHUFFED_TOPDIR"/chuffed/flatzinc/parser.tab.cpp \
"$CHUFFED_TOPDIR"/chuffed/flatzinc/parser.tab.cpp.bak
lexer.yy.cpp
可能存在类似的问题,因此:
mv "$CHUFFED_TOPDIR"/chuffed/flatzinc/lexer.yy.cpp \
"$CHUFFED_TOPDIR"/chuffed/flatzinc/lexer.yy.cpp.bak
Note
It is always good to take a look at
"$CHUFFED_TOPDIR"/build/CMakeFiles/CMakeError.log
but in my case it just says that looking for the pthread library
failed, at least initially.
编译成功。可以发现 Bison 输出为:
"$CHUFFED_TOPDIR"/build/parser.tab.cpp
以及:
"$CHUFFED_TOPDIR"/build/chuffed/flatzinc/parser.tab.h
请注意,在 CMakeLists.txt
文件中,我们找到以下代码:
find_package(BISON)
if(BISON_FOUND)
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/chuffed/flatzinc)
bison_target(FZNParser
${PROJECT_SOURCE_DIR}/chuffed/flatzinc/parser.yxx
${PROJECT_BINARY_DIR}/parser.tab.cpp
DEFINES_FILE ${PROJECT_BINARY_DIR}/chuffed/flatzinc/parser.tab.h
COMPILE_FLAGS "-l"
)
else()
message(WARNING "Bison cannot be run. Using cached file, which may be out of date.")
set(BISON_FZNParser_OUTPUTS
${PROJECT_SOURCE_DIR}/chuffed/flatzinc/parser.tab.cpp
${PROJECT_SOURCE_DIR}/chuffed/flatzinc/parser.tab.h
)
endif()
find_package(FLEX)
if(FLEX_FOUND)
flex_target(FZNLexer
${PROJECT_SOURCE_DIR}/chuffed/flatzinc/lexer.lxx
${PROJECT_BINARY_DIR}/lexer.yy.cpp
COMPILE_FLAGS "-L"
)
add_flex_bison_dependency(FZNLexer FZNParser)
else()
message(WARNING "Flex cannot be run. Using cached file, which may be out of date.")
set(FLEX_FZNLexer_OUTPUTS ${PROJECT_SOURCE_DIR}/chuffed/flatzinc/lexer.yy.cpp)
endif()
我想如果在编译系统上可以找到 bison,应该自动跳过提供的 parser.tab.h
。我不确定这里出了什么问题。
我正在尝试使用
在 Linux 上编译 chuffed- gcc-c++-10.3.1-1.fc33.x86_64
- flex-2.6.4-5.fc33.x86_64
- bison-3.6.4-3.fc33.x86_64
这是 CMAKE 管理的安装。
如 the README 中所述,从发行版的顶层目录开始,我 运行:
mkdir build
cd build
cmake ..
cmake --build . --verbose
此时出现错误。解析器代码的创建似乎有效。然后使用选项 -std=gnu++11
调用 /usr/bin/c++
。它终止于:
parser.tab.cpp: In function ‘int yyparse(void*)’:
parser.tab.cpp:1963:12: error: ‘YYEMPTY’ was not declared in this scope
1963 | yychar = YYEMPTY; /* Cause a token to be read. */
| ^~~~~~~
parser.tab.cpp:2077:17: error: ‘YYEOF’ was not declared in this scope
2077 | if (yychar <= YYEOF)
| ^~~~~
parser.tab.cpp:2083:22: error: ‘YYerror’ was not declared in this scope; did you mean ‘yyerror’?
2083 | else if (yychar == YYerror)
| ^~~~~~~
| yyerror
parser.tab.cpp:2089:16: error: ‘YYUNDEF’ was not declared in this scope; did you mean ‘YYUSE’?
2089 | yychar = YYUNDEF;
| ^~~~~~~
| YYUSE
parser.tab.cpp:3650:21: error: ‘YYEOF’ was not declared in this scope
3650 | if (yychar <= YYEOF)
| ^~~~~
在源代码中,编译器正在查找的常量在枚举中定义:
/* Token kinds. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
YYEMPTY = -2,
YYEOF = 0, /* "end of file" */
YYerror = 256, /* error */
YYUNDEF = 257, /* "invalid token" */
INT_LIT = 258, /* INT_LIT */
BOOL_LIT = 259, /* BOOL_LIT */
FLOAT_LIT = 260, /* FLOAT_LIT */
ID = 261, /* ID */
STRING_LIT = 262, /* STRING_LIT */
...
WHERE = 301 /* WHERE */
};
typedef enum yytokentype yytoken_kind_t;
#endif
并在 yyparse(void *parm)
中使用这样的例子:
YYDPRINTF ((stderr, "Starting parse\n"));
yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
乍一看,编译器似乎没有理由抱怨。但是,可能有一些特定于 C++ 版本或此处使用的语法。我的 C++ 很生疏,这可能是直截了当的事情。
我尝试将行更改为
yychar = yytokentype::YYEMPTY; /* Cause a token to be read. */
但后来我得到:
parser.tab.cpp:1963:25: error: ‘YYEMPTY’ is not a member of ‘yytokentype’
1963 | yychar = yytokentype::YYEMPTY; /* Cause a token to be read. */
那就更令人费解了。
在n-1-8e9-wheres-my-share-m的建议下,
假设
CHUFFED_TOPDIR=... # toplevel of the distribution
我们发现有一个现有的 parser.tab.h
使用旧式 GNU Bison 3.0.4 创建:
"$CHUFFED_TOPDIR"/chuffed/flatzinc/parser.tab.h
这个文件在编译的时候确实被包含了,这样编译的时候就可以确定,导致打印出包含树:
cd "$CHUFFED_TOPDIR"
rm -rf build/
mkdir build
cd build/
cmake -E env CXXFLAGS="-H" cmake .. # using cmake to run cmake
cmake --build . --verbose
Note
The usual command line for running
cmake
would be:cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR ..
Definitely consider switching on debug mode for a first try. This is important for running the examples, which do not check their commandline arguments and segfault if these are missing . With debugging on, you at least get assertion error messages:
cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR \ -DCMAKE_BUILD_TYPE=Debug ..
So, altogether
cmake -E env CXXFLAGS="-H" \ cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR -DCMAKE_BUILD_TYPE=Debug ..
因此,请尝试删除 parser.tab.h
并确保随附的 parser.tab.cpp
:
mv "$CHUFFED_TOPDIR"/chuffed/flatzinc/parser.tab.h \
"$CHUFFED_TOPDIR"/chuffed/flatzinc/parser.tab.h.bak
mv "$CHUFFED_TOPDIR"/chuffed/flatzinc/parser.tab.cpp \
"$CHUFFED_TOPDIR"/chuffed/flatzinc/parser.tab.cpp.bak
lexer.yy.cpp
可能存在类似的问题,因此:
mv "$CHUFFED_TOPDIR"/chuffed/flatzinc/lexer.yy.cpp \
"$CHUFFED_TOPDIR"/chuffed/flatzinc/lexer.yy.cpp.bak
Note It is always good to take a look at
"$CHUFFED_TOPDIR"/build/CMakeFiles/CMakeError.log
but in my case it just says that looking for the pthread library failed, at least initially.
编译成功。可以发现 Bison 输出为:
"$CHUFFED_TOPDIR"/build/parser.tab.cpp
以及:
"$CHUFFED_TOPDIR"/build/chuffed/flatzinc/parser.tab.h
请注意,在 CMakeLists.txt
文件中,我们找到以下代码:
find_package(BISON)
if(BISON_FOUND)
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/chuffed/flatzinc)
bison_target(FZNParser
${PROJECT_SOURCE_DIR}/chuffed/flatzinc/parser.yxx
${PROJECT_BINARY_DIR}/parser.tab.cpp
DEFINES_FILE ${PROJECT_BINARY_DIR}/chuffed/flatzinc/parser.tab.h
COMPILE_FLAGS "-l"
)
else()
message(WARNING "Bison cannot be run. Using cached file, which may be out of date.")
set(BISON_FZNParser_OUTPUTS
${PROJECT_SOURCE_DIR}/chuffed/flatzinc/parser.tab.cpp
${PROJECT_SOURCE_DIR}/chuffed/flatzinc/parser.tab.h
)
endif()
find_package(FLEX)
if(FLEX_FOUND)
flex_target(FZNLexer
${PROJECT_SOURCE_DIR}/chuffed/flatzinc/lexer.lxx
${PROJECT_BINARY_DIR}/lexer.yy.cpp
COMPILE_FLAGS "-L"
)
add_flex_bison_dependency(FZNLexer FZNParser)
else()
message(WARNING "Flex cannot be run. Using cached file, which may be out of date.")
set(FLEX_FZNLexer_OUTPUTS ${PROJECT_SOURCE_DIR}/chuffed/flatzinc/lexer.yy.cpp)
endif()
我想如果在编译系统上可以找到 bison,应该自动跳过提供的 parser.tab.h
。我不确定这里出了什么问题。