<?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!=';') $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;
        }
	}

