7 * @subpackage exception
\r
9 class Less_Exception_Chunk extends Less_Exception_Parser{
\r
12 protected $parserCurrentIndex = 0;
\r
14 protected $emitFrom = 0;
\r
16 protected $input_len;
\r
22 * @param string $input
\r
23 * @param Exception $previous Previous exception
\r
24 * @param integer $index The current parser index
\r
25 * @param Less_FileInfo|string $currentFile The file
\r
26 * @param integer $code The exception code
\r
28 public function __construct($input, Exception $previous = null, $index = null, $currentFile = null, $code = 0){
\r
30 $this->message = 'ParseError: Unexpected input'; //default message
\r
32 $this->index = $index;
\r
34 $this->currentFile = $currentFile;
\r
36 $this->input = $input;
\r
37 $this->input_len = strlen($input);
\r
40 $this->genMessage();
\r
45 * See less.js chunks()
\r
46 * We don't actually need the chunks
\r
49 protected function Chunks(){
\r
52 $lastMultiCommentEndBrace = null;
\r
53 $lastOpening = null;
\r
54 $lastMultiComment = null;
\r
57 for( $this->parserCurrentIndex = 0; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ){
\r
58 $cc = $this->CharCode($this->parserCurrentIndex);
\r
59 if ((($cc >= 97) && ($cc <= 122)) || ($cc < 34)) {
\r
60 // a-z or whitespace
\r
69 $lastParen = $this->parserCurrentIndex;
\r
75 if( $parenLevel < 0 ){
\r
76 return $this->fail("missing opening `(`");
\r
82 //if (!$parenLevel) { $this->emitChunk(); }
\r
88 $lastOpening = $this->parserCurrentIndex;
\r
95 return $this->fail("missing opening `{`");
\r
98 //if (!$level && !$parenLevel) { $this->emitChunk(); }
\r
102 if ($this->parserCurrentIndex < $this->input_len - 1) { $this->parserCurrentIndex++; continue; }
\r
103 return $this->fail("unescaped `\\`");
\r
110 $currentChunkStartIndex = $this->parserCurrentIndex;
\r
111 for ($this->parserCurrentIndex = $this->parserCurrentIndex + 1; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++) {
\r
112 $cc2 = $this->CharCode($this->parserCurrentIndex);
\r
113 if ($cc2 > 96) { continue; }
\r
114 if ($cc2 == $cc) { $matched = 1; break; }
\r
115 if ($cc2 == 92) { // \
\r
116 if ($this->parserCurrentIndex == $this->input_len - 1) {
\r
117 return $this->fail("unescaped `\\`");
\r
119 $this->parserCurrentIndex++;
\r
122 if ($matched) { continue; }
\r
123 return $this->fail("unmatched `" . chr($cc) . "`", $currentChunkStartIndex);
\r
125 // /, check for comment
\r
127 if ($parenLevel || ($this->parserCurrentIndex == $this->input_len - 1)) { continue; }
\r
128 $cc2 = $this->CharCode($this->parserCurrentIndex+1);
\r
131 for ($this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++) {
\r
132 $cc2 = $this->CharCode($this->parserCurrentIndex);
\r
133 if (($cc2 <= 13) && (($cc2 == 10) || ($cc2 == 13))) { break; }
\r
135 } else if ($cc2 == 42) {
\r
137 $lastMultiComment = $currentChunkStartIndex = $this->parserCurrentIndex;
\r
138 for ($this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len - 1; $this->parserCurrentIndex++) {
\r
139 $cc2 = $this->CharCode($this->parserCurrentIndex);
\r
140 if ($cc2 == 125) { $lastMultiCommentEndBrace = $this->parserCurrentIndex; }
\r
141 if ($cc2 != 42) { continue; }
\r
142 if ($this->CharCode($this->parserCurrentIndex+1) == 47) { break; }
\r
144 if ($this->parserCurrentIndex == $this->input_len - 1) {
\r
145 return $this->fail("missing closing `*/`", $currentChunkStartIndex);
\r
150 // *, check for unmatched */
\r
152 if (($this->parserCurrentIndex < $this->input_len - 1) && ($this->CharCode($this->parserCurrentIndex+1) == 47)) {
\r
153 return $this->fail("unmatched `/*`");
\r
159 if( $level !== 0 ){
\r
160 if( ($lastMultiComment > $lastOpening) && ($lastMultiCommentEndBrace > $lastMultiComment) ){
\r
161 return $this->fail("missing closing `}` or `*/`", $lastOpening);
\r
163 return $this->fail("missing closing `}`", $lastOpening);
\r
165 } else if ( $parenLevel !== 0 ){
\r
166 return $this->fail("missing closing `)`", $lastParen);
\r
170 //chunk didn't fail
\r
173 //$this->emitChunk(true);
\r
176 public function CharCode($pos){
\r
177 return ord($this->input[$pos]);
\r
181 public function fail( $msg, $index = null ){
\r
184 $this->index = $this->parserCurrentIndex;
\r
186 $this->index = $index;
\r
188 $this->message = 'ParseError: '.$msg;
\r
193 function emitChunk( $force = false ){
\r
194 $len = $this->parserCurrentIndex - $this->emitFrom;
\r
195 if ((($len < 512) && !$force) || !$len) {
\r
198 $chunks[] = substr($this->input, $this->emitFrom, $this->parserCurrentIndex + 1 - $this->emitFrom );
\r
199 $this->emitFrom = $this->parserCurrentIndex + 1;
\r