Closed. This question needs to be more focused。它当前不接受答案。
想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
5年前关闭。
我正在使用C ++ 11为自己的编程语言构建一个解释器,作为一种业余爱好。到目前为止,我的解释器可以理解变量,表达式和打印语句。
我的解释器只是一个简单的解释器,它将源文件转换为令牌列表,并且解析器在令牌存储在C ++向量中找到令牌时仅执行令牌。
变量查询
查找变量的方式是,获取变量名的长度,然后循环遍历变量向量,仅捕获变量名长的第一个字符(无论长度多少)。当我找到变量名时,我抓住了其余的变量,变量名和值的存储方式如下:
如果变量值是字符串,则在变量值两边加上引号。
表达评估
在评估表达式时,我首先一次遍历表达式1字符,并确定该字符是数字,运算符还是方括号。然后,如果有一个多于1个字符的数字,我将数字和数字(如果是全角字符)组合在一起。
当我这样做时,然后将所有内容添加到向量中。我计算前置减号的数量是否为偶数,以便知道是否用加号或减号代替它们。
例:
然后,我遍历向量并计算左括号的数量,当我看到左括号时,将迭代器的值存储在变量中。然后,我从该迭代器开始,并获取括号内部的内容。
然后,我循环遍历括号的内部,首先进行除法,然后再次循环并进行乘法,然后进行减法,最后进行加法。然后,当求值完成时,我删除表达式那部分周围的括号,并将值存储在向量中的左括号位置。
例:
我写了一个手写的词法分析器。词法分析器按照您的期望进行操作,它将源代码作为一个字符串(每次1个字符)循环遍历,并将这些字符组合在一起以标识每个标记。
解析器仅将令牌向量中的项目与字符串(无正则表达式)进行比较。
解析器示例
令牌向量如下所示:
解析器使用字符串
我可以对自己的处事方式进行任何优化吗?我从没读过计算机科学或任何编译器课程,因此希望获得一些改进我的解释器的技巧。如果需要的话,我可以向您显示代码,尽管它很长。
然后,AST节点可以是常量,变量查找,一元运算或二进制运算:
您要使用哪种指针取决于您计划如何管理内存(在自定义池中分配了节点的裸指针对于垃圾回收方法可能是可行的,否则某些引用计数的智能指针会更好地工作)。
使用这种方法在计算表达式时,您只需执行所需的操作(无需在运行时重做解析)。
想改善这个问题吗?更新问题,使其仅通过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