我如何从antlrcpp::Any解决这个std::bad_cast?
How do I solve this std::bad_cast with from antlrcpp::Any?
我正在尝试使用 ANTLR4 解析表达式。因此,我正在使用访问者模式并创建一个抽象语法树。
结果可以是表达式或其他内容(我从此示例代码中删除了这些表达式)。访问者期望返回类型为antlrcpp::Any
,因此抽象语法树的元素将转换为antlrcpp::Any
。
但是如果我尝试将结果从antlrcpp::Any
转换为std::shared_ptr<Expression>
,我会得到一个std::bad_cast
.
#include <iostream>
#include <string>
#include <memory>
#include "antlr4-runtime.h"
#include "Parser/SimpleLangLexer.h"
#include "Parser/SimpleLangParser.h"
#include "Parser/SimpleLangBaseVisitor.h"
struct Expression;
struct Node {
virtual ~Node() { }
};
struct Expression: public Node {
int constValue;
Expression(int constValue) : constValue(constValue) { }
virtual ~Expression() override { }
};
struct AstVisitor: public SimpleLangBaseVisitor {
virtual antlrcpp::Any visitTopLevelElement(SimpleLangParser::TopLevelElementContext *ctx) override {
std::shared_ptr<Expression> expression = ctx->expression()->accept(this);
return std::dynamic_pointer_cast<Node>(expression);
}
virtual antlrcpp::Any visitIntExpr(SimpleLangParser::IntExprContext *ctx) override {
std::string strInteger = ctx->INTEGER()->getSymbol()->getText();
int constValue = std::stoi(strInteger);
auto intExpr = std::make_shared<Expression>(constValue);
return intExpr;
}
};
int main() {
std::string line = "123;";
antlr4::ANTLRInputStream input(line);
SimpleLangLexer lexer(&input);
antlr4::CommonTokenStream tokens(&lexer);
SimpleLangParser parser(&tokens);
antlr4::tree::ParseTree *tree = parser.start();
// Prints:
// > (start (topLevelElement (expression 123) ;) <EOF>)
std::cout << std::endl << tree->toStringTree(&parser) << std::endl;
AstVisitor astVisitor;
antlrcpp::Any result = tree->accept(&astVisitor);
// Prints:
// > Dn
// std::cout << result.get_typeinfo().name() << std::endl;
// Error:
// > terminate called after throwing an instance of 'std::bad_cast'
// what(): std::bad_cast
std::shared_ptr<Node> node = result;
std::shared_ptr<Expression> iexpr = std::dynamic_pointer_cast<Expression>(node);
// Expected:
// > 123
std::cout << iexpr->constValue << std::endl;
return 0;
}
antlrcpp::任何
我的语法:
grammar SimpleLang;
start
: topLevelElement* EOF
;
topLevelElement
: expression ';'
;
expression
: IDENTIFIER #identifierExpr
| INTEGER #intExpr
;
IDENTIFIER
: [_a-zA-Z][_a-zA-Z0-9]*
;
INTEGER
: [0-9]+
;
WS: [ rnt] -> skip;
注意:我大大减少了这个问题的代码,我希望它仍然有意义。
antlrcpp::Any result = tree->accept(&astVisitor);
// Error:
// > terminate called after throwing an instance of 'std::bad_cast'
// what(): std::bad_cast
std::shared_ptr<Node> node = tree->accept(result);
在这里,您首先使用指向astVisitor
的指针调用tree->accept
。
然后你获取结果,并将其传递给tree->accept
,这可能需要一个指向SimpleLangBaseVisitor
的指针。 但是第一个tree->accept
调用返回了一个可能不包含指向SimpleLangBaseVisitor
的指针的Any
。
所以它会抛出一个错误。
顺便说一句,您正在使用的Any
缺少std::typeinfo const& get_typeinfo() const
。 如果你有这个,你可以做一些get_typeinfo().name()
printf调试,以获得出了什么问题的线索。
如果您有权访问源代码,请添加:
struct Base {
virtual ~Base();
virtual Base* clone() const = 0;
std::typeinfo const& get_typeinfo() const = 0;
};
template<typename T>
struct Derived : Base {
// ...
std::typeinfo const& get_typeinfo() const override {
return typeid(T);
}
};
并Any
自己:
std::typeinfo const& get_typeinfo() const {
if (!_ptr) return typeid(std::nullptr_t);
return ptr->get_typeinfo();
}
一旦你有了这个,std::cerr << some_any.get_typeinfo().name() << std::endl;
就会解决许多"为什么我会得到bad_cast?!"的痛苦。 但它确实要求你的代码和生成 Any 的代码都使用此修改后的Any
构建。
相关文章:
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- std::向量与传递值的动态数组
- 使用std::vector的OpenCL矩阵乘法
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- std::condition_variable::wait()如何评估给定的谓词
- 如何获取std::result_of函数的返回类型
- std::原子加载和存储都需要吗
- 将对象移动到std::shared_ptr
- 获取错误:在抛出"std::bad::alloc"的实例后终止调用 what(): std::bad_alloc
- "std::vector"在调整大小时引发"bad allocation"异常
- 成员函数 bad() 的 std::ftsream 用于检查
- 正在使用std::string而不是char*bad
- 在抛出 'std::bad _alloc' 的实例后调用终止 what(): std::bad_alloc 在 c++ 中
- What is Scala for: getline(), std::cin.eof(), std::cin.bad()