Closed. This question needs to be more focused。它当前不接受答案。
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
                        
                        5年前关闭。
                                                                                            
                
        
我正在使用C ++ 11为自己的编程语言构建一个解释器,作为一种业余爱好。到目前为止,我的解释器可以理解变量,表达式和打印语句。

我的解释器只是一个简单的解释器,它将源文件转换为令牌列表,并且解析器在令牌存储在C ++向量中找到令牌时仅执行令牌。

变量查询

查找变量的方式是,获取变量名的长度,然后循环遍历变量向量,仅捕获变量名长的第一个字符(无论长度多少)。当我找到变量名时,我抓住了其余的变量,变量名和值的存储方式如下:

variable_name:variable_value


如果变量值是字符串,则在变量值两边加上引号。

表达评估

在评估表达式时,我首先一次遍历表达式1字符,并确定该字符是数字,运算符还是方括号。然后,如果有一个多于1个字符的数字,我将数字和数字(如果是全角字符)组合在一起。

当我这样做时,然后将所有内容添加到向量中。我计算前置减号的数量是否为偶数,以便知道是否用加号或减号代替它们。

例:

------------10  ->  becomes +10
because there are 12 minuses before the 10


然后,我遍历向量并计算左括号的数量,当我看到左括号时,将迭代器的值存储在变量中。然后,我从该迭代器开始,并获取括号内部的内容。

然后,我循环遍历括号的内部,首先进行除法,然后再次循环并进行乘法,然后进行减法,最后进行加法。然后,当求值完成时,我删除表达式那部分周围的括号,并将值存储在向量中的左​​括号位置。

例:

(10 + -(2 * 4))
(10 + -(8))
(10 + - 8)
(10 - 8)
(2)


我写了一个手写的词法分析器。词法分析器按照您的期望进行操作,它将源代码作为一个字符串(每次1个字符)循环遍历,并将这些字符组合在一起以标识每个标记。

解析器仅将令牌向量中的项目与字符串(无正则表达式)进行比较。

解析器示例

令牌向量如下所示:

[0] print
[1] string:"Hello World"
[2] sc


解析器使用字符串print string sc标识令牌顺序背后的含义。

我可以对自己的处事方式进行任何优化吗?我从没读过计算机科学或任何编译器课程,因此希望获得一些改进我的解释器的技巧。如果需要的话,我可以向您显示代码,尽管它很长。

最佳答案

可能获得的最大加速是(假设使用动态类型的语言):


创建一个通用值对象,该对象可以存储要用您的语言处理的数字,字符串,布尔值和其他值类型
将表达式解析为AST


例如

struct Value {
    int type;
    enum {
       NUMBER = 1,
       STRING = 2
    };
    double doubleValue;         // Value in case it's a number
    std::string stringValue;    // Value in case it's a string

    Value(double x) : type(NUMBER), doubleValue(x) { }
    Value(const std::string& x) : type(STRING), stringValue(x) { }
};


然后,AST节点可以是常量,变量查找,一元运算或二进制运算:

struct ASTNode {
    virtual Value compute() = 0;
    virtual ~ASTNode() {}
};

struct ConstantNode : ASTNode {
    Value x;
    ConstantNode(Value x) : x(x) {}
    virtual Value compute() { return x; }
};

struct VariableNode : ASTNode {
    std::string name;
    VariableNode(const std::string& name) : name(name) {}
    virtual value compute() { return lookup(name); }
};

struct AdditionNode : ASTNode {
    ASTNode *a, *b;
    AdditionNode(ASTNode *a, ASTNode *b) : a(a), b(b) {}
    virtual Value compute() {
        Value av = a->compute();
        Value bv = b->compute();
        if (av.type == Value::NUMBER && bv.type == Value::NUMBER) {
            return av.doubleValue + bv.doubleValue;
        } else if (av.type == Value::STRING && bv.type == Value::STRING) {
            return av.stringValue + bv.stringValue;
        } else {
            throw std::runtime_error("Type mismatch");
        }
    }
};


您要使用哪种指针取决于您计划如何管理内存(在自定义池中分配了节点的裸指针对于垃圾回收方法可能是可行的,否则某些引用计数的智能指针会更好地工作)。

使用这种方法在计算表达式时,您只需执行所需的操作(无需在运行时重做解析)。

关于c++ - 解释器的最佳选择,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24840214/

10-13 03:33