<?php
/*
* @package LabCMS
* @copyright (c) 2006 Alexander Levin aka Loki (loki_angel@mail.ru)
* @support http://labcms.ru
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
class CompressionAutomate
{
	private $_cursor=-1;
	private $string='';
	private $new_string='';
	private $bWhiteSpace=false;
	private $bIsBackSlash=false;
	private $char;
	private $bBracket;
	
	function __construct($string)
	{
		$this->string=$string;
		$this->_ParseData();
	}
	
	public function GetData()
	{
		return $this->new_string;
	}
	
	private function _ParseData()
	{
		while ($this->_NextChar()!==false) {
			switch ($this->_CurrentChar())
			{
				case "'":
				case '"':
					if ($this->bIsBackSlash) $this->_PutLiteral($this->_CurrentChar());
					else $this->_ParseLiteral();
					break;
				case '/':    // Возможно, мы встретили комментарий
					if ($this->bIsBackSlash) $this->_PutLiteral('/');
					else $this->_ParseComment();
					break;
				default:
					$this->_Put($this->_CurrentChar());
			}
		}
	}
	
	private function _ParseComment ()
	{
		if ($this->_NextChar()===false) {
			// Файл зачем-то заканчивается слешем, пропишем его
			$this->_Put('/');
			return;
		}
		if ($this->_CurrentChar() == '/') {
			// Встретили однострочный комментарий, нужно пропустить входной поток до конца строки
			while ($this->_NextChar()!==false) {
				if ($this->_CurrentChar() == "\r" || $this->_CurrentChar() == "\n") return;
			}
		} elseif ($this->_CurrentChar() == '*') {
			// Встретили многострочный комментарий /*...*/
			while ($this->_NextChar()!==false) {
				if ($this->_CurrentChar() == '/' && $this->bIsStar) {
					$this->_PutLiteral(' ');
					return; // Комментарий завершен
				}
				// Встретили звездочку, возможно, она закрывает комментарий
				$this->bIsStar=($this->_CurrentChar() == '*')?true:false;
			}
		} else $this->_PutLiteral('/'.$this->_CurrentChar());
	}
	
	private function _ParseLiteral ()
	{
		$quote = $this->_CurrentChar();
		$this->_PutLiteral($quote);
		while ($this->_NextChar()!==false) {
			if ($this->_CurrentChar() == '\\') {
				// Встретили \ в строке, скопируем его и следующий символ в выходной поток
				$this->_PutLiteral($this->_CurrentChar());
				if ($this->_NextChar()===false)	return;
				// Если символ прочитан нормально, он будет скопирован в выходной поток ниже
			} elseif ($this->_CurrentChar() == $quote) {
				// Литерал закрывается, закроем его в выходном потоке и вернемся
				$this->_PutLiteral($quote);
				return;
			}
			// Все остальное просто копируем
			$this->_PutLiteral($this->_CurrentChar());
		}
	}
	
	private function _NextChar()
	{
		$this->bIsBackSlash=($this->char=='\\')?true:false;
		if (isset($this->string[++$this->_cursor])) {
			$this->char=$this->string[$this->_cursor];
			return $this->char;
		} else {
			$this->char=='';
			return false;
		}
	}
	
	private function _CurrentChar()
	{
		return $this->char;
	}
	
	private function _Put ($char)
	{
		if (in_array($char, array(" ", "\t", "\r", "\n"))) {
			$this->bWhiteSpace = true;
		} else {
			$this->bThisAlphaNum = preg_match('/[\w_$.#%-]/', $char);
			if ($char==')') $this->bBracket=true;
			else {
				if ($this->bBracket && $char!=';' && $char!=':') $this->new_string.=' ';
				$this->bBracket=false;
			}
			if ($this->bWhiteSpace && $this->bAlphaNum && $this->bThisAlphaNum) $this->new_string.=' ';
			$this->new_string.=$char;
			$this->bAlphaNum = $this->bThisAlphaNum;
			$this->bWhiteSpace = false;
		}
	}
	
	private function _PutLiteral ($char)
	{
		$this->new_string.=$char;
		$this->bWhiteSpace = false;
	}
}

