簡體   English   中英

如何使用antlrcpp :: Any解決此std :: bad_cast問題?

[英]How do I solve this std::bad_cast with from antlrcpp::Any?

我正在嘗試使用ANTLR4解析表達式。 因此,我正在使用訪問者模式並創建抽象語法樹。

結果可以是表達式或其他內容(我從此示例代碼中刪除了該內容)。 訪問者期望返回類型為antlrcpp::Any因此抽象語法樹的元素將轉換為antlrcpp::Any

但我發現了一個std::bad_cast ,如果我想要的結果,從轉換回antlrcpp::Anystd::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;
}

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);

在這里,您首先使用指向astVisitor的指針調用tree->accept

然后,您將得到的結果傳遞給tree->accept ,它可能期望指向SimpleLangBaseVisitor的指針。 但是第一個tree->accept調用返回的Any可能不包含指向SimpleLangBaseVisitor的指針。

因此會引發錯誤。


std::typeinfo const& get_typeinfo() const ,您正在使用的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; 將解決許多“為什么我會收到壞消息?!” 煞費苦心。 但這確實要求您的代碼以及生成Any的代碼都必須使用經過修改的Any來構建。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM