ホームページ バックエンド開発 PHPの問題 PHPはPythonのConstructライブラリと同様の機能を実装します (4) do-while関数の実装

PHPはPythonのConstructライブラリと同様の機能を実装します (4) do-while関数の実装

Aug 19, 2019 pm 05:41 PM

はじめに

記事「PythonでContructライブラリと同様の機能をphpが実装する(1)基本的な設計の考え方」ではphpを使って行う基本的な考え方を紹介しています。バイナリデータを解析する

記事 「PythonでContructライブラリと同様の機能をphpで実装する(2)アダプター関数の実装」 でアダプター関数の実装方法を説明しています。

記事 「php で Contruct ライブラリと同様の機能を Python で実装 (3) 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";
ログイン後にコピー

2 バイトの固定長文字列 'AB' を解析した後、残りの内容が整数に解析できなくなるまで、4 セクションのループで整数値の解析を開始します。 。

結論: do-while 関数は実装され、検証されました。

その他の関連する質問については、PHP 中国語 Web サイトをご覧ください:

https://www.php.cn/

以上がPHPはPythonのConstructライブラリと同様の機能を実装します (4) do-while関数の実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

OWASPトップ10 PHP:共通の脆弱性を説明し、軽減します。 OWASPトップ10 PHP:共通の脆弱性を説明し、軽減します。 Mar 26, 2025 pm 04:13 PM

この記事では、PHPおよび緩和戦略におけるOWASPトップ10の脆弱性について説明します。重要な問題には、PHPアプリケーションを監視および保護するための推奨ツールを備えたインジェクション、認証の壊れ、XSSが含まれます。

PHP 8 JIT(Just-in-Time)コンピレーション:パフォーマンスの向上方法。 PHP 8 JIT(Just-in-Time)コンピレーション:パフォーマンスの向上方法。 Mar 25, 2025 am 10:37 AM

PHP 8のJITコンピレーションは、頻繁に実行されるコードをマシンコードにコンパイルし、重い計算でアプリケーションに利益をもたらし、実行時間を短縮することにより、パフォーマンスを向上させます。

PHPセキュアファイルアップロード:ファイル関連の脆弱性の防止。 PHPセキュアファイルアップロード:ファイル関連の脆弱性の防止。 Mar 26, 2025 pm 04:18 PM

この記事では、コードインジェクションのような脆弱性を防ぐために、PHPファイルのアップロードを確保することについて説明します。ファイルタイプの検証、セキュアストレージ、およびアプリケーションセキュリティを強化するエラー処理に焦点を当てています。

PHP暗号化:対称と非対称暗号化。 PHP暗号化:対称と非対称暗号化。 Mar 25, 2025 pm 03:12 PM

この記事では、PHPの対称的および非対称暗号化について説明し、適合性、パフォーマンス、セキュリティの違いを比較しています。対称暗号化はより速く、バルクデータに適していますが、非対称は安全なキー交換に使用されます。

PHP認証&amp;承認:安全な実装。 PHP認証&amp;承認:安全な実装。 Mar 25, 2025 pm 03:06 PM

この記事では、不正アクセスを防ぎ、ベストプラクティスの詳細、セキュリティ強化ツールの推奨を防ぐために、PHPで堅牢な認証と承認の実装について説明します。

PHP APIレート制限:実装戦略。 PHP APIレート制限:実装戦略。 Mar 26, 2025 pm 04:16 PM

この記事では、Token BucketやLeaky BucketなどのアルゴリズムやSymfony/Rate-Limiterなどのライブラリを使用するなど、PHPでAPIレート制限を実装するための戦略について説明します。また、監視、動的に調整されたレートの制限、および手をカバーします

PHP入力検証:ベストプラクティス。 PHP入力検証:ベストプラクティス。 Mar 26, 2025 pm 04:17 PM

記事では、組み込み関数、ホワイトリストアプローチ、サーバー側の検証などの手法に焦点を当てたセキュリティを強化するためのPHP入力検証のベストプラクティスについて説明します。

PHP CSRF保護:CSRF攻撃を防ぐ方法。 PHP CSRF保護:CSRF攻撃を防ぐ方法。 Mar 25, 2025 pm 03:05 PM

この記事では、CSRFトークン、同じサイトCookie、適切なセッション管理など、PHPでのCSRF攻撃を防ぐための戦略について説明します。

See all articles