lang:自制編程語言7——改進判斷運算和邏輯運算

前言

雖然只是改進,但是還是很複雜的任務!之前寫的判斷運算和邏輯運算,其中的限制是不少!特定位置不能加括號這個毛病我不解決了,其他要解決的毛病還有
判斷式子中,兩邊返回都是數字!
邏輯式子中,兩邊都要是判斷式子!
意思我必須在簡單表達式之上,構造判斷式,然後在判斷式之上,構造邏輯式。這種限制太多了,改進後允許在簡單表達式之上,就可以構造邏輯式!!!允許簡單表達式單元爲字符串!!!


1.構造語法樹(回顧之前的內容)

簡單表達式在第二篇裏詳細介紹過,可以是五則運算(+ - * / ^)和括號構造的計算式子,也可以是字符串、字符串類型的id和加號構造的式子!

  • 賦值式、判斷式、邏輯式、簡單表達式並不是並列的關係!!!
  • 在沒有改進判斷運算和邏輯運算前,幾個式子的關係是:賦值式>邏輯式>判斷式>簡單表達式
  • 在改進了判斷運算和邏輯運算後,邏輯式和判斷式是幾乎並列的!
  • 是否是賦值式由root是否爲空決定,判斷式和邏輯式由exprType的類型決定!
  • exprType默認是五則運算,每次exprRoot爲空時遇到的第一個如果是字符串,就會將exprType置爲字符串拼接模式
  • 每次遇到>,<,>=,<=,~=,==就會將exprType置爲判斷模式
  • 每次遇到and,not,or就會將exprType置爲邏輯模式(好暈啊^_^,exprType的已經名存實亡了,具體表達式模式的判斷由幾個指針是否爲空和expr_compare_flag,expr_logic_flag區分了)
op = >|<|>=|<=|~=|==
E  = 簡單表達式
id = 變量
【根節點】 = 傳入的子語法樹的根節點


1.賦值式
E ::= id = E;
E ::= id = id = id =...= E;
1.1第一次遇到=後式子變成【賦值式】,第一個賦值節點掛在root上,exprRoot即前面的id掛在
	root左孩子上,置空exprRoot
1.2第N此遇到=,將exprRoot掛在新的賦值節點的左孩子上,將新的賦值節點掛在root語法樹
	最右的賦值節點的右孩子上,置空exprRoot
1.3遇到; 將exprRoot掛在root語法樹最右賦值節點的右孩子上,然後置空exprRoot




2.判斷式
E ::= E op E;
2.1遇到op後式子變成【判斷式】,第一個op節點掛在judgeRoot上,exprRoot即op前面的簡單表達式掛在judgeRoot
	左孩子上,置空exprRoot
2.2遇到; 將exprRoot掛在judgeRoot右孩子上,然後用exprRoot替換掉judgeRoot,置空judgeRoot





3.邏輯式
E ::= [not] E op E;
E ::= [not] E op E (and|or) E op E (and|or) E op E;
3.1遇到not後式子變成【邏輯式】,not節點掛在logicRoot上,置空exprRoot
3.2遇到and後式子變成【邏輯式】,
	>>>如果judgeRoot不爲空,執行2.2操作
	>>>如果logicRoot爲空,將exprRoot掛在新的and節點左孩子上,置空exprRoot
	>>>如果logicRoot下面是not節點,就往下取其內容,
		————如果內容爲空,將exprRoot掛在新的and節點左孩子上,將and節點掛在not,置空exprRoot
		————如果內容不爲空,對not的內容執行and_chunk操作
	>>>如果logicRoot下面不是not節點,對logicRoot執行and_chunk操作
  	

  	>and_chunk操作爲
  		————如果【根節點】是and,將exprRoot掛在【根節點】右孩子上,再將【根節點】掛在新的and節點左孩子上
  		————如果【根節點】是or,取or右孩子,
  				————如果內容爲空,將exprRoot掛在新的and節點左孩子上,再將and節點掛在【根節點】右孩子上
  				————如果內容不爲空,將exprRoot掛在【根節點】右孩子的右孩子上,再講【根節點】的右孩子掛在新的and節點左孩子上,將and節點掛在【根節點】右孩子上
  	>and_chunk結束時,置空exprRoot


3.3遇到or後式子變成【邏輯式】,
	>>>如果judgeRoot不爲空,執行2.2操作
	>>>如果logicRoot爲空,將exprRoot掛在新的的or節點左孩子上,置空exprRoot
	>>>如果logicRoot下面是not節點,就往下取其內容,
		————如果內容爲空,將exprRoot掛在新的or節點左孩子上,將or節點掛在【根節點】右孩子上,置空exprRoot
		————如果內容不爲空,對not的內容執行or_chunk操作
	>>>如果logicRoot下面不是not節點,對logicRoot執行or_chunk操作
  	

  	>or_chunk操作爲
  		————如果【根節點】是and,將exprRoot掛在【根節點】右孩子上,將【根節點】掛在新的or節點的左孩子上
  		————如果【根節點】是or,取or右孩子
  				————如果內容爲空,將exprRoot掛在or右孩子上,將【根節點】掛在新的or節點左孩子上
  				————如果內容不爲空,將exprRoot掛在or右孩子的右孩子上,將【根節點】掛在新的or節點左孩子上
  	>or_chunk結束時,置空exprRoot


3.4遇到; 接下來
	>>>如果judgeRoot不爲空,執行2.2操作
	>>>如果logicRoot下面是not節點,就往下取其內容,
		————如果內容爲空,將exprRoot掛在not的下面
		————如果內容不爲空,對not的內容執行logic_chunk操作
	>>>如果logicRoot下面不是not節點,對logicRoot執行logic_chunk操作
  	

  	>logic_chunk操作爲
  		————如果【根節點】是and,將exprRoot掛在and右邊
  		————如果【根節點】是or,or的右孩子
  				————如果內容是空,將exprRoot掛在【根節點】右孩子上
  				————如果內容不是空,將exprRoot掛在【根節點】右孩子的右孩子上


	>>>做完上面的操作後,用exprRoot替換logicRoot,置空logicRoot
	>
	>
	>>>如果root不爲空,還要執行1.3操作
	>>>如果root爲空,用root替換exprRoot,置空exprRoot
	
	

>
>
>最後上面執行完,無論是什麼語法樹,都會掛在root上,另外的exprRoot\judgeRoot\logicRoot都爲空!!!		
>之後解釋語法樹、銷燬語法樹都從root開始!!!	  		

2.確定要調用解釋接口類型(改進判斷、邏輯運算)

之前判斷運算調用的解釋接口都是interpret,都是通過值來判斷!
改進之後~= 和 == 中不止可以通過值來判斷,還可以通過字符串或是布爾來判斷!
同樣的,改進之後邏輯運算的單元就不一定是判斷式了,可以是簡單表達式,邏輯運算的三種節點的解釋接口中,也可以通過值、字符串、布爾來判斷!

想要實現這種實在不容易,我開始懷疑自己前幾天爲了這個解釋器模式寫了三種解釋接口的操作是否使項目複雜化了!我覺得是的,但是正是沒有其他好方法,才寫了三種接口——所以不能動接口,要實現上面的改進,需要讓~= == and not or這5種節點得到某種信息,得到他們該調用哪種接口的信息!

	//該判斷類或邏輯類中,單元(簡單表達式)該使用的解釋接口
	enum Unit_InterfaceType {
		Unit_InterfaceType_number,     //調用interpret接口
		Unit_InterfaceType_string,     //調用interpret_str接口
		Unit_InterfaceType_bool,       //調用interpret_bool接口
	};
解釋器的類

目前有25個類。
引入了一箇中間類,記錄左右的解釋接口類型!Not節點是單獨一個,所以解釋接口類型的標誌就讓Not類中!
在這裏插入圖片描述

爲Not\And\Or\Neq\EqEq確定解釋接口類型
  • 在創建~=/==/and/or/not節點時,要確定語法樹某個位置上的解釋接口類型
  1. 在遇到~=/==時,確定judgeRoot左孩子的解釋接口類型
  2. 在遇到and/or時,如果judgeRoot不爲空,就要爲judgeRoot右孩子確定解釋接口類型。在logicRoot語法樹中沒有確定過接口類型的分支上,確定接口類型!
  3. 遇到分號後,如果judgeRoot不爲空,爲judgeRoot右孩子確定解釋接口類型。如果logicRoot不爲空,爲logicRoot語法樹中沒有確定過接口類型的分支上,確定接口類型!如果logicRoot根節點是NOT節點,確定NOT節點的解釋接口類型!
Not\And\Or\Neq\EqEq的解釋
	bool AndExpr::interpret_bool() {
		if (left_i_type == Unit_InterfaceType_bool) {
			if (right_i_type == Unit_InterfaceType_bool) {
				return left->interpret_bool() && right->interpret_bool();
			}
			else {
				return left->interpret_bool();//右邊的爲true,所以只用判斷左邊的
			}
		}
		else {
			if (right_i_type == Unit_InterfaceType_bool) {
				return right->interpret_bool();//左邊的爲true,所以只用判斷右邊的
			}
		}
		return true;
	}
	
	bool OrExpr::interpret_bool() {
		//除了bool和bool需要考慮外,其他分支的都有一方是真,這就夠了
		if (left_i_type == Unit_InterfaceType_bool) {
			if (right_i_type == Unit_InterfaceType_bool) {
				return left->interpret_bool() || right->interpret_bool();
			}
		}
		return true;
	}

	bool NotExpr::interpret_bool() {
		if (i_type == Unit_InterfaceType_bool) {
			return !(content->interpret_bool());//not後面的內容返回真假
		}
		return false;//當not後面的內容返回字符串或數字時,其內容是true
		
	}

	bool NeqExpr::interpret_bool() {
		if (left_i_type == Unit_InterfaceType_bool) {
			if (right_i_type == Unit_InterfaceType_bool) {
				return left->interpret_bool() != right->interpret_bool();
			}
			return !(left->interpret_bool());//右邊是true,所以只用判斷左邊
		}
		else if (left_i_type == Unit_InterfaceType_number) {
			if (right_i_type == Unit_InterfaceType_bool) {
				return !(right->interpret_bool());//左邊是true,所以只用判斷右邊
			}
			else if (right_i_type == Unit_InterfaceType_number) {
				return left->interpret() != right->interpret();
			}
		}
		else if(left_i_type==Unit_InterfaceType_string){
			if (right_i_type == Unit_InterfaceType_bool) {
				return !(right->interpret_bool());//左邊是true,所以只用判斷右邊
			}
			else if (right_i_type == Unit_InterfaceType_string) {
				return left->interpret_str() != right->interpret_str();
			}
		}

		//ThrowException<SuatinErrorType_Value>("Neq interpret error");
		return true;
	}


	bool EqEqExpr::interpret_bool() {
		if (left_i_type == Unit_InterfaceType_bool) {
			if (right_i_type == Unit_InterfaceType_bool) {
				return left->interpret_bool() == right->interpret_bool();
			}
			return left->interpret_bool();//右邊是true,所以只用判斷左邊
		}
		else if (left_i_type == Unit_InterfaceType_number) {
			if (right_i_type == Unit_InterfaceType_bool) {
				return right->interpret_bool();//左邊是true,所以只用判斷右邊
			}
			else if (right_i_type == Unit_InterfaceType_number) {
				return left->interpret() == right->interpret();
			}
		}
		else if (left_i_type==Unit_InterfaceType_string) {
			if (right_i_type == Unit_InterfaceType_bool) {
				return right->interpret_bool();//左邊是true,所以只用判斷右邊
			}
			else if (right_i_type == Unit_InterfaceType_string) {
				return left->interpret_str() == right->interpret_str();
			}
		}

		//ThrowException<SuatinErrorType_Value>("EqEq interpret error");
		return false;
	}
通過傳入的小樹根節點,得到該小樹的解釋接口類型
	/*返回_node該調用的解釋接口類型
	 一個Unit返回三種數據:字符串、數字、id
	*/
	Unit_InterfaceType Parser::GetTree_InterfaceType(Expr** _node) {
		//字符串處理
		if (typeid(*((*_node)->GetClassType())) == typeid(StrExpr)) { 
			return Unit_InterfaceType_string;
		}

		//id處理
		if (typeid(*((*_node)->GetClassType())) == typeid(IDExpr)) { 
			IDExpr* tmp = dynamic_cast<IDExpr*>(*_node);
			if (tmp->GetType() == SuatinIDType_bool || tmp->GetType() == SuatinIDType_nil ) {
				return Unit_InterfaceType_bool;
			}
			else  if (tmp->GetType() == SuatinIDType_string) {
				return Unit_InterfaceType_string;
			}
			else if (tmp->GetType() == SuatinIDType_int || tmp->GetType() == SuatinIDType_number) {
				return Unit_InterfaceType_number;
			}
		}

		//Num處理
		if (typeid(*((*_node)->GetClassType())) == typeid(NumExpr)) { 
			return Unit_InterfaceType_number;
		}


		//~=/==處理
		if (typeid(*((*_node)->GetClassType())) == typeid(NeqExpr) || typeid(*((*_node)->GetClassType())) == typeid(EqEqExpr)) {
			return Unit_InterfaceType_bool;
		}

		//返回計算結果或拼接結果
		if (typeid(*((*_node)->GetClassType())) == typeid(AddExpr)) { 
			SymbolExpr* node_tmp = dynamic_cast<SymbolExpr*>(*_node);
			if (node_tmp->GetRight() == NULL) {
				ThrowException<SuatinErrorType_NoDefined>("error in GetTree_InterfacceType");
				return Unit_InterfaceType_number;
			}

			//字符串拼接處理
			if (typeid(*(node_tmp->GetLeft()->GetClassType())) == typeid(StrExpr) && typeid(*(node_tmp->GetRight()->GetClassType())) == typeid(StrExpr)) {
				return Unit_InterfaceType_string;
			}
	
			//五則運算處理,基本就是不處理,因爲默認就是使用五則運算接口
		}

		return Unit_InterfaceType_number;
	}


項目演示

項目地址在這!!!!!!!!!!!!!!!!!!!

輸入:a= b = c = not “hh” and 1 == “” or TRUE and 2 == 3 + 1;

詞法分析 time consumed 456 ms
初始化語言環境 time consumed 1 ms
語法分析·構造語法樹 time consumed 4 ms
=
├── a
└── =
    ├── b
    └── =
        ├── c
        └── not
            └── or
                ├── and
                │   ├── "hh"
                │   └── ==
                │       ├── 1
                │       └── ""
                └── and
                    ├── TRUE
                    └── ==
                        ├── 2
                        └── +
                            ├── 3
                            └── 1
語法分析·顯示語法樹 time consumed 982 ms
語法樹是否完全==>true
last result = true
語法分析·解釋語法樹 time consumed 9 ms
語言環境>
                name   isconst    type      funcPtr     flag             num   str
                 NIL    true       nil     00000000    false               0
              TEST_C    true       int     00000000     true               7
               FALSE    true      bool     00000000    false               0
              TEST_D    true      bool     00000000    false               0
                TRUE    true      bool     00000000     true               0
                   a   false      bool     00000000     true               0
                   b   false      bool     00000000     true               0
                   c   false      bool     00000000     true               0
              TEST_B    true    number     00000000     true     1.22323e+06
              TEST_A    true    string     00000000     true               0   author@Demllie
顯示環境信息 time consumed 1732 ms
釋放環境 time consumed 0 ms

項目代碼地址CSDN
https://download.csdn.net/download/weixin_41374099/12222491
項目代碼地址BDWP
鏈接:https://pan.baidu.com/s/1bJrucz35cEA5JBt_xjuIAw
提取碼:40ha

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章