lang:自制编程语言4——语法树引入赋值

前言

虽然现在做的很欢快!但是因为除了语法树外没有涉及到编译原理的知识——比如递归下降、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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章