Location: PHPKode > projects > Harmony preview > harmony-preview/libraries/Harmony/Script/Context.php
<?php
/**
 * Harmony
 * Copyright (c) 2008 Maxime Bouroumeau-Fuseau
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * @category Harmony
 * @package Harmony_Script
 * @author Maxime Bouroumeau-Fuseau
 * @copyright 2008 (c) Maxime Bouroumeau-Fuseau
 * @license http://www.opensource.org/licenses/mit-license.php
 * @link http://www.harmony-framework.com
 */

/** Harmony_Parser_Context */
require_once 'Harmony/Parser/Context.php';

/**
 * @category Harmony
 * @package Harmony_Script 
 * @copyright 2008 (c) Maxime Bouroumeau-Fuseau
 * @license http://www.opensource.org/licenses/mit-license.php
 */
class Harmony_Script_Context extends Harmony_Parser_Context
{
	/**
	 * Javascript code
	 * 
	 * @var string
	 */
	public $_js = '';
	
	/**
	 * Current value of the self keyword
	 * 
	 * @var string
	 */
	public static $_self = 'this';
	
	/**
	 * The last doc block
	 * 
	 * @var string
	 */
	protected $_previousDocBlock;
	
	/**
	 * Stores doc blocks
	 */
	public function tokenDocComment($text)
	{
		$this->_previousDocBlock = $text;
	}
	
	/**
	 * Transforms an echo instruction to document.write
	 */
	public function tokenEcho($text)
	{
		$this->_js .= 'document.body.write(' . $this->getParser()->enterContext('Line') . ');';
	}
	
	/**
	 * Removes the dollar sign from variables name
	 */
	public function tokenVariable($text)
	{
		$this->_js .= substr($text, 1);
	}
	
	/**
	 * Transforms php array syntax to json
	 */
	public function tokenArray($text)
	{
		$this->_js .= $this->getParser()->enterContext('Array');
	}
	
	/**
	 * Transforms -> to .
	 */
	public function tokenObjectOperator($text)
	{
		$this->_js .= '.';
	}
	
	/**
	 * Transforms :: to .
	 */
	public function tokenDoubleColon($text)
	{
		$this->_js .= '.';
	}
	
	/**
	 * Transforms . to +
	 */
	public function tokenConcat($text)
	{
		$this->_js .= '+';
	}
	
	/**
	 * Transforms === to ==
	 */
	public function tokenIsIdentical($text)
	{
		$this->_js .= '==';
	}
	
	/**
	 * Transforms !== to !=
	 */
	public function tokenIsNotIdentical($text)
	{
		$this->_js .= '!=';
	}
	
	/**
	 * Transforms &= to =
	 */
	public function tokenAndEqual($text)
	{
		$this->_js .= '=';
	}
	
	/**
	 * Transforms .= to +=
	 */
	public function tokenConcatEqual($text)
	{
		$this->_js .= '+=';
	}
	
	/**
	 * Transforms elseif to else if
	 */
	public function tokenElseif($text)
	{
		$this->_js .= 'else if';
	}
	
	/**
	 * Transform and to &&
	 */
	public function tokenLogicalAnd($text)
	{
		$this->_js .= '&&';
	}
	
	/**
	 * Transform or to ||
	 */
	public function tokenLogicalOr($text)
	{
		$this->_js .= '||';
	}
	
	/**
	 * Parses a T_STRING token
	 */
	public function tokenString($text)
	{
		if ($text == 'self') {
			/* replaced with current class name represented by self */
			$this->_js .= self::$_self;
			
		} else if ($text == 'define') {
			/* defines a javascript variable */
			$args = explode(',', $this->getParser()->enterContext('Line'));
			$this->_js .= 'var ' . trim($args[0], '"\'(') . ' = ' . rtrim($args[1], ')') . ";\n";
			
		} else if ($text == 'func_get_args') {
			/* replaces func_get_args() with arguments */
			$this->getParser()->enterContext('Line');
			$this->_js .= 'arguments;';
			
		} else if ($text == 'count') {
			/* replaces count() with .length */
			$var = trim(str_replace('$', '', $this->getParser()->enterContext('Line', array('endChar' => ')'))));
			$this->_js .= ltrim($var, '(') . '.length';
			
		} else if ($text == 'parent') {
			$line = $this->getParser()->enterContext('Line');
			$this->_js .= 'this.parent' . substr($line, strpos($line, '(')) . ';';
			
		} else if ($text == 'Callback') {
			/* special syntax for callbacks */
			$args = explode(',', ltrim(str_replace('$', '', $this->getParser()->enterContext('Line', array('endChar' => ')'))), '('));
			
			if (count($args) == 1) {
				$this->_js .= $args[0];
				return;
			}
			
			$this->_js .= trim($args[0]) . '[' . trim($args[1]) . '].bind(' . trim($args[0]) . ')';
			
		} else {
			/* any other, raw add */
			$this->_js .= $text;
		}
	}
	
	/**
	 * Transforms foreach instruction
	 */
	public function tokenForeach($text)
	{
		$this->_js .= $this->getParser()->enterContext('ForEach');
	}
	
	/**
	 * Transforms catch instruction
	 */
	public function tokenCatch($text)
	{
		$this->_js .= $this->getParser()->enterContext('Catch');
	}
	
	/**
	 * Transforms unset() to delete
	 */
	public function tokenUnset($text)
	{
		$args = explode(',', trim(trim($this->getParser()->enterContext('Line')), '()'));
		
		foreach ($args as $arg) {
			$this->_js .= 'delete ' . trim(str_replace('$', '', $arg)) . ";\n";
		}
	}
	
	/**
	 * Removes include()
	 */
	public function tokenInclude($text) 
	{
		$this->_includeFile();
	}
	
	/**
	 * Removes include_once()
	 */
	public function tokenIncludeOnce($text) 
	{
		$this->_includeFile();
	}
	
	/**
	 * Removes require()
	 */
	public function tokenRequire($text) 
	{
		$this->_includeFile();
	}
	
	/**
	 * Removes require_once()
	 */
	public function tokenRequireOnce($text) 
	{
		$this->_includeFile();
	}
	
	/**
	 * Includes an external file
	 */
	protected function _includeFile()
	{
		$filename = trim($this->getParser()->enterContext('Line'), '() \'"');
		
		if (!empty($this->_previousDocBlock)) {
			$docBlock = $this->_previousDocBlock;
			$this->_previousDocBlock = null;
			
			if (preg_match('/@harmony-ignore/', $docBlock)) {
				return;
			}
			
			if (preg_match('/@harmony-include/', $docBlock)) {
				/* finds the real path of the file using the include paths */
				foreach (explode(PATH_SEPARATOR, get_include_path()) as $path) {
					$testFilename = trim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $filename;
					if (file_exists($testFilename)) {
						$filename = $testFilename;
						break;
					}
				}
				
				/* parses the targeted file and include it in the current one */
				$script = new Harmony_Script();
				$script->load($filename);
				$this->_js .= $script->saveJavascript();
				return;
			}
		}
		
		if (substr($filename, 0, 10) == 'harmony://') {
			$filename = substr($filename, 10);
		}
		
		if (substr($filename, 0, 15) == 'Harmony/Toolkit') {
			if ($filename == 'Harmony/Toolkit.php') {
				return;
			}
			$this->_js .= 'Harmony_Toolkit.loadToolkit("' . substr($filename, 16) . '");';
			return;
		}
		
		$this->_js .= 'Harmony_Toolkit.loadAsset("' . $filename . '");';
	}
	
	/**
	 * Removes exit()
	 */
	public function tokenExit($text)
	{
		$this->getParser()->enterContext('Line');
	}
	
	/**
	 * End of file
	 */
	public function tokenEof($text)
	{
		$this->exitContext($this->_js);
	}
	
	/** references are not supported */
	public function tokenAmp($text) {}
	
	/** var keyword not supported (see Class context) */
	public function tokenVar($text) {}
	
	/* class modifiers not supported */
	public function tokenPublic($text) {}
	public function tokenProtected($text) {}
	public function tokenPrivate($text) {}
	public function tokenAbstract($text) {}
	public function tokenFinal($text) {}
	
	/* cast not supported */
	public function tokenArrayCast($text) {}
	public function tokenBoolCast($text) {}
	public function tokenDoubleCast($text) {}
	public function tokenIntCast($text) {}
	public function tokenObjectCast($text) {}
	public function tokenStringCast($text) {}
	public function tokenUnsetCast($text) {}
	
	/** @ syntax to remove errors not supported */
	public function tokenNoError($text) {}
	
	/**
	 * Catch all calls to unmatched tokens and appends them
	 * to the js code (no transformation)
	 */
	public function __call($method, $args)
	{
		$this->_js .= $args[0];
	}
}
Return current item: Harmony preview