2017-10-03 8 views
0

私はANTLR4で式を解析しようとしています。そのため私はビジターパターンを使用しており、抽象構文ツリーを作成しています。このstd :: bad_castをantlrcpp :: Anyからどのように解決すればよいですか?

結果は式など(この例のコードから削除したもの)にすることができます。訪問者は戻りタイプが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; 
} 

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; 

注:私は非常にこの質問のための私のコードを削減し、私はそれはまだ感じるになりたいと考えています。ここ

答えて

2
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へのポインタは含まれていません。

これでエラーが発生します。 Any使用しているがstd::typeinfo const& get_typeinfo() constが欠落していることはさておき、として


。もしあなたがそれを持っていれば、何が起こっているのかを知るために、get_typeinfo().name() printfデバッグを行うことができます。

あなたは、ソースコードの追加にアクセスしている場合:あなたはstd::cerr << some_any.get_typeinfo().name() << std::endl;は、なぜ私はbad_castを取得しています」多くを解決する、ことをしたら

std::typeinfo const& get_typeinfo() const { 
    if (!_ptr) return typeid(std::nullptr_t); 
    return ptr->get_typeinfo(); 
} 

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自体には? ! "痛み。しかし、あなたのコードとAnyを生成するコードの両方が、この変更されたAnyで構築されている必要があります。

+0

すばやくお返事ありがとうございます!私は私の質問を編集しました。 'std :: bad_cast'は' std :: shared_ptr node = result; 'という行にスローされます。私はローカルコピーをAnyに再構築します。しかし、私はタイプ名 'Dn'が意味するものを見つけることができません。 – dotjpg3141

+0

@ JP3141 http://coliru.stacked-crooked.com/a/2e6451847ce85e93(nullptr)。 – Yakk

+0

ありがとう! 'result.isNull()'は 'true'を返します。 – dotjpg3141

関連する問題