소개
기사에서"PHP는 Python의 Construct 라이브러리와 유사한 기능을 구현합니다. (1) 기본 디자인 아이디어"PHP를 사용하여 바이너리 데이터를 구문 분석하는 기본 아이디어를 소개합니다
기사에서"php 구현 Python과 유사한 함수 Construct 라이브러리의 함수 (2) 어댑터 함수 구현》 어댑터 함수 구현 방법을 설명합니다.
위의 두 기사는 정적 데이터 구조를 분석합니다. 다음으로, 동적 데이터 구조 분석을 점진적으로 구현해야 합니다. 즉, 데이터 구조의 정의는 컨텍스트와 관련되어 있으며 데이터 구문 분석 중에만 실제로 결정될 수 있습니다.
추천 관련 PHP 동영상 튜토리얼: https://www.php.cn/course/list/29/type/2.html
이번에 구현하고 싶은 것은 if-else 함수입니다.
기본 아이디어
1. if 및 else 키워드를 허용하도록 어휘 분석 규칙을 수정합니다
2. if 및 else 문을 허용하도록 구문 분석 규칙을 수정합니다.
3 . 인코더를 수정하고 실행 가능한 PHP 타겟 코드를 생성합니다
주요 작업 내용은 구문 분석 규칙 파일을 수정하는 것입니다.
구현 내용
파싱할 구조 정의 파일
struct student { char name[2]; int num; if(num.value==1 ){ int age; }else{ char addr[3]; } };
if-else 함수 구현에 집중하기 위해 이번에는 하나의 구조 학생만 정의합니다. 이전 정적 구조체 정의와 가장 큰 차이점은 다음과 같은 정의입니다.
if(num.value==1 ){ int age; }else{ char addr[3]; }
파싱 과정에서 num 필드의 값이 1이면 age 필드가 정의되고, 그렇지 않으면 addr 필드가 정의됩니다.
어휘 규칙 파일은 크게 변경되지 않았습니다. if 및 else 키워드의 일치만 추가하세요.
['/^if\b/','_if' ,'i'], ['/^else\b/','_else' ,'e'],
문법 규칙 파일에서 변경해야 할 곳이 많습니다.
우선 처리를 추가하세요. 기호를 이동할 때 작동합니다. 앞서 소개한 처리 기능들은 모두 리덕션 시 호출되지만, 좀 더 복잡한 상황에서는 쉬프트 시에도 처리해야 한다.
먼저 script_parser.php
에서 시프트 처리의 기본 동작을 살펴보세요script_parser.php
中的移进处理的基本操作
//移进 private function shift($token){ //处理记号栈 $this->tokenStack= $this->tokenStack.$token[0]; if($this->debugMode){ echo I('srcline:'),$token[2],I(' shifted :'),$this->tokenStack,"\n"; } //处理语法栈,栈中元素为[记号名,记号值,起始位置,结束位置,[附加信息]] array_push($this->syntaxStack, [$token[0],$token[1],$this->tokenIndex-1,$this->tokenIndex-1,[]]); //调用规则处理中的移进处理函数 $extra=$this->rulesHandler->handleShift($token[0],$this->syntaxStack,$this->coder); //在栈中保存附加信息 $this->syntaxStack[count($this->syntaxStack)-1][TokenExtraIndex]=$extra; }
其中放置了一个钩子函数的调用
//调用规则处理中的移进处理函数 $extra=$this->rulesHandler->handleShift($token[0],$this->syntaxStack,$this->coder);
在语法规则处理的基类中定义了一个空的 handleShift
方法。
我们需要做的就是在语法规则处理类中重载 handleShift
方法。
//处理移进,返回附加信息数组 function handleShift($tokenName,$stack,$coder){ if($tokenName=='_if'){ //插入一个空行,空行所在的序号存入附加信息数组,以后可以替换为正确的内容 return [$coder->pushLine('')]; } if($tokenName=='_else'){ //插入一个空行,空行所在的序号存入附加信息数组,以后可以替换为正确的内容 return [$coder->pushLine('')]; } return []; }
从以上代码可以看出,在编译过程中,如果发生了if 或 else的移进操作,则在要生成的目标代码中插入一个空白行,并且将这个空白行的地址保存起来,在对if-else语句进行归约时用最终确定的内容替换空白行。
为什么要这么做呢?
因为 if 语句中,if 或else的块语句先完成归约,整个if语句在此之后才完成归约。而目标代码的生成是边归约边生成,所以要先为if 或else抢占一个位置。
下而是if-else的语法规则处理函数
// if {{{ function _ifStatement_0_ifStatement_else_blockStatement($stack,$coder){ //取出_else 记号中保存的空白行所在的地址,替换为正确的内容 $t1= $this->topItem($stack,2); $lineIndex=$t1[TokenExtraIndex][0]; $content='else{'; $coder->resetLine($lineIndex,$content); $coder->pushLine('}'); 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='if'.$condtionExp.'{'; $coder->resetLine($lineIndex,$content); $coder->pushLine('}'); return $this->pass($stack,3); } // if }}}
着重分析一下if语句的处理,处理函数如下所示
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='if'.$condtionExp.'{'; $coder->resetLine($lineIndex,$content); $coder->pushLine('}'); return $this->pass($stack,3); }
以下语句
$t1= $this->topItem($stack,3);
的含义是从当前语法栈的栈顶取出元素,第2个参数3 表明是从栈顶计数,取第三个元素。计数时从1开始
_ifStatement_0_if_wholeExpression_blockStatement
所包含的语法规则就是:
当栈顶出现了_if
, _wholeExpression
, _blockStatement
三个符号是,这三个符号就可以归约为 _ifStatement_0
是一个分隔串,分隔语法规则的左部与右部。
在ados脚本语言中采用了一种设计技巧,就是以产生式(语法规则)做为函数的名称,语法规则与语法规则处理函数合二为一。
这样做的好处是不用分别维护语法规则与语法规则处理函数,不用时刻保持两者的同步。
$t1= $this->topItem($stack,3);
取出的是_if 这个符号在语法栈中对应的内容。前面已经介绍过,在_if 符号移进时,插入了一个空白行,在符加信息数组中保存了这个空白行的地址。这时将其取出来。
$t2= $this->topItem($stack,2); $condtionExp=$t2[TokenValueIndex];
从 _wholeExpression
num.value
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 = '$'.$obj.'[\''.$var.'\']'; return [$exp,[]]; }
handleShift
메소드. 우리가 해야 할 일은 문법 규칙 처리 클래스의 handleShift
메서드를 오버로드하는 것뿐입니다. function _wholeExpression_0_wholeExpression_bieq_expression($stack,$coder){ return $this->biOpertors($stack,3,'==',1,$coder); } //二元操作符的通用处理函数 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,[]]; }
다음은 if-else의 구문 규칙 처리 기능입니다
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=='_if'){ //插入一个空行,空行所在的序号存入附加信息数组,以后可以替换为正确的内容 return [$coder->pushLine('')]; } if($tokenName=='_else'){ //插入一个空行,空行所在的序号存入附加信息数组,以后可以替换为正确的内容 return [$coder->pushLine('')]; } return []; } //语法规则处理函数名由规则右边部分与规则左边部分拼接而成 //语法规则定义的先后决定了归约时匹配的顺序,要根据实际的语法安排 //如果不熟悉语法,随意调整语法规则的先后次序将有可能导致语法错误 // struct list {{{ function _structList_0_structList_struct($stack,$coder){ $coder->pushBlockTail(); return ['#',[]]; } function _structList_0_struct($stack,$coder){ $coder->pushBlockTail(); return ['#',[]]; } // 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); } function _statement_0_ifStatement($stack,$coder){ return $this->pass($stack,1); } // statement }}} // if {{{ function _ifStatement_0_ifStatement_else_blockStatement($stack,$coder){ //取出_else 记号中保存的空白行所在的地址,替换为正确的内容 $t1= $this->topItem($stack,2); $lineIndex=$t1[TokenExtraIndex][0]; $content='else{'; $coder->resetLine($lineIndex,$content); $coder->pushLine('}'); 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='if'.$condtionExp.'{'; $coder->resetLine($lineIndex,$content); $coder->pushLine('}'); return $this->pass($stack,3); } // if }}} // function expression {{{ //函数表达式 function _term_0_funcTerm($stack,$coder){ $t1= $this->topItem($stack,1); $funcName=$t1[TokenValueIndex]; $paraArray=$t1[TokenExtraIndex]; $paras = implode(",", $paraArray); $exp = $funcName.'('.$paras.')'; 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,'==',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 = 'parseDouble'; $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 = 'parseFloat'; $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 = 'parseFixStr'; $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 = 'parseInt'; $coder->pushParseBody($parseFuncName,$elementName,4); return $this->pass($stack,1); } 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='('.$t1[TokenValueIndex].')'; 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 = '$'.$obj.'[\''.$var.'\']'; return [$exp,[]]; } function _term_0_iden($stack,$coder){ $t1= $this->topItem($stack,1); //未指定数据长度时将长度值设为0 $valLen = '0'; $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
if 문 처리에 중점을 둡니다. 처리 기능은 다음과 같습니다
<?php /*! * structwkr编码器, * * 45022300@qq.com * Version 0.9.0 * * Copyright 2019, Zhu Hui * Released under the MIT license */ namespace Ados; require_once __SCRIPTCORE__.'coder/base_coder.php'; require_once __STRUCT_PARSE_TEMP__.'templateReplaceFuncs.php'; class StructwkrCoder extends BaseCoder{ public function __construct($engine) { if($engine){ $this->engine = $engine; }else{ exit('the engine is not valid in StructwkrCoder construct.'); } } //编译得到的最终结果 public function codeLines(){ if(count($this->codeLines)<1){ return ''; } $script=''; 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='',$filedSize=0){ $content = makeParseBody($parseFuncName,$filedName,$filedSize); return $this->pushLine($content); } //添加一个管道处理 public function pushPipeBody($handler,$filedName=''){ $content = makePipeBody($handler,$filedName); return $this->pushLine($content); } //添加一个检查结果值的body public function pushCheckBody($filedName=''){ $content = makeCheckBody($filedName); return $this->pushLine($content); } //添加一个块解析类的tail public function pushBlockTail(){ $content = makeblockTail(); return $this->pushLine($content); } }
다음 문
<?php namespace Ados; //加载常量定义文件 require_once 'const.php'; require_once __STRUCT_PARSE_TEMP__.'templateBuidinFuncs.php'; require_once __STRUCT_PARSE_ADAPTER__.'int2str.adapter.php'; require_once __STRUCT_PARSE_ADAPTER__.'intoffset.adapter.php'; $context['pos']=0; $context['data']="\x41\x43\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['pos']+=$expRes['size']; print_r($expRes); /* $expRes = Teacher::parse($context); $context['pos']+=$expRes['size']; print_r($expRes); */ class Student{ static function parse($context,$size=0){ $valueArray=[]; $totalSize = 0; $name = parseFixStr($context,2); if($name['error']==0){ $filed = 'name'; if($filed){ $valueArray[$filed]=$name['value']; }else{ $valueArray[]=$name['value']; } $context['pos']+=$name['size']; $totalSize+= $name['size']; }else{ return ['value'=>False,'size'=>0,'error'=>$name['error'],'msg'=>$name['msg']]; } $num = parseInt($context,4); if($num['error']==0){ $filed = 'num'; if($filed){ $valueArray[$filed]=$num['value']; }else{ $valueArray[]=$num['value']; } $context['pos']+=$num['size']; $totalSize+= $num['size']; }else{ return ['value'=>False,'size'=>0,'error'=>$num['error'],'msg'=>$num['msg']]; } if($num['value']==1){ $age = parseInt($context,4); if($age['error']==0){ $filed = 'age'; if($filed){ $valueArray[$filed]=$age['value']; }else{ $valueArray[]=$age['value']; } $context['pos']+=$age['size']; $totalSize+= $age['size']; }else{ return ['value'=>False,'size'=>0,'error'=>$age['error'],'msg'=>$age['msg']]; } }else{ $addr = parseFixStr($context,3); if($addr['error']==0){ $filed = 'addr'; if($filed){ $valueArray[$filed]=$addr['value']; }else{ $valueArray[]=$addr['value']; } $context['pos']+=$addr['size']; $totalSize+= $addr['size']; }else{ return ['value'=>False,'size'=>0,'error'=>$addr['error'],'msg'=>$addr['msg']]; } } return ['value'=>$valueArray,'size'=>$totalSize,'error'=>0,'msg'=>'ok']; } }
은 현재의 맨 위에서 요소를 가져오는 것을 의미합니다. 구문 스택, 두 번째 매개변수 3은 스택의 맨 위에서 세어 세 번째 요소를 가져오는 것을 나타냅니다. 계산은 1
🎜_ifStatement_0_if_wholeExpression_blockStatement
🎜🎜포함된 구문 규칙은 다음과 같습니다.🎜🎜_if
, _wholeExpression
, < 세 개의 기호 코드>_blockStatement 즉, 이 세 기호는 문법 규칙의 왼쪽 부분과 오른쪽 부분을 구분하는 구분된 문자열인 _ifStatement_0
으로 축소될 수 있습니다. 🎜🎜ADOS 스크립팅 언어에서 채택한 설계 기법은 프로덕션(문법 규칙)을 함수 이름으로 사용하고 문법 규칙과 문법 규칙 처리 기능을 하나로 결합하는 것입니다. 🎜🎜이것의 장점은 문법 규칙과 문법 규칙 처리 기능을 별도로 유지할 필요가 없고, 두 가지를 항상 동기화 상태로 유지할 필요가 없다는 것입니다. 🎜Array ( [value] => Array ( [name] => AC [num] => 1 [age] => 2 ) [size] => 10 [error] => 0 [msg] => ok )
$context['data']="\x41\x43\x01\x00\x00\x00\x02\x00\x00\x00\x41\x42\x43\x41\x42\x01\x00\x00\x00\x41\x42\x43";
_wholeExpression
에 해당하는 구문 스택 요소에서 해당 조건식을 꺼내어 완전한 콘텐츠를 구성하고 이전 빈 줄을 바꿉니다. 🎜🎜이번에는 if 문 블록의 내용이 대상 코드에 작성되었음을 참고하세요. 🎜다음으로 if 문 블록의 끝 표시 '}'를 추가하면 괜찮습니다. 🎜🎜다음으로 속성 연산자 처리를 구현합니다. 예시에서는 🎜rrreee🎜🎜🎜구문 규칙 처리 기능은 다음과 같습니다🎜rrreee🎜예시에서 소스 코드는 다음과 같습니다. num.value , 최종 대상 코드는 $num['value']🎜즉, C와 유사한 소스 코드가 PHP 코드로 변환됩니다🎜🎜다음 단계는 비교 연산자 ==:🎜rrreee🎜를 구현하는 것입니다. 완전한 구문 규칙은 파일의 내용을 처리합니다🎜rrreee🎜다음은 향상된 인코더의 내용입니다🎜<?php /*! * structwkr编码器, * * 45022300@qq.com * Version 0.9.0 * * Copyright 2019, Zhu Hui * Released under the MIT license */ namespace Ados; require_once __SCRIPTCORE__.'coder/base_coder.php'; require_once __STRUCT_PARSE_TEMP__.'templateReplaceFuncs.php'; class StructwkrCoder extends BaseCoder{ public function __construct($engine) { if($engine){ $this->engine = $engine; }else{ exit('the engine is not valid in StructwkrCoder construct.'); } } //编译得到的最终结果 public function codeLines(){ if(count($this->codeLines)<1){ return ''; } $script=''; 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='',$filedSize=0){ $content = makeParseBody($parseFuncName,$filedName,$filedSize); return $this->pushLine($content); } //添加一个管道处理 public function pushPipeBody($handler,$filedName=''){ $content = makePipeBody($handler,$filedName); return $this->pushLine($content); } //添加一个检查结果值的body public function pushCheckBody($filedName=''){ $content = makeCheckBody($filedName); return $this->pushLine($content); } //添加一个块解析类的tail public function pushBlockTail(){ $content = makeblockTail(); return $this->pushLine($content); } }
实现结果
自动生成的测试文件如下
<?php namespace Ados; //加载常量定义文件 require_once 'const.php'; require_once __STRUCT_PARSE_TEMP__.'templateBuidinFuncs.php'; require_once __STRUCT_PARSE_ADAPTER__.'int2str.adapter.php'; require_once __STRUCT_PARSE_ADAPTER__.'intoffset.adapter.php'; $context['pos']=0; $context['data']="\x41\x43\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['pos']+=$expRes['size']; print_r($expRes); /* $expRes = Teacher::parse($context); $context['pos']+=$expRes['size']; print_r($expRes); */ class Student{ static function parse($context,$size=0){ $valueArray=[]; $totalSize = 0; $name = parseFixStr($context,2); if($name['error']==0){ $filed = 'name'; if($filed){ $valueArray[$filed]=$name['value']; }else{ $valueArray[]=$name['value']; } $context['pos']+=$name['size']; $totalSize+= $name['size']; }else{ return ['value'=>False,'size'=>0,'error'=>$name['error'],'msg'=>$name['msg']]; } $num = parseInt($context,4); if($num['error']==0){ $filed = 'num'; if($filed){ $valueArray[$filed]=$num['value']; }else{ $valueArray[]=$num['value']; } $context['pos']+=$num['size']; $totalSize+= $num['size']; }else{ return ['value'=>False,'size'=>0,'error'=>$num['error'],'msg'=>$num['msg']]; } if($num['value']==1){ $age = parseInt($context,4); if($age['error']==0){ $filed = 'age'; if($filed){ $valueArray[$filed]=$age['value']; }else{ $valueArray[]=$age['value']; } $context['pos']+=$age['size']; $totalSize+= $age['size']; }else{ return ['value'=>False,'size'=>0,'error'=>$age['error'],'msg'=>$age['msg']]; } }else{ $addr = parseFixStr($context,3); if($addr['error']==0){ $filed = 'addr'; if($filed){ $valueArray[$filed]=$addr['value']; }else{ $valueArray[]=$addr['value']; } $context['pos']+=$addr['size']; $totalSize+= $addr['size']; }else{ return ['value'=>False,'size'=>0,'error'=>$addr['error'],'msg'=>$addr['msg']]; } } return ['value'=>$valueArray,'size'=>$totalSize,'error'=>0,'msg'=>'ok']; } }
运行测试文件的结果
Array ( [value] => Array ( [name] => AC [num] => 1 [age] => 2 ) [size] => 10 [error] => 0 [msg] => ok )
对比测试数据
$context['data']="\x41\x43\x01\x00\x00\x00\x02\x00\x00\x00\x41\x42\x43\x41\x42\x01\x00\x00\x00\x41\x42\x43";
由于字段 num的值为1,所以接下来产生了一个age字段,而并没有产生addr字段。
结论:if-else功能已经实现并通过了验证。
更多相关问题请访问PHP中文网:https://www.php.cn/
위 내용은 PHP는 Python의 Construct 라이브러리와 유사한 기능을 구현합니다. (3) if-else 함수를 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!