首頁 後端開發 PHP問題 php 實作類似pyhon中的Construct函式庫的功能(四)實作do-while功能

php 實作類似pyhon中的Construct函式庫的功能(四)實作do-while功能

Aug 19, 2019 pm 05:41 PM

引言

在文章 《php 實作類似pyhon中的Contruct函式庫的功能(一)基本設計思路》介紹了用php解析二進位資料的基本思路

在文章《php 實作類似pyhon中的Contruct函式庫的功能(二)實作適配器功能》說明如何實作適配器功能。

在文章《php 實作類似pyhon中的Contruct函式庫的功能(三)實作if-else功能》說明如何if-else功能。

這次要實現的是do-while功能。

推薦PHP影片教學:https://www.php.cn/course/list/29/type/2.html

基本想法

1,修改詞法分析規則,使其可以接受do,while關鍵字,為了引用內部變量,還需要識別$ 符號

2,修改語法分析規則,使其可以接受do,while語句

3,修改編碼器,產生可運行的php目標程式碼

4,目標程式碼的範本檔案也要做一些小的修改

其中主要的工作內容還是修改語法分析規則檔。

實作內容

準備解析的結構體定義檔

struct student
{
  char name[2];
  do{
  	int;
  }while($lastError == 0);
};
登入後複製
为了聚焦在do-while功能的实现上,这次只定义了一个结构体 student。循环语句定义如下:
登入後複製
  do{
  	int;
  }while($lastError == 0);
登入後複製

解析過程中有一個內部變數$lastError,保存每次解析的錯誤代號,如果為0則表示沒有錯誤。

下面是完整的語法規則處理文件的內容

<?php
/*!
 * structwkr的语法规则处理器
 * 45022300@qq.com
 * Version 0.9.0
 *
 * Copyright 2019, Zhu Hui
 * Released under the MIT license
 */

namespace Ados;

require_once &#39;const.php&#39;;
require_once __SCRIPTCORE__.&#39;syntax_rule/base_rules_handler.php&#39;;

class StructwkrRulesHandler extends BaseRulesHandler{

//语法分析的起始记号,归约到最后得到就是若干个结构体定义的列表
function startToken(){

	return &#39;_structList&#39;;
}


//求出放在附加信息中的数组长度
function elementSize($extraArray){
	if(count($extraArray)>0){
		return intval($extraArray[0]);
	}else{
		return 0;
	}
}

//二元操作符的通用处理函数
function biOpertors($stack,$op1Index,$op,$op2Index,$coder){

	$t1= $this->topItem($stack,$op1Index);
	$exp1=$t1[TokenValueIndex];

	$t2= $this->topItem($stack,$op2Index);
	$exp2=$t2[TokenValueIndex];

	$s=$exp1.$op.$exp2;
	return [$s,[]];
}

//处理移进,返回附加信息数组
function handleShift($tokenName,$stack,$coder){

	if($tokenName==&#39;_if&#39;){
		//插入一个空行,空行所在的序号存入附加信息数组,以后可以替换为正确的内容
		return [$coder->pushLine(&#39;&#39;)];
	}

	if($tokenName==&#39;_else&#39;){
		//插入一个空行,空行所在的序号存入附加信息数组,以后可以替换为正确的内容
		return [$coder->pushLine(&#39;&#39;)];
	}

	if($tokenName==&#39;_do&#39;){
		//插入一个空行,空行所在的序号存入附加信息数组,以后可以替换为正确的内容
		$coder->isInLoop = True;
		return [$coder->pushLine(&#39;&#39;)];
	}

	if($tokenName==&#39;_while&#39;){
		//插入一个空行,空行所在的序号存入附加信息数组,以后可以替换为正确的内容
		return [$coder->pushLine(&#39;&#39;)];
	}	

	return [];
}


//语法规则处理函数名由规则右边部分与规则左边部分拼接而成
//语法规则定义的先后决定了归约时匹配的顺序,要根据实际的语法安排
//如果不熟悉语法,随意调整语法规则的先后次序将有可能导致语法错误

// struct list  {{{

function _structList_0_structList_struct($stack,$coder){

	$coder->pushBlockTail();
	return [&#39;#&#39;,[]];
	
	
}

function _structList_0_struct($stack,$coder){	
	$coder->pushBlockTail();
	return [&#39;#&#39;,[]];
}

// struct list  }}}


// struct   {{{

function _struct_0_structName_blockStatement_semi($stack,$coder){

	$t1= $this->topItem($stack,3);
	$structName = 	$t1[TokenValueIndex];

	$t2= $this->topItem($stack,2);
	$extraArray=$t2[TokenExtraIndex];
	
	return [$structName,$extraArray];
}

// struct   }}}

// struct name     {{{

function _structName_0_strukey_iden($stack,$coder){  

	$t1= $this->topItem($stack,1);
	$structName = 	$t1[TokenValueIndex];

	$coder->pushBlockHeader($structName);	
	return $this->pass($stack,1);
}

// struct name     }}}

// blockStatement    {{{

function _blockStatement_0_lcb_statementList_rcb($stack,$coder){

	return $this->pass($stack,2);

}

// blockStatement    }}}

// statement list  {{{

function _statementList_0_statementList_statement($stack,$coder){
	
	return $this->pass($stack,1);
}

function _statementList_0_statement($stack,$coder){
	//此处0表示statementList是上一级节点,要做特殊处理
	return $this->pass($stack,1);
}

// statement list  }}}


// statement       {{{

function _statement_0_wholeExpression_semi($stack,$coder){

	$t1= $this->topItem($stack,2);
	$elementName = 	$t1[TokenValueIndex];	
	$coder->pushCheckBody($elementName);	
	return $this->pass($stack,2);
}



// statement        }}}


// if          {{{

function _statement_0_ifStatement($stack,$coder){
	
	return $this->pass($stack,1);
}

function _ifStatement_0_ifStatement_else_blockStatement($stack,$coder){	

	//取出_else 记号中保存的空白行所在的地址,替换为正确的内容
	$t1= $this->topItem($stack,2);
	$lineIndex=$t1[TokenExtraIndex][0];

	$content=&#39;else{&#39;;

	$coder->resetLine($lineIndex,$content);	

	$coder->pushLine(&#39;}&#39;);	

	return $this->pass($stack,3);
}

function _ifStatement_0_if_wholeExpression_blockStatement($stack,$coder){
	
	//取出_if 记号中保存的空白行所在的地址,替换为正确的内容
	$t1= $this->topItem($stack,3);
	$lineIndex=$t1[TokenExtraIndex][0];

	$t2= $this->topItem($stack,2);
	$condtionExp=$t2[TokenValueIndex];

	$content=&#39;if&#39;.$condtionExp.&#39;{&#39;;

	$coder->resetLine($lineIndex,$content);	

	$coder->pushLine(&#39;}&#39;);

	return $this->pass($stack,3);
}

//  if        }}}

// do while   {{{

function _statement_0_whileStatement($stack,$coder){
	
	return $this->pass($stack,1);
}

function _whileStatement_0_doBlock_whileExpression_semi($stack,$coder){
	
	$t1= $this->topItem($stack,2);
	
	$condtionExp=$t1[TokenValueIndex];

	$content=&#39;while(&#39;.$condtionExp.&#39;);&#39;;

	$coder->pushLine($content);		

	$coder->isInLoop = False;

	return $this->pass($stack,3);
}

function _whileExpression_0_whileLp_wholeExpression_rp($stack,$coder){
	
	return $this->pass($stack,2);
}

function _whileLp_0_while_lp($stack,$coder){
	
	return $this->pass($stack,2);
}

function _doBlock_0_do_blockStatement($stack,$coder){

	//取出_do 记号中保存的空白行所在的地址,替换为正确的内容
	$t1= $this->topItem($stack,2);
	$lineIndex=$t1[TokenExtraIndex][0];

	$content=&#39;do {&#39;;

	$coder->resetLine($lineIndex,$content);	

	$coder->pushLine(&#39;}&#39;);
	
	return $this->pass($stack,1);
}

//  do while    }}}


// function expression {{{


//函数表达式
function _term_0_funcTerm($stack,$coder){  

	$t1= $this->topItem($stack,1);
	$funcName=$t1[TokenValueIndex];
	$paraArray=$t1[TokenExtraIndex]; 
	$paras = implode(",", $paraArray);
	$exp = $funcName.&#39;(&#39;.$paras.&#39;)&#39;;	
	return [$exp,[]];

}

function _funcTerm_0_funcExpLp_rp($stack,$coder){  

	return $this->pass($stack,2);
}

function _funcTerm_0_funcExpLeft_rp($stack,$coder){  

	return $this->pass($stack,2);
}

function _funcExpLeft_0_funcExpLeft_comma_expression($stack,$coder){  
			
	$t1= $this->topItem($stack,3);
	$t2= $this->topItem($stack,1);

	//函数的参数列表存放在附加信息中
	$paraArray=$t1[TokenExtraIndex]; 
	array_push($paraArray, $t2[TokenValueIndex]);
	
	return [$t1[TokenValueIndex],$paraArray];
}

function _funcExpLeft_0_funcExpLp_expression($stack,$coder){  
	
	$t1= $this->topItem($stack,2);
	$t2= $this->topItem($stack,1);

	//函数的参数列表存放在附加信息中
	$paraArray=$t1[TokenExtraIndex]; 
	array_push($paraArray, $t2[TokenValueIndex]);
	
	return [$t1[TokenValueIndex],$paraArray];
}

function _funcExpLp_0_iden_lp($stack,$coder){  
	
	return $this->pass($stack,2);

}

// function expression }}}


// whole Expression  {{{

function _wholeExpression_0_wholeExpression_bieq_expression($stack,$coder){
	
	return $this->biOpertors($stack,3,&#39;==&#39;,1,$coder);
}

function _wholeExpression_0_expression($stack,$coder){
	
	return $this->pass($stack,1);
}

// whole Expression      }}}


//    Expression         {{{

//表达式可以进行管道运算
function _expression_0_expression_pipe_factor($stack,$coder){

	$t1= $this->topItem($stack,1);
	$handlerName = 	$t1[TokenValueIndex];

	$t2= $this->topItem($stack,3);
	$elementName = 	$t2[TokenValueIndex];

	$coder->pushPipeBody($handlerName,$elementName);	
	
	return $this->pass($stack,3);
}


function _expression_0_double_factor($stack,$coder){	

	$t1= $this->topItem($stack,1);
	$elementName = 	$t1[TokenValueIndex];
	$parseFuncName = &#39;parseDouble&#39;;	
	$coder->pushParseBody($parseFuncName,$elementName);	
	
	return $this->pass($stack,1);
}

function _expression_0_float_factor($stack,$coder){	

	$t1= $this->topItem($stack,1);
	$elementName = 	$t1[TokenValueIndex];
	$parseFuncName = &#39;parseFloat&#39;;	
	$coder->pushParseBody($parseFuncName,$elementName);	
	
	return $this->pass($stack,1);
}


function _expression_0_char_factor($stack,$coder){

	$t1= $this->topItem($stack,1);
	$elementName = 	$t1[TokenValueIndex];
	$size = $this->elementSize($t1[TokenExtraIndex]);
	
	$parseFuncName = &#39;parseFixStr&#39;;	
	$coder->pushParseBody($parseFuncName,$elementName,$size);		
	
	return $this->pass($stack,1);
}

function _expression_0_int_factor($stack,$coder){	

	$t1= $this->topItem($stack,1);
	$elementName = 	$t1[TokenValueIndex];
	$parseFuncName = &#39;parseInt&#39;;	
	$coder->pushParseBody($parseFuncName,$elementName,4);	
	
	return $this->pass($stack,1);
}

function _expression_0_int($stack,$coder){	

	$elementName = 	&#39;&#39;;
	$parseFuncName = &#39;parseInt&#39;;	
	$coder->pushParseBody($parseFuncName,$elementName,4);	
	
	return [&#39;&#39;,[]];
}

function _expression_0_factor($stack,$coder){
	
	return $this->pass($stack,1);
}

//   Expression         }}}

// factor       {{{

function _factor_0_term($stack,$coder){
	
	return $this->pass($stack,1);
}

//  factor        }}}

//   term    {{{

function _term_0_lp_wholeExpression_rp($stack,$coder){
	
	$t1= $this->topItem($stack,2);
	$s=&#39;(&#39;.$t1[TokenValueIndex].&#39;)&#39;;
	return [$s,[]];
}

function _term_0_term_dot_iden($stack,$coder){  
		
	$t1= $this->topItem($stack,3);
	$obj = $t1[TokenValueIndex];
	$t2= $this->topItem($stack,1);
	$var = $t2[TokenValueIndex];
	$exp = &#39;$&#39;.$obj.&#39;[\&#39;&#39;.$var.&#39;\&#39;]&#39;;

	return [$exp,[]];
}

function _term_0_dollar_iden($stack,$coder){
	$t1= $this->topItem($stack,1);	
	$exp = &#39;$&#39;.$t1[TokenValueIndex];
	return [$exp,[]];	
}

function _term_0_iden($stack,$coder){
	$t1= $this->topItem($stack,1);
	//未指定数据长度时将长度值设为0 
	$valLen = 	&#39;0&#39;;	
	$t2= $this->topItem($stack,2);
	return [$t1[TokenValueIndex],[$valLen]];	
}



function _term_0_num($stack,$coder){
	return $this->pass($stack,1);
}

function _term_0_array($stack,$coder){
	return $this->pass($stack,1);
}

//   term     }}}


// array 	  {{{

function _array_0_arrayLb_num_rb($stack,$coder){

	$t1= $this->topItem($stack,2);
	$valLen = 	$t1[TokenValueIndex];	
	
	$t2= $this->topItem($stack,3);
	//将数据长度放入附加信息 
	return [$t2[TokenValueIndex],[$valLen]];		
}

function _arrayLb_0_iden_lb($stack,$coder){  
	return $this->pass($stack,2);
}

// array 	   }}}

}// end of class
登入後複製

下面是改進後的編碼器的內容

<?php
/*!
 * structwkr编码器,
 *
 * 45022300@qq.com
 * Version 0.9.0
 *
 * Copyright 2019, Zhu Hui
 * Released under the MIT license
 */

namespace Ados;

require_once __SCRIPTCORE__.&#39;coder/base_coder.php&#39;;
require_once __STRUCT_PARSE_TEMP__.&#39;templateReplaceFuncs.php&#39;;


class StructwkrCoder extends BaseCoder{

	public function __construct($engine)
	{
		if($engine){ 
			$this->engine = $engine;
		}else{ 
			exit(&#39;the engine is not valid in StructwkrCoder construct.&#39;);
		}
		$this->isInLoop = False;
	}

	//编译得到的最终结果
	public function codeLines(){
		if(count($this->codeLines)<1){
			return &#39;&#39;;
		}
		$script=&#39;&#39;;		
		for ($i=0;$i< count($this->codeLines);$i+=1) {
			$script.=$this->codeLines[$i];
		}	
		return $script;
	}	

	//输出编译后的结果
	public function printCodeLines(){
		echo $this->codeLines();	
	}

	//添加一个块解析函数头
	public function pushLine($content){		
		array_push($this->codeLines, $content);
		$lineIndex=$this->lineIndex;
		$this->lineIndex+=1;
		return $lineIndex;		
	}

	//重置一行的内容
	public function resetLine($lineIndex,$line){

		$this->codeLines[$lineIndex]=$line;
	}

	//添加一个块解析函数头
	public function pushBlockHeader($structName){
		$structName=ucfirst($structName);
		$content = makeBlockHeader($structName);		
		return $this->pushLine($content);		
	}

	//添加一个块解析函数体
	public function pushParseBody($parseFuncName,$filedName=&#39;&#39;,$filedSize=0){
		$content = makeParseBody($parseFuncName,$filedName,$filedSize);
		return $this->pushLine($content);
	}

	//添加一个管道处理
	public function pushPipeBody($handler,$filedName=&#39;&#39;){
		$content = makePipeBody($handler,$filedName);		
		return $this->pushLine($content);
	}

	//添加一个检查结果值的body
	public function pushCheckBody($filedName=&#39;&#39;){
		if($this->isInLoop){
			$content = makeCheckBodyInLoop($filedName);
		}else{
			$content = makeCheckBody($filedName);
		}		
		return $this->pushLine($content);
	}	

	//添加一个块解析类的tail
	public function pushBlockTail(){
		$content = makeblockTail();
		return $this->pushLine($content);
	}	

}
登入後複製

實現結果

自動生成的測試檔案如下

<?php

namespace Ados;

//加载常量定义文件
require_once &#39;const.php&#39;;
require_once __STRUCT_PARSE_TEMP__.&#39;templateBuidinFuncs.php&#39;;
require_once __STRUCT_PARSE_ADAPTER__.&#39;int2str.adapter.php&#39;;
require_once __STRUCT_PARSE_ADAPTER__.&#39;intoffset.adapter.php&#39;;

$context[&#39;pos&#39;]=0;
$context[&#39;data&#39;]="\x41\x42\x01\x00\x00\x00\x02\x00\x00\x00\x41\x42\x43\x41\x42\x01\x00\x00\x00\x41\x42\x43";

$expRes = Student::parse($context);
$context[&#39;pos&#39;]+=$expRes[&#39;size&#39;];
print_r($expRes);

/*
$expRes = Teacher::parse($context);
$context[&#39;pos&#39;]+=$expRes[&#39;size&#39;];
print_r($expRes);
*/

class Student{

	static function parse($context,$size=0){
		$valueArray=[];
		$totalSize = 0;
	
		$name = parseFixStr($context,2);
		$lastError = $name[&#39;error&#39;];
	
		/*checkBodyInLoop{{*/
		if($name[&#39;error&#39;]==0){
			$filed = &#39;name&#39;;
			if($filed){
				$valueArray[$filed]=$name[&#39;value&#39;];
			}else{
				$valueArray[]=$name[&#39;value&#39;];
			}		
			$context[&#39;pos&#39;]+=$name[&#39;size&#39;];
			$totalSize+= $name[&#39;size&#39;];
		}
		/*checkBodyInLoop}}*/
		else{
			return [&#39;value&#39;=>False,&#39;size&#39;=>0,&#39;error&#39;=>$name[&#39;error&#39;],&#39;msg&#39;=>$name[&#39;msg&#39;]];
		}
	do {
		$expRes = parseInt($context,4);
		$lastError = $expRes[&#39;error&#39;];
	
		if($expRes[&#39;error&#39;]==0){
			$filed = &#39;&#39;;
			if($filed){
				$valueArray[$filed]=$expRes[&#39;value&#39;];
			}else{
				$valueArray[]=$expRes[&#39;value&#39;];
			}		
			$context[&#39;pos&#39;]+=$expRes[&#39;size&#39;];
			$totalSize+= $expRes[&#39;size&#39;];
		}
		}while($lastError==0);
		return [&#39;value&#39;=>$valueArray,&#39;size&#39;=>$totalSize,&#39;error&#39;=>0,&#39;msg&#39;=>&#39;ok&#39;];
	}
}	
登入後複製

可以看出在測試檔案中自動產生了do-while循環結構

運行測試檔案的結果

Array
(
    [value] => Array
        (
            [name] => AB
            [0] => 1
            [1] => 2
            [2] => 1094926913
            [3] => 322
            [4] => 1128415488
        )

    [size] => 22
    [error] => 0
    [msg] => ok
)
登入後複製

對比測試資料

$context[&#39;data&#39;]="\x41\x42\x01\x00\x00\x00\x02\x00\x00\x00\x41\x42\x43\x41\x42\x01\x00\x00\x00\x41\x42\x43";
登入後複製

在解析完兩個位元組的定長字串'AB'之後,開始按4個節一段循環解析整數值,直到剩下的內容無法解析為一個整數為止。

結論:do-while功能已經實現並通過了驗證。

更多相關問題請上PHP中文網:https://www.php.cn/

#

以上是php 實作類似pyhon中的Construct函式庫的功能(四)實作do-while功能的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)