aboutsummaryrefslogtreecommitdiff
path: root/lib/less.php/Exception/Chunk.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/less.php/Exception/Chunk.php')
-rw-r--r--lib/less.php/Exception/Chunk.php203
1 files changed, 203 insertions, 0 deletions
diff --git a/lib/less.php/Exception/Chunk.php b/lib/less.php/Exception/Chunk.php
new file mode 100644
index 0000000..b9f0a5e
--- /dev/null
+++ b/lib/less.php/Exception/Chunk.php
@@ -0,0 +1,203 @@
+<?php
+
+/**
+ * Chunk Exception
+ *
+ * @package Less
+ * @subpackage exception
+ */
+class Less_Exception_Chunk extends Less_Exception_Parser{
+
+
+ protected $parserCurrentIndex = 0;
+
+ protected $emitFrom = 0;
+
+ protected $input_len;
+
+
+ /**
+ * Constructor
+ *
+ * @param string $input
+ * @param Exception $previous Previous exception
+ * @param integer $index The current parser index
+ * @param Less_FileInfo|string $currentFile The file
+ * @param integer $code The exception code
+ */
+ public function __construct($input, Exception $previous = null, $index = null, $currentFile = null, $code = 0){
+
+ $this->message = 'ParseError: Unexpected input'; //default message
+
+ $this->index = $index;
+
+ $this->currentFile = $currentFile;
+
+ $this->input = $input;
+ $this->input_len = strlen($input);
+
+ $this->Chunks();
+ $this->genMessage();
+ }
+
+
+ /**
+ * See less.js chunks()
+ * We don't actually need the chunks
+ *
+ */
+ protected function Chunks(){
+ $level = 0;
+ $parenLevel = 0;
+ $lastMultiCommentEndBrace = null;
+ $lastOpening = null;
+ $lastMultiComment = null;
+ $lastParen = null;
+
+ for( $this->parserCurrentIndex = 0; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ){
+ $cc = $this->CharCode($this->parserCurrentIndex);
+ if ((($cc >= 97) && ($cc <= 122)) || ($cc < 34)) {
+ // a-z or whitespace
+ continue;
+ }
+
+ switch ($cc) {
+
+ // (
+ case 40:
+ $parenLevel++;
+ $lastParen = $this->parserCurrentIndex;
+ break;
+
+ // )
+ case 41:
+ $parenLevel--;
+ if( $parenLevel < 0 ){
+ return $this->fail("missing opening `(`");
+ }
+ break;
+
+ // ;
+ case 59:
+ //if (!$parenLevel) { $this->emitChunk(); }
+ break;
+
+ // {
+ case 123:
+ $level++;
+ $lastOpening = $this->parserCurrentIndex;
+ break;
+
+ // }
+ case 125:
+ $level--;
+ if( $level < 0 ){
+ return $this->fail("missing opening `{`");
+
+ }
+ //if (!$level && !$parenLevel) { $this->emitChunk(); }
+ break;
+ // \
+ case 92:
+ if ($this->parserCurrentIndex < $this->input_len - 1) { $this->parserCurrentIndex++; break; }
+ return $this->fail("unescaped `\\`");
+
+ // ", ' and `
+ case 34:
+ case 39:
+ case 96:
+ $matched = 0;
+ $currentChunkStartIndex = $this->parserCurrentIndex;
+ for ($this->parserCurrentIndex = $this->parserCurrentIndex + 1; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++) {
+ $cc2 = $this->CharCode($this->parserCurrentIndex);
+ if ($cc2 > 96) { continue; }
+ if ($cc2 == $cc) { $matched = 1; break; }
+ if ($cc2 == 92) { // \
+ if ($this->parserCurrentIndex == $this->input_len - 1) {
+ return $this->fail("unescaped `\\`");
+ }
+ $this->parserCurrentIndex++;
+ }
+ }
+ if ($matched) { break; }
+ return $this->fail("unmatched `" . chr($cc) . "`", $currentChunkStartIndex);
+
+ // /, check for comment
+ case 47:
+ if ($parenLevel || ($this->parserCurrentIndex == $this->input_len - 1)) { break; }
+ $cc2 = $this->CharCode($this->parserCurrentIndex+1);
+ if ($cc2 == 47) {
+ // //, find lnfeed
+ for ($this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++) {
+ $cc2 = $this->CharCode($this->parserCurrentIndex);
+ if (($cc2 <= 13) && (($cc2 == 10) || ($cc2 == 13))) { break; }
+ }
+ } else if ($cc2 == 42) {
+ // /*, find */
+ $lastMultiComment = $currentChunkStartIndex = $this->parserCurrentIndex;
+ for ($this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len - 1; $this->parserCurrentIndex++) {
+ $cc2 = $this->CharCode($this->parserCurrentIndex);
+ if ($cc2 == 125) { $lastMultiCommentEndBrace = $this->parserCurrentIndex; }
+ if ($cc2 != 42) { continue; }
+ if ($this->CharCode($this->parserCurrentIndex+1) == 47) { break; }
+ }
+ if ($this->parserCurrentIndex == $this->input_len - 1) {
+ return $this->fail("missing closing `*/`", $currentChunkStartIndex);
+ }
+ }
+ break;
+
+ // *, check for unmatched */
+ case 42:
+ if (($this->parserCurrentIndex < $this->input_len - 1) && ($this->CharCode($this->parserCurrentIndex+1) == 47)) {
+ return $this->fail("unmatched `/*`");
+ }
+ break;
+ }
+ }
+
+ if( $level !== 0 ){
+ if( ($lastMultiComment > $lastOpening) && ($lastMultiCommentEndBrace > $lastMultiComment) ){
+ return $this->fail("missing closing `}` or `*/`", $lastOpening);
+ } else {
+ return $this->fail("missing closing `}`", $lastOpening);
+ }
+ } else if ( $parenLevel !== 0 ){
+ return $this->fail("missing closing `)`", $lastParen);
+ }
+
+
+ //chunk didn't fail
+
+
+ //$this->emitChunk(true);
+ }
+
+ public function CharCode($pos){
+ return ord($this->input[$pos]);
+ }
+
+
+ public function fail( $msg, $index = null ){
+
+ if( !$index ){
+ $this->index = $this->parserCurrentIndex;
+ }else{
+ $this->index = $index;
+ }
+ $this->message = 'ParseError: '.$msg;
+ }
+
+
+ /*
+ function emitChunk( $force = false ){
+ $len = $this->parserCurrentIndex - $this->emitFrom;
+ if ((($len < 512) && !$force) || !$len) {
+ return;
+ }
+ $chunks[] = substr($this->input, $this->emitFrom, $this->parserCurrentIndex + 1 - $this->emitFrom );
+ $this->emitFrom = $this->parserCurrentIndex + 1;
+ }
+ */
+
+}