C++ AST Visitor - 存储表达式值的问题

C++ AST Visitor - Problems to store value of expressions

我正在尝试编写一个简单的脚本系统(用于视频游戏),其中没有复杂的任务,只有简单的布尔检查和操作集。

我是一名学生,但我不是在学习编程,我只是作为一种爱好,所以我正在学习基础知识,最近我觉得要编写自己的解析器和解释器, 但由于这是我的第一种 AST 方法,我不明白为什么结果一直是 true 而不是 false(对于给定的表达式),也想知道它是否是我正在寻找的最佳方法。

你可以用我的源文件编译就好了。

Expression.h

#pragma once

enum OperatorType
{
    OPERATOR_EQUALS = 0,        // =
    OPERATOR_LESSER_THAN,       // <
    OPERATOR_GREATER_THAN,      // >
    OPERATOR_LESSER_OR_EQUALS,  // <=
    OPERATOR_GREATER_OR_EQUALS, // >=
    OPERATOR_UNEQUAL,           // <>
    OPERATOR_MULTIPLY,          // *
    OPERATOR_SUM,               // +
    OPERATOR_SUB,               // -
};

class Expression;
class ATSVisitor;

class ATSNode
{
public:
    virtual void accept(ATSVisitor* visitor) = 0;
};

class ATSRoot
{
public:
    Expression* expression;
};

class Expression : public ATSNode
{
public:
    ~Expression()
    {
        left = nullptr;
        right = nullptr;
    }

    virtual void accept(ATSVisitor* visitor) = 0;

    Expression* left;
    Expression* right;
};

class OperationExpression : public Expression
{
public:
    OperationExpression() : Expression(){}

    virtual void accept(ATSVisitor* visitor);

    OperatorType type;
};

class NumberExpression : public Expression
{
public:
    NumberExpression() : Expression(){ value = 0; }

    virtual void accept(ATSVisitor* visitor);

    int value;
};

class ATSVisitor
{
public:
    ATSVisitor()
    {
        Result = false;
    }

    bool evaluate(ATSRoot* root);

    void visit(OperationExpression* expression);
    void visit(NumberExpression* expression);

    bool Result;
    int number;
};

Expression.cpp

#include "expressions.h"

#include <iostream>

void OperationExpression::accept(ATSVisitor* visitor)
{
    visitor->visit(this);
}

void NumberExpression::accept(ATSVisitor* visitor)
{
    visitor->visit(this);
}

bool ATSVisitor::evaluate(ATSRoot* root)
{
    std::cout << "Evaluating ROOT" << std::endl;

    bool result = false;
    root->expression->accept(this);
    result = Result;
    return result;
}

void ATSVisitor::visit(OperationExpression* expression)
{
    std::cout << "Visitor just visited OPERATIONEXPRESSION: " << expression->type << std::endl;
    expression->left->accept(this);
    int leftValue = number;
    expression->right->accept(this);
    int rightValue = number;

    switch (expression->type)
    {
    case OPERATOR_EQUALS:
        Result = leftValue == rightValue;
    case OPERATOR_GREATER_OR_EQUALS:
        Result = leftValue >= rightValue;
    case OPERATOR_GREATER_THAN:
        Result = leftValue > rightValue;
    case OPERATOR_LESSER_OR_EQUALS:
        Result = leftValue <= rightValue;
    case OPERATOR_LESSER_THAN:
        Result = leftValue < rightValue;
    case OPERATOR_MULTIPLY:
        Result = leftValue * rightValue;
    case OPERATOR_SUB:
        Result = leftValue - rightValue;
    case OPERATOR_SUM:
        Result = leftValue + rightValue;
    case OPERATOR_UNEQUAL:
        Result = leftValue != rightValue;
    }
}

void ATSVisitor::visit(NumberExpression* expression)
{
    std::cout << "Visitor just visited NUMBEREXPRESSION: " << expression->value << std::endl;
    number = expression->value;
}

Main.cpp

#include <iostream>

#include "expressions.h"

int main(int argc, char** argv)
{
    ATSVisitor* visitor = new ATSVisitor();

    // QuestValue(100)>=10
    ATSRoot* root = new ATSRoot();
    OperationExpression* operation = new OperationExpression();
    operation->type = OPERATOR_GREATER_OR_EQUALS;
    NumberExpression* number1 = new NumberExpression();
    number1->value = 1;
    NumberExpression* number2 = new NumberExpression();
    number2->value = 10;

    operation->left = number1;
    operation->right = number2;

    root->expression = operation;

    if (!visitor->evaluate(root))
    {
        std::cout << "\nOperation evaluation FAILED!" << std::endl;
    }
    else
    {
        std::cout << "\nOperation evaluation SUCCEED!" << std::endl;
    }

    std::cout << "Finished" << std::endl;

    std::cin.get();
    delete root;
    delete number1;
    delete number2;
    delete operation;
    return EXIT_SUCCESS;
}

基本上这个带有访问者模式的 AST 应该解析如果当我的分词器解析这个脚本时:

1>=10

会不会return成功与否

您的 switch 陈述与您认为的不符。

在 C++ 中,与在 C 中一样,执行 switch 语句会导致控制流跳转到适当的 case 标签。然后它执行块的其余部分,这意味着它会执行以下 case 标签,然后执行下一个,除非它遇到 break 语句。

不用说,正常的风格是每个个案例部分以break:

结束
switch (expression->type)
    {
    case OPERATOR_EQUALS:
        Result = leftValue == rightValue;
        break;
    case OPERATOR_GREATER_OR_EQUALS:
        Result = leftValue >= rightValue;
        break;
    case OPERATOR_GREATER_THAN:
        Result = leftValue > rightValue;
        break;
    case OPERATOR_LESSER_OR_EQUALS:
        Result = leftValue <= rightValue;
        break;
    case OPERATOR_LESSER_THAN:
        Result = leftValue < rightValue;
        break;
    case OPERATOR_MULTIPLY:
        Result = leftValue * rightValue;
        break;
    case OPERATOR_SUB:
        Result = leftValue - rightValue;
        break;
    case OPERATOR_SUM:
        Result = leftValue + rightValue;
        break;
    case OPERATOR_UNEQUAL:
        Result = leftValue != rightValue;
        break;
    }

否则,不管expression->type的计算结果是什么(只要它的计算结果是其中一个标签表达式),它最终都会执行最后的语句,Result = leftValue != rightValue;.