问题描述
使用这个 https://github.com/antlr/grammars-v4/tree/master/cpp antlr 语法我正在尝试解析 C++ 代码。下面是我正在使用的同一个访问者类,我没有实现太多的访问者功能,
#include <iostream>
#include <antlr4-runtime.h>
#include "parser/CPP14Lexer.h"
#include "parser/CPP14BaseVisitor.h"
#include "parser/CPP14Parser.h"
#include "parser/CPP14Visitor.h"
class TREEVisitor : public CPP14BaseVisitor {
public:
virtual antlrcpp::Any TREEVisitor::visitFunctionBody(
CPP14Parser::FunctionBodyContext *ctx) override
{
std::cout << ctx->getText() << std::endl;
return visitChildren(ctx);
}
};
int main(int argc,char *argv[]) {
std::ifstream stream;
stream.open(argv[1]);
antlr4::ANTLRInputStream input(stream);
CPP14Lexer lexer(&input);
antlr4::CommonTokenStream tokens(&lexer);
CPP14Parser parser(&tokens);
antlr4::tree::ParseTree *tree = parser.translationunit();
// Visitor
auto *visitor = new TREEVisitor();
visitor->visit(tree);
return 0;
}
我正在尝试解析以下 C++ 代码,
#include <atomic>
#define RUN_ONCE \
for (static std::atomic<int> _run_already_(false); \
!_run_already_.fetch_or(true);) \
void foo()
{
RUN_ONCE
{
printf("Hello only once!\n");
/* Other statements follow */
}
}
然后我收到以下消息
line 11:36 no viable alternative at input 'voidfoo(){RUN_ONCE{printf("Hello only once!\n");'
line 14:0 extraneous input '}' expecting <EOF>
RUN_ONCE{}
有问题,但我不确定如何解决这个问题?
当我有一个名为 override 的变量时,我遇到了同样的问题!
void foo()
{
std::string override;
}
我收到以下消息,
line 9:16 no viable alternative at input 'voidfoo(){std::stringoverride'
line 9:24 mismatched input ';' expecting {'try','{','=',':'}
line 10:0 extraneous input '}' expecting <EOF>
我不介意忽略 override
并且不再将其视为 C++ 关键字。我不知道我应该如何修改我的语法。
非常感谢您为解决此问题而提供的答案。
谢谢, 亚历克斯
解决方法
您使用的 C++ 语法并不真正支持宏¹。它只是在词法分析期间跳过以 #
开头的行,然后假定源的其余部分在没有任何宏处理的情况下在语法上是有效的。在您的代码中显然不是这种情况,这就是它不起作用的原因。
在将代码传递给解析器之前,您需要通过现有的预处理器传递代码,或者实现自己的预处理器。
您的第二个问题是由于语法将 override
视为关键字,而它应该是上下文关键字,即它仍然应该被允许作为标识符。您可以通过为匹配上下文关键字以及 Identifier
的标识符创建一个非终结符来解决这个问题,然后在当前使用 Identifier
的任何地方使用它。
¹ 这是可以预料的。您无法真正使用单一语法解析未经预处理的 C 或 C++。