前言
虽然现在做的很欢快!但是因为除了语法树外没有涉及到编译原理的知识——比如递归下降、LX分析等等,也就是说等到了某一步做不下去的时候,就又要花一番功夫看编译原理了!!!
EqExpr类
前一篇给表达式设置了两种模式,五则运算模式(+ -*/^)和字符串拼接模式(“a”+“b”+“c”),并且增加了一个解释接口(interpret_str)!这次做的只有一点点的工作,仅仅是增加了一个赋值类。
1)1 + 2*3 //表达式,result = 5
2)"h"+"ell"+"0" //表达式,result = hell0
3)a = 1*(2 + 3) //赋值语句,result = 5
4)a = b = 2 //赋值语句,result = 2
式子1)的语法树为: +
/ \
1 *
/ \
2 3
式子2)的语法树为: +
/ \
+ "0"
/ \
"h" "ell"
式子3)的语法树为: =
/ \
a *
/ \
1 ()
|
+
/ \
2 3
式子4)的语法树为: =
/ \
a =
/ \
b 2
可以看出等于号也是有左结合和右结合的,运算符类解释的时候要取左右孩子节点的值进行计算或其他处理,而赋值类解释的时候要取右孩子的返回结果,将其赋值给左孩子,并且在此时确定左孩子标识符的类型,是number(double),还是string,由右孩子的返回结果决定,然后赋值类解释返回也是这个结果!
如何添加赋值节点进语法树?
- exprRoot是表达式的根节点指针——之前这个指针是root
- root是赋值语句的根节点指针——构造语法树之后,要么root=NULL,要么exprRoot为空。之后的解释语法树操作和打印语法树操作都需要分两种情况,要么root不为空表示是赋值语句,要么exprRoot不为空表示是表达式!!!
- 第一次遇到等于号(【id =】前缀 ),建立一个以root为根节点的语法树,置空exprRoot
- 第N此遇到等于号,找到最右下面的等于号节点Q,新建一个等于号节点W,把exprRoot上的内容装上W的左孩子,把W装上Q的右孩子
- 最后遇到分号时,同样找到最右下面的等于号节点Q,把exprRoot的内容装上Q的右孩子
项目演示
当输入为:a= “SOMEONESAY:”+“TECH”+“OTAKU”+“save”+“the”+“world”;
词法分析 time consumed 57 ms
中缀表达式>
name pos type
a 0 10
= 1 23
"SOMEONESAY:" 2 11
+ 3 15
"TECH" 4 11
+ 5 15
"OTAKU" 6 11
+ 7 15
"save" 8 11
+ 9 15
"the" 10 11
+ 11 15
"world" 12 11
; 13 32
全局中缀表达式 time consumed 76 ms
初始化语言环境 time consumed 0 ms
语法分析·构造语法树 time consumed 1 ms
------------------------------------------------------------
=
├── a
└── +
├── +
│ ├── +
│ │ ├── +
│ │ │ ├── +
│ │ │ │ ├── "SOMEONESAY:"
│ │ │ │ └── "TECH"
│ │ │ └── "OTAKU"
│ │ └── "save"
│ └── "the"
└── "world"
------------------------------------------------------------
语法分析·显示语法树 time consumed 54 ms
语法树是否完全==>true
result = SOMEONESAY:TECHOTAKUsavetheworld
语法分析·解释语法树 time consumed 2 ms
语言环境>
name isconst type funcPtr num str
FALSE 1 2 00000000 0 FALSE
NIL 1 0 00000000 0 NIL
TRUE 1 2 00000000 0 TRUE
a 0 4 00000000 0 SOMEONESAY:TECHOTAKUsavetheworld
显示环境信息 time consumed 111 ms
当输入为:a=b = c = 1 + 2 * 3 - 4 - 20
词法分析 time consumed 364 ms
中缀表达式>
name pos type
a 0 10
= 1 23
b 2 10
= 3 23
c 4 10
= 5 23
1 6 7
+ 7 15
2 8 7
* 9 13
3 10 7
- 11 16
4 12 7
- 13 16
20 14 7
全局中缀表达式 time consumed 709 ms
初始化语言环境 time consumed 0 ms
语法分析·构造语法树 time consumed 1 ms
------------------------------------------------------------
-
├── -
│ ├── +
│ │ ├── 1
│ │ └── *
│ │ ├── 2
│ │ └── 3
│ └── 4
└── 20
------------------------------------------------------------
语法分析·显示语法树 time consumed 17 ms
语法树是否完全==>true
result = -17
语法分析·解释语法树 time consumed 2 ms
语言环境>
name isconst type funcPtr num str
FALSE 1 2 00000000 0 FALSE
NIL 1 0 00000000 0 NIL
TRUE 1 2 00000000 0 TRUE
a 0 0 00000000 0
b 0 0 00000000 0
c 0 0 00000000 0
显示环境信息 time consumed 406 ms
上面这个演示中,result=-17是对的,但是语法树不对!!!语言环境也不对!!!
- 语言环境就是符号表,是一个std::map<std::string,SuatinID*>类型的容器!保存标识符和它的值!
消灭BUG
因为CSDN上上传的东西无法修改,也无法删除!!!所以上面的演示错了我也就留在这了!接下来修改项目中的BUG,解决上面的问题!!!
在Parser类中添加一个属性
bool firstEq_flag = true;//是否是第一次命名
修改Parser.cpp文件中的DealToken_Eq函数
void Parser::DealToken_Eq(int& _t) {
if (exprRoot == NULL&&expTmp) { //等于号左边没有标识符,或存在待处理节点
ThrowException<SuatinErrorType_NoDefined>(file_dir, file_lineNumber, file_lineContent, "[Eq] wrong expression");
expTmp = NULL;
return;
}
/*
第一种情况:
a -> =
/ \
a None
第二种情况:
= + b -> =
/ \ / \
a None a =
/ \
b None
*/
//第一次遇到等号,并且左边就是一个标识符
if (firstEq_flag) {
if (typeid(*(exprRoot->GetClassType())) == typeid(IDExpr)) {
root = new EqExpr(exprRoot, NULL);
completedName_flag = true;//成功命名
exprRoot = NULL;
firstEq_flag = false;
return;
}
}
//第N次遇到等号,找到最右的等号节点,取下,换上新小树
if (typeid(*(root->GetClassType())) == typeid(EqExpr)) {
SymbolExpr* eq = dynamic_cast<SymbolExpr*>(root);//转成SymbolExpr而不是EqExpr是为了好兼容下面的递归操作
while ( eq->GetRight()) {
SymbolExpr* eq2 = dynamic_cast<SymbolExpr*>(eq->GetRight());
eq = eq2;
}
EqExpr* tmp = new EqExpr(exprRoot, NULL);
eq->SetRight(tmp);
exprRoot = NULL;
return;
}
//。。。
ThrowException<SuatinErrorType_NoDefined>(file_dir, file_lineNumber, file_lineContent, "[Eq] wrong expression");
}
还有一个错误就是,之前的文件内容后面没有分号!!!我现在将分号作为了语句解释(又改了2333)
当输入为:a=b = c = 1 + 2 * 3 - 4 - 20;
词法分析 time consumed 205 ms
中缀表达式>
name pos type
a 0 10
= 1 23
b 2 10
= 3 23
c 4 10
= 5 23
1 6 7
+ 7 15
2 8 7
* 9 13
3 10 7
- 11 16
4 12 7
- 13 16
20 14 7
; 15 32
全局中缀表达式 time consumed 190 ms
初始化语言环境 time consumed 0 ms
语法分析·构造语法树 time consumed 1 ms
------------------------------------------------------------
=
├── a
└── =
├── b
└── =
├── c
└── -
├── -
│ ├── +
│ │ ├── 1
│ │ └── *
│ │ ├── 2
│ │ └── 3
│ └── 4
└── 20
------------------------------------------------------------
语法分析·显示语法树 time consumed 55 ms
语法树是否完全==>true
result = -17
语法分析·解释语法树 time consumed 4 ms
语言环境>
name isconst type funcPtr num str
FALSE 1 2 00000000 0 FALSE
NIL 1 0 00000000 0 NIL
TRUE 1 2 00000000 0 TRUE
a 0 3 00000000 -17
b 0 3 00000000 -17
c 0 3 00000000 -17
显示环境信息 time consumed 180 ms