سؤال

أقوم بكتابة مترجم بلغة صغيرة، وتقوم فئة المحلل بمحللتي حاليا ببناء AST لاستخدامها لاحقا. ومع ذلك، فإن التعبيرات العودية لا تعمل بشكل صحيح لأن المتجه في كل عقدة AST التي تحمل العقد الطفل لا تعمل بشكل صحيح. حاليا ملف رأس AST الخاص بي يشبه هذا:

class AST
{
public:
    enum ASTtype {nil, fdecl, pdecl, vdecl, rd, wr, set, rdLV, setLV, exprLV, add, sub, mul, fcall,
        divide, mod, lt, gt, lte, gte, eq, ne, aAnd, aOr, aNot, aNeg, nConst, t, f, vs, dl, loop,
        cond, ss};
    enum scalarType {tNA, tINVALID, tINT, tLONG, tBOOL};
    AST ();
    AST (AST const&);
    AST (ASTtype);
    AST (ASTtype, std::string);
    void addChild(AST);
    ASTtype getNodeType();
    std::string text;
    ASTtype nodeType;
    int size;
    scalarType evalType;
    std::vector<AST> children;
};

إليك رمز تحليل التعبير الذي يسبب مشكلة:

void Parser::e(AST& parent)
{
    AST expr;
    AST::ASTtype check = AST::nil;
    bool binOp = false;

    switch (lookahead.type)
    {
        case Lexer::AND    : check = AST::aAnd  ; binOp = true; break; 
        case Lexer::OR     : check = AST::aOr   ; binOp = true; break; 
        case Lexer::NOT    : check = AST::aNot  ; break;
        case Lexer::NEG    : check = AST::aNeg  ; break;
        case Lexer::PLUS   : check = AST::add   ; binOp = true; break;
        case Lexer::MINUS  : check = AST::sub   ; binOp = true; break;
        case Lexer::SPLAT  : check = AST::mul   ; binOp = true; break;
        case Lexer::FSLASH : check = AST::divide; binOp = true; break;
        case Lexer::MOD    : check = AST::mod   ; binOp = true; break;
        case Lexer::EQ     : check = AST::eq    ; binOp = true; break;
        case Lexer::LT     : check = AST::lt    ; binOp = true; break;
        case Lexer::GT     : check = AST::gt    ; binOp = true; break;
        case Lexer::GTE    : check = AST::gte   ; binOp = true; break;
        case Lexer::LTE    : check = AST::lte   ; binOp = true; break;
        case Lexer::NE     : check = AST::ne    ; binOp = true; break;
    }
    if (check != AST::nil && binOp)
    {
        match(lookahead.type);
        expr = AST(check);
        e(expr);
        e(expr);
    } else if (check != AST::nil && !binOp) {
        match(lookahead.type);
        expr = AST(check);
    } else if (lookahead.type == Lexer::IDENT) {

        if (symbols.resolve(lookahead.text).sym_type == symbol::FUNC)
        {
            expr = AST(AST::fcall, lookahead.text);
            match(Lexer::IDENT);
            while (lookahead.type != Lexer::BANG)
            {
                e(expr);
            }
            match(Lexer::BANG);
        } else {
            expr = AST(AST::exprLV);
            lv(expr);
        }
    } else if (lookahead.type == Lexer::T) {
        match(Lexer::T); //true
        expr = AST(AST::t);
    } else if (lookahead.type == Lexer::F) {
        match(Lexer::F); //false
        expr = AST(AST::f);
    } else {
        expr = AST(AST::nConst, lookahead.text);
        match(Lexer::NUM);
    }
    parent.children.push_back(expr);
}

تعبير مثال لا يعمل هو + 1 + 2 + 3 4. يجب أن تحليل ast مثل هذا: + [1، + [2، + [3، 4]]، ولكن بدلا من ذلك أحصل على هذا: + [[ 1، + []

أي نصيحة حول ما أفعله خطأ؟

هل كانت مفيدة؟

المحلول

parent.children.push_back(expr) نسخ التعبير. وبالتالي، فإنه يدعو AST::AST(AST const&). وبعد خطأ في ذلك قد يسبب بالتأكيد المشكلة التي تراها. ومع ذلك، بدون رمز، لا يمكننا العثور على الأخطاء فيه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top