public function setTheOther(self $aToken = null) { // 先解除原有配对的token关系 if ($this->aTheOther) { // nothing to do if ($this->aTheOther === $aToken) { return; } $this->aTheOther->setTheOther(null); $this->aTheOther = null; } // 设置一个配对的 闭合token if ($aToken) { $thisTokenType = $this->tokenType(); if ($this->isOpen()) { if (!self::isPair($thisTokenType, $aToken->tokenType())) { throw new ClassCompileException(null, $aToken, "遇到意外的闭合token类型,“%s”和“%s”类型不匹配。", array($thisTokenType, $aToken->tokenTypeName())); } } else { if (!self::isPair($aToken->tokenType(), $thisTokenType)) { throw new ClassCompileException(null, $aToken, "遇到意外的闭合token类型,“%s”和“%s”类型不匹配。", array($thisTokenType, $aToken->tokenTypeName())); } } $this->aTheOther = $aToken; $aToken->aTheOther = $this; } }
public function setArgListToken(ClosureToken $aTokenArgList) { if ($aTokenArgList->tokenType() != Token::T_BRACE_ROUND_OPEN or $aTokenArgList->sourceCode() != '(') { throw new ClassCompileException(null, $aTokenArgList, "参数 \$aTokenArgList 必须是一个内容为 “(” 的Token对象"); } $this->aTokenArgList = $aTokenArgList; }
/** * 设置class body 开始的大括号token */ public function setBodyToken(ClosureToken $aTokenBody) { if ($aTokenBody->tokenType() != Token::T_BRACE_OPEN or $aTokenBody->sourceCode() != '{') { throw new ClassCompileException(null, $aTokenBody, "参数 \$aTokenBody 必须是一个内容为 “{” 的Token对象"); } $this->aTokenBody = $aTokenBody; }
public function analyze(TokenPool $aObjectContainer) { $arrStacks = array(Token::T_BRACE_OPEN => new Stack(), Token::T_BRACE_SQUARE_OPEN => new Stack(), Token::T_BRACE_ROUND_OPEN => new Stack(), T_OPEN_TAG => new Stack()); $arrStacks[Token::T_BRACE_CLOSE] = $arrStacks[Token::T_BRACE_OPEN]; $arrStacks[Token::T_BRACE_SQUARE_CLOSE] = $arrStacks[Token::T_BRACE_SQUARE_OPEN]; $arrStacks[Token::T_BRACE_ROUND_CLOSE] = $arrStacks[Token::T_BRACE_ROUND_OPEN]; $arrStacks[T_OPEN_TAG_WITH_ECHO] = $arrStacks[T_OPEN_TAG]; $arrStacks[T_CLOSE_TAG] = $arrStacks[T_OPEN_TAG]; $arrStacks[T_DOLLAR_OPEN_CURLY_BRACES] = $arrStacks[Token::T_BRACE_OPEN]; $arrStacks[T_CURLY_OPEN] = $arrStacks[Token::T_BRACE_OPEN]; $aTokenIter = $aObjectContainer->iterator(); foreach ($aTokenIter as $aObject) { $nIdx = $aTokenIter->key(); $tokenType = $aObject->tokenType(); if (!in_array($tokenType, ClosureToken::openClosureTokens()) and !in_array($tokenType, ClosureToken::closeClosureTokens())) { continue; } $aNewToken = new ClosureToken($aObject); $aObjectContainer->replace($aObject, $aNewToken); if ($aNewToken->isOpen()) { $arrStacks[$tokenType]->put($aNewToken); } else { if (!($aOpenToken = $arrStacks[$tokenType]->out())) { throw new ClassCompileException(null, $aNewToken, "编译class时遇到了语法错误,闭合对象的结尾没有对应的开始:%s; on position %d", array($aNewToken->sourceCode(), $aNewToken->position())); } $aNewToken->setTheOther($aOpenToken); } } return; }
/** * 创建并织入一个用于集中调用各个advice的函数 */ protected function generateAdviceDispatchFunction(GenerateStat $aStat) { Assert::type("org\\jecat\\framework\\lang\\compile\\object\\FunctionDefine", $aStat->aExecutePoint); if (!$aStat->aExecutePoint->bodyToken()) { throw new Exception("AOP织入遇到错误:正在对一个抽象方法(%s::%s)进行织入操作。", array($aStat->aExecutePoint->belongsClass()->fullName(), $aStat->aExecutePoint->name())); } // 新建同名方法 $aOriFuncStart = $aStat->aExecutePoint->startToken(); $aOriFuncEnd = $aStat->aExecutePoint->endToken(); $aStat->aAdvicesDispatchFunc = new FunctionDefine($aStat->aExecutePoint, new Token(T_STRING, $aStat->aExecutePoint->name(), 0), null, null); // static declare if ($aStat->aExecutePoint->staticToken()) { $aStaticClareToken = new Token(T_STATIC, 'static', 0); $aStat->aAdvicesDispatchFunc->setStaticToken($aStaticClareToken); $aStat->aTokenPool->insertBefore($aOriFuncStart, $aStaticClareToken); $aStat->aTokenPool->insertBefore($aOriFuncStart, new Token(T_WHITESPACE, ' ', 0)); } // private, protected, public $aOriAccess = $aStat->aExecutePoint->accessToken(); $aNewAccess = $aOriAccess ? new Token($aOriAccess->tokenType(), $aOriAccess->sourceCode(), 0) : new Token(T_PUBLIC, 'public', 0); $aStat->aAdvicesDispatchFunc->setAccessToken($aNewAccess); $aStat->aTokenPool->insertBefore($aOriFuncStart, $aNewAccess); $aStat->aTokenPool->insertBefore($aOriFuncStart, new Token(T_WHITESPACE, ' ', 0)); // function keyword $aStat->aTokenPool->insertBefore($aOriFuncStart, $aStat->aAdvicesDispatchFunc); $aStat->aTokenPool->insertBefore($aOriFuncStart, new Token(T_WHITESPACE, ' ', 0)); // function name $aStat->aTokenPool->insertBefore($aOriFuncStart, $aStat->aAdvicesDispatchFunc->nameToken()); // 参数表 $aArgvLstStart = new ClosureToken($aStat->aExecutePoint->argListToken()); $aArgvLstEnd = new ClosureToken($aStat->aExecutePoint->argListToken()->theOther()); $aArgvLstStart->setTheOther($aArgvLstEnd); $aStat->aAdvicesDispatchFunc->setArgListToken($aArgvLstStart); $aStat->aTokenPool->insertBefore($aOriFuncStart, $aArgvLstStart); foreach ($this->cloneFunctionArgvLst($aStat->aTokenPool, $aStat->aExecutePoint) as $aToken) { $aStat->aTokenPool->insertBefore($aOriFuncStart, $aToken); } $aStat->aTokenPool->insertBefore($aOriFuncStart, $aArgvLstEnd); // 换行 $aStat->aTokenPool->insertBefore($aOriFuncStart, new Token(T_WHITESPACE, "\r\n\t")); // 函数体 $aBodyStart = new ClosureToken($aStat->aExecutePoint->bodyToken()); $aBodyEnd = new ClosureToken($aOriFuncEnd); $aBodyStart->setTheOther($aBodyEnd); $aStat->aAdvicesDispatchFunc->setBodyToken($aBodyStart); $aStat->aTokenPool->insertBefore($aOriFuncStart, $aBodyStart); $aStat->aTokenPool->insertBefore($aOriFuncStart, $aBodyEnd); // init call state 对像 $sLines = "\r\n"; $sLines .= "\t\t\$__apo_aCallState = new \\org\\jecat\\framework\\lang\\aop\\AdviceCallState() ;\r\n"; if (!$aStat->aExecutePoint->staticToken()) { $sLines .= "\t\t\$__apo_aCallState->aOriginObject = \$this ;\r\n"; } $sLines .= "\t\t\$__apo_aCallState->sOriginClass = '" . addslashes($aStat->aAdvicesDispatchFunc->belongsClass()->fullName()) . "';\r\n"; $sLines .= "\t\t\$__apo_aCallState->sOriginMethod = '" . $aStat->aAdvicesDispatchFunc->name() . "' ;\r\n"; foreach ($this->parseArgvs($aStat->aTokenPool, $aStat->aAdvicesDispatchFunc) as $sArgvName => $sArgv) { $sLines .= "\t\t\$__apo_aCallState->arrAvgvs['{$sArgvName}'] =& \${$sArgvName} ;\r\n"; } $aStat->aTokenPool->insertAfter($aBodyStart, new Token(T_WHITESPACE, $sLines)); // 换行 $aStat->aTokenPool->insertBefore($aOriFuncStart, new Token(T_WHITESPACE, "\r\n\r\n\t")); }
protected function createMethod($sFuncName, $argLstToken = null, $sAccess, $bStatic = false, TokenPool $aTokenPool, Token $aTargetToken, $sWhere = 'insertAfter') { $aFuncToken = new FunctionDefine(new Token(T_FUNCTION, 'function')); // 函数体 $aBodyStart = new ClosureToken(new Token(T_STRING, '{')); $aBodyEnd = new ClosureToken(new Token(T_STRING, '}')); $aBodyStart->setTheOther($aBodyEnd); $aTokenPool->{$sWhere}($aTargetToken, $aBodyStart); $aTokenPool->insertAfter($aBodyStart, $aBodyEnd); $aTokenPool->insertAfter($aBodyEnd, new Token(T_WHITESPACE, "\r\n")); $aTokenPool->insertBefore($aBodyStart, new Token(T_WHITESPACE, "\r\n\t")); // static if ($bStatic) { $aStaticToken = new Token(T_PRIVATE, 'static'); $aTokenPool->insertBefore($aBodyStart, $aStaticToken); $aTokenPool->insertBefore($aBodyStart, new Token(T_WHITESPACE, "\r\n\t")); $aFuncToken->setStaticToken($aStaticToken); } // access $arrAccessTokenTypes = array('private' => T_PRIVATE, 'protected' => T_PROTECTED, 'public' => T_PUBLIC); $aAccessToken = new Token($arrAccessTokenTypes[$sAccess], $sAccess); $aTokenPool->insertBefore($aBodyStart, $aAccessToken); $aTokenPool->insertBefore($aBodyStart, new Token(T_WHITESPACE, ' ')); $aFuncToken->setAccessToken($aAccessToken); // function $aTokenPool->insertBefore($aBodyStart, $aFuncToken); $aTokenPool->insertBefore($aBodyStart, new Token(T_WHITESPACE, ' ')); $aFuncToken->setBodyToken($aBodyStart); // function name $aFuncNameToken = new Token(T_STRING, $sFuncName); $aTokenPool->insertBefore($aBodyStart, $aFuncNameToken); $aFuncToken->setNameToken($aFuncNameToken); // 参数表 $aArgvLstStart = new ClosureToken(new Token(T_STRING, '(')); $aArgvLstEnd = new ClosureToken(new Token(T_STRING, ')')); $aArgvLstStart->setTheOther($aArgvLstEnd); $aTokenPool->insertBefore($aBodyStart, $aArgvLstStart); if ($argLstToken) { $aTokenPool->insertBefore($aBodyStart, new Token(T_STRING, $argLstToken)); } $aTokenPool->insertBefore($aBodyStart, $aArgvLstEnd); $aTokenPool->insertBefore($aBodyStart, new Token(T_WHITESPACE, "\r\n\t")); $aFuncToken->setArgListToken($aArgvLstStart); return $aFuncToken; }