gpt4 book ai didi

c++ - 如何使用来自 antlrcpp::Any 的 std::bad_cast 解决这个问题?

转载 作者:行者123 更新时间:2023-11-30 03:28:31 32 4
gpt4 key购买 nike

我正在尝试使用 ANTLR4 解析表达式。因此,我正在使用访问者模式并创建一个抽象语法树。

结果可以是一个表达式或其他东西(我从这个示例代码中删除了)。访问者期望返回类型 antlrcpp::Any所以抽象语法树的元素被转换为antlrcpp::Any .

但我得到一个 std::bad_cast如果我试图将结果从 antlrcpp::Any 转换回来至 std::shared_ptr<Expression> .

#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;
}

Implementation of antlrcpp::Any

我的语法:

grammar SimpleLang;

start
: topLevelElement* EOF
;

topLevelElement
: expression ';'
;

expression
: IDENTIFIER #identifierExpr
| INTEGER #intExpr
;

IDENTIFIER
: [_a-zA-Z][_a-zA-Z0-9]*
;

INTEGER
: [0-9]+
;

WS: [ \r\n\t] -> 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);

给你打电话tree->accept首先是一个指向 astVisitor 的指针.

然后你把结果传给tree->accept ,它可能需要一个指向 SimpleLangBaseVisitor 的指针.但是第一个tree->accept调用返回 Any可能不包含指向 SimpleLangBaseVisitor 的指针.

所以它会抛出一个错误。


顺便说一句,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 构建.

关于c++ - 如何使用来自 antlrcpp::Any 的 std::bad_cast 解决这个问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46550607/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com