Passed
Push — EXTRACT_CLASSES ( 0382f2...c25e41 )
by Rafael
52:18
created
Dolibarr/Code/Contrat/Classes/ContratLigne.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
         return $this->LibStatut($this->statut, $mode, ((!empty($this->date_end)) ? ($this->date_end < dol_now() ? 1 : 0) : -1));
261 261
     }
262 262
 
263
-	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
263
+    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
264 264
     /**
265 265
      *  Return label of a contract line status
266 266
      *
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
      */
274 274
     public static function LibStatut($status, $mode, $expired = -1, $moreatt = '', $morelabel = '')
275 275
     {
276
-		// phpcs:enable
276
+        // phpcs:enable
277 277
         global $langs;
278 278
         $langs->load("contracts");
279 279
 
@@ -709,7 +709,7 @@  discard block
 block discarded – undo
709 709
     }
710 710
 
711 711
 
712
-	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
712
+    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
713 713
     /**
714 714
      *  Update in database the fields total_xxx of lines
715 715
      *  Used by migration process
@@ -718,7 +718,7 @@  discard block
 block discarded – undo
718 718
      */
719 719
     public function update_total()
720 720
     {
721
-		// phpcs:enable
721
+        // phpcs:enable
722 722
         $this->db->begin();
723 723
 
724 724
         // Mise a jour ligne en base
@@ -836,7 +836,7 @@  discard block
 block discarded – undo
836 836
         }
837 837
     }
838 838
 
839
-	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
839
+    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
840 840
     /**
841 841
      *  Activate a contract line
842 842
      *
@@ -848,7 +848,7 @@  discard block
 block discarded – undo
848 848
      */
849 849
     public function active_line($user, $date, $date_end = '', $comment = '')
850 850
     {
851
-		// phpcs:enable
851
+        // phpcs:enable
852 852
         $error = 0;
853 853
 
854 854
         $this->db->begin();
@@ -894,7 +894,7 @@  discard block
 block discarded – undo
894 894
         }
895 895
     }
896 896
 
897
-	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
897
+    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
898 898
     /**
899 899
      *  Close a contract line
900 900
      *
@@ -906,7 +906,7 @@  discard block
 block discarded – undo
906 906
      */
907 907
     public function close_line($user, $date_end_real, $comment = '', $notrigger = 0)
908 908
     {
909
-		// phpcs:enable
909
+        // phpcs:enable
910 910
         $this->date_cloture = $date_end_real;
911 911
         $this->date_end_real = $date_end_real;
912 912
         $this->user_closing_id = $user->id;
Please login to merge, or discard this patch.
Dolibarr/Code/Core/Classes/lessc_parser.php 2 patches
Indentation   +1646 added lines, -1646 removed lines patch added patch discarded remove patch
@@ -61,1650 +61,1650 @@
 block discarded – undo
61 61
 // syntax tree
62 62
 class lessc_parser
63 63
 {
64
-	protected static $nextBlockId = 0; // used to uniquely identify blocks
65
-
66
-	protected static $precedence = array(
67
-		'=<' => 0,
68
-		'>=' => 0,
69
-		'=' => 0,
70
-		'<' => 0,
71
-		'>' => 0,
72
-
73
-		'+' => 1,
74
-		'-' => 1,
75
-		'*' => 2,
76
-		'/' => 2,
77
-		'%' => 2,
78
-	);
79
-
80
-	protected static $whitePattern;
81
-	protected static $commentMulti;
82
-
83
-	protected static $commentSingle = "//";
84
-	protected static $commentMultiLeft = "/*";
85
-	protected static $commentMultiRight = "*/";
86
-
87
-	// regex string to match any of the operators
88
-	protected static $operatorString;
89
-
90
-	// these properties will supress division unless it's inside parenthases
91
-	protected static $supressDivisionProps =
92
-		array('/border-radius$/i', '/^font$/i');
93
-
94
-	protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document", "viewport", "-moz-viewport", "-o-viewport", "-ms-viewport");
95
-	protected $lineDirectives = array("charset");
96
-
97
-	/**
98
-	 * if we are in parens we can be more liberal with whitespace around
99
-	 * operators because it must evaluate to a single value and thus is less
100
-	 * ambiguous.
101
-	 *
102
-	 * Consider:
103
-	 *     property1: 10 -5; // is two numbers, 10 and -5
104
-	 *     property2: (10 -5); // should evaluate to 5
105
-	 */
106
-	protected $inParens = false;
107
-
108
-	// caches preg escaped literals
109
-	protected static $literalCache = array();
110
-
111
-	public $env;
112
-	public $buffer;
113
-	public $count;
114
-	public $line;
115
-	public $eatWhiteDefault;
116
-	public $lessc;
117
-	public $sourceName;
118
-	public $writeComments;
119
-	public $seenComments;
120
-	public $currentProperty;
121
-	public $inExp;
122
-
123
-
124
-	public function __construct($lessc, $sourceName = null)
125
-	{
126
-		$this->eatWhiteDefault = true;
127
-		// reference to less needed for vPrefix, mPrefix, and parentSelector
128
-		$this->lessc = $lessc;
129
-
130
-		$this->sourceName = $sourceName; // name used for error messages
131
-
132
-		$this->writeComments = false;
133
-
134
-		if (!self::$operatorString) {
135
-			self::$operatorString =
136
-				'('.implode('|', array_map(
137
-					array('lessc', 'preg_quote'),
138
-					array_keys(self::$precedence)
139
-				)).')';
140
-
141
-			$commentSingle = Lessc::preg_quote(self::$commentSingle);
142
-			$commentMultiLeft = Lessc::preg_quote(self::$commentMultiLeft);
143
-			$commentMultiRight = Lessc::preg_quote(self::$commentMultiRight);
144
-
145
-			self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
146
-			self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
147
-		}
148
-	}
149
-
150
-	/**
151
-	 * Parse a string
152
-	 *
153
-	 * @param       string  $buffer         String to parse
154
-	 * @throws exception
155
-	 * @return NULL|stdclass
156
-	 */
157
-	public function parse($buffer)
158
-	{
159
-		$this->count = 0;
160
-		$this->line = 1;
161
-
162
-		$this->env = null; // block stack
163
-		$this->buffer = $this->writeComments ? $buffer : $this->removeComments($buffer);
164
-		$this->pushSpecialBlock("root");
165
-		$this->eatWhiteDefault = true;
166
-		$this->seenComments = array();
167
-
168
-		// trim whitespace on head
169
-		// if (preg_match('/^\s+/', $this->buffer, $m)) {
170
-		//  $this->line += substr_count($m[0], "\n");
171
-		//  $this->buffer = ltrim($this->buffer);
172
-		// }
173
-		$this->whitespace();
174
-
175
-		// parse the entire file
176
-		while (false !== $this->parseChunk());
177
-
178
-		if ($this->count != strlen($this->buffer)) {
179
-			$this->throwError('parse error count '.$this->count.' != len buffer '.strlen($this->buffer));
180
-
181
-		}
182
-
183
-		// TODO report where the block was opened
184
-		if (!property_exists($this->env, 'parent') || !is_null($this->env->parent)) {
185
-			throw new exception('parse error: unclosed block');
186
-		}
187
-
188
-		return $this->env;
189
-	}
190
-
191
-	/**
192
-	 * Parse a single chunk off the head of the buffer and append it to the
193
-	 * current parse environment.
194
-	 * Returns false when the buffer is empty, or when there is an error.
195
-	 *
196
-	 * This function is called repeatedly until the entire document is
197
-	 * parsed.
198
-	 *
199
-	 * This parser is most similar to a recursive descent parser. Single
200
-	 * functions represent discrete grammatical rules for the language, and
201
-	 * they are able to capture the text that represents those rules.
202
-	 *
203
-	 * Consider the function Lessc::keyword(). (all parse functions are
204
-	 * structured the same)
205
-	 *
206
-	 * The function takes a single reference argument. When calling the
207
-	 * function it will attempt to match a keyword on the head of the buffer.
208
-	 * If it is successful, it will place the keyword in the referenced
209
-	 * argument, advance the position in the buffer, and return true. If it
210
-	 * fails then it won't advance the buffer and it will return false.
211
-	 *
212
-	 * All of these parse functions are powered by Lessc::match(), which behaves
213
-	 * the same way, but takes a literal regular expression. Sometimes it is
214
-	 * more convenient to use match instead of creating a new function.
215
-	 *
216
-	 * Because of the format of the functions, to parse an entire string of
217
-	 * grammatical rules, you can chain them together using &&.
218
-	 *
219
-	 * But, if some of the rules in the chain succeed before one fails, then
220
-	 * the buffer position will be left at an invalid state. In order to
221
-	 * avoid this, Lessc::seek() is used to remember and set buffer positions.
222
-	 *
223
-	 * Before parsing a chain, use $s = $this->seek() to remember the current
224
-	 * position into $s. Then if a chain fails, use $this->seek($s) to
225
-	 * go back where we started.
226
-	 */
227
-	protected function parseChunk()
228
-	{
229
-		if (empty($this->buffer)) {
230
-			return false;
231
-		}
232
-		$s = $this->seek();
233
-
234
-		if ($this->whitespace()) {
235
-			return true;
236
-		}
237
-
238
-		$key = null;
239
-		$value = null;
240
-		$mediaQueries = null;
241
-		$dirName = null;
242
-		$dirValue = null;
243
-		$importValue = null;
244
-		$guards = null;
245
-		$tag = null;
246
-		$args = null;
247
-		$isVararg = null;
248
-		$argv = null;
249
-		$suffix = null;
250
-		$var = null;
251
-		$tags = null;
252
-
253
-		// setting a property
254
-		if ($this->keyword($key) && $this->assign() &&
255
-			$this->propertyValue($value, $key) && $this->end()
256
-		) {
257
-			$this->append(array('assign', $key, $value), $s);
258
-			return true;
259
-		} else {
260
-			$this->seek($s);
261
-		}
262
-
263
-
264
-		// look for special css blocks
265
-		if ($this->literal('@', false)) {
266
-			$this->count--;
267
-
268
-			// media
269
-			if ($this->literal('@media')) {
270
-				if ($this->mediaQueryList($mediaQueries)
271
-					&& $this->literal('{')
272
-				) {
273
-					$media = $this->pushSpecialBlock("media");
274
-					$media->queries = is_null($mediaQueries) ? array() : $mediaQueries;
275
-					return true;
276
-				} else {
277
-					$this->seek($s);
278
-					return false;
279
-				}
280
-			}
281
-
282
-			if ($this->literal("@", false) && $this->keyword($dirName)) {
283
-				if ($this->isDirective($dirName, $this->blockDirectives)) {
284
-					if ($this->openString("{", $dirValue, null, array(";")) &&
285
-						$this->literal("{")
286
-					) {
287
-						$dir = $this->pushSpecialBlock("directive");
288
-						$dir->name = $dirName;
289
-						if (isset($dirValue)) {
290
-							$dir->value = $dirValue;
291
-						}
292
-						return true;
293
-					}
294
-				} elseif ($this->isDirective($dirName, $this->lineDirectives)) {
295
-					if ($this->propertyValue($dirValue) && $this->end()) {
296
-						$this->append(array("directive", $dirName, $dirValue));
297
-						return true;
298
-					}
299
-				}
300
-			}
301
-
302
-			$this->seek($s);
303
-		}
304
-
305
-		// setting a variable
306
-		if ($this->variable($var) && $this->assign() &&
307
-			$this->propertyValue($value) && $this->end()
308
-		) {
309
-			$this->append(array('assign', $var, $value), $s);
310
-			return true;
311
-		} else {
312
-			$this->seek($s);
313
-		}
314
-
315
-		if ($this->import($importValue)) {
316
-			$this->append($importValue, $s);
317
-			return true;
318
-		}
319
-
320
-		// opening parametric mixin
321
-		if ($this->tag($tag, true) && $this->argumentDef($args, $isVararg) &&
322
-			$this->guards($guards) &&
323
-			$this->literal('{')
324
-		) {
325
-			$block = $this->pushBlock($this->fixTags(array($tag)));
326
-			$block->args = $args;
327
-			$block->isVararg = $isVararg;
328
-			if (!empty($guards)) {
329
-				$block->guards = $guards;
330
-			}
331
-			return true;
332
-		} else {
333
-			$this->seek($s);
334
-		}
335
-
336
-		// opening a simple block
337
-		if ($this->tags($tags) && $this->literal('{', false)) {
338
-			$tags = $this->fixTags($tags);
339
-			$this->pushBlock($tags);
340
-			return true;
341
-		} else {
342
-			$this->seek($s);
343
-		}
344
-
345
-		// closing a block
346
-		if ($this->literal('}', false)) {
347
-			try {
348
-				$block = $this->pop();
349
-			} catch (exception $e) {
350
-				$this->seek($s);
351
-				$this->throwError($e->getMessage());
352
-			}
353
-
354
-			$hidden = false;
355
-			if (is_null($block->type)) {
356
-				$hidden = true;
357
-				if (!isset($block->args)) {
358
-					foreach ($block->tags as $tag) {
359
-						if (!is_string($tag) || $tag[0] != $this->lessc->mPrefix) {
360
-							$hidden = false;
361
-							break;
362
-						}
363
-					}
364
-				}
365
-
366
-				foreach ($block->tags as $tag) {
367
-					if (is_string($tag)) {
368
-						$this->env->children[$tag][] = $block;
369
-					}
370
-				}
371
-			}
372
-
373
-			if (!$hidden) {
374
-				$this->append(array('block', $block), $s);
375
-			}
376
-
377
-			// this is done here so comments aren't bundled into he block that
378
-			// was just closed
379
-			$this->whitespace();
380
-			return true;
381
-		}
382
-
383
-		// mixin
384
-		if ($this->mixinTags($tags) &&
385
-			$this->argumentDef($argv, $isVararg) &&
386
-			$this->keyword($suffix)  && $this->end()
387
-		) {
388
-			$tags = $this->fixTags($tags);
389
-			$this->append(array('mixin', $tags, $argv, $suffix), $s);
390
-			return true;
391
-		} else {
392
-			$this->seek($s);
393
-		}
394
-
395
-		// spare ;
396
-		if ($this->literal(';')) {
397
-			return true;
398
-		}
399
-
400
-		return false; // got nothing, throw error
401
-	}
402
-
403
-	protected function isDirective($dirname, $directives)
404
-	{
405
-		// TODO: cache pattern in parser
406
-		$pattern = implode(
407
-			"|",
408
-			array_map(array("lessc", "preg_quote"), $directives)
409
-		);
410
-		$pattern = '/^(-[a-z-]+-)?('.$pattern.')$/i';
411
-
412
-		return preg_match($pattern, $dirname);
413
-	}
414
-
415
-	protected function fixTags($tags)
416
-	{
417
-		// move @ tags out of variable namespace
418
-		foreach ($tags as &$tag) {
419
-			if ($tag[0] == $this->lessc->vPrefix) {
420
-				$tag[0] = $this->lessc->mPrefix;
421
-			}
422
-		}
423
-		return $tags;
424
-	}
425
-
426
-	// a list of expressions
427
-	protected function expressionList(&$exps)
428
-	{
429
-		$exp = null;
430
-
431
-		$values = array();
432
-
433
-		while ($this->expression($exp)) {
434
-			$values[] = $exp;
435
-		}
436
-
437
-		if (count($values) == 0) {
438
-			return false;
439
-		}
440
-
441
-		$exps = Lessc::compressList($values, ' ');
442
-		return true;
443
-	}
444
-
445
-	/**
446
-	 * Attempt to consume an expression.
447
-	 * @link http://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudo-code
448
-	 */
449
-	protected function expression(&$out)
450
-	{
451
-		$lhs = null;
452
-		$rhs = null;
453
-
454
-		if ($this->value($lhs)) {
455
-			$out = $this->expHelper($lhs, 0);
456
-
457
-			// look for / shorthand
458
-			if (!empty($this->env->supressedDivision)) {
459
-				unset($this->env->supressedDivision);
460
-				$s = $this->seek();
461
-				if ($this->literal("/") && $this->value($rhs)) {
462
-					$out = array("list", "",
463
-						array($out, array("keyword", "/"), $rhs));
464
-				} else {
465
-					$this->seek($s);
466
-				}
467
-			}
468
-
469
-			return true;
470
-		}
471
-		return false;
472
-	}
473
-
474
-	/**
475
-	 * recursively parse infix equation with $lhs at precedence $minP
476
-	 */
477
-	protected function expHelper($lhs, $minP)
478
-	{
479
-		$next = null;
480
-		$rhs = null;
481
-
482
-		$this->inExp = true;
483
-		$ss = $this->seek();
484
-
485
-		while (true) {
486
-			$whiteBefore = isset($this->buffer[$this->count - 1]) &&
487
-				ctype_space($this->buffer[$this->count - 1]);
488
-
489
-			// If there is whitespace before the operator, then we require
490
-			// whitespace after the operator for it to be an expression
491
-			$needWhite = $whiteBefore && !$this->inParens;
492
-
493
-			$m = array();
494
-			if ($this->match(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) {
495
-				if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) {
496
-					foreach (self::$supressDivisionProps as $pattern) {
497
-						if (preg_match($pattern, $this->env->currentProperty)) {
498
-							$this->env->supressedDivision = true;
499
-							break 2;
500
-						}
501
-					}
502
-				}
503
-
504
-
505
-				$whiteAfter = isset($this->buffer[$this->count - 1]) &&
506
-					ctype_space($this->buffer[$this->count - 1]);
507
-
508
-				if (!$this->value($rhs)) {
509
-					break;
510
-				}
511
-
512
-				// peek for next operator to see what to do with rhs
513
-				if ($this->peek(self::$operatorString, $next) && self::$precedence[$next[1]] > self::$precedence[$m[1]]) {
514
-					$rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
515
-				}
516
-
517
-				$lhs = array('expression', $m[1], $lhs, $rhs, $whiteBefore, $whiteAfter);
518
-				$ss = $this->seek();
519
-
520
-				continue;
521
-			}
522
-
523
-			break;
524
-		}
525
-
526
-		$this->seek($ss);
527
-
528
-		return $lhs;
529
-	}
530
-
531
-	// consume a list of values for a property
532
-	public function propertyValue(&$value, $keyName = null)
533
-	{
534
-		$v = null;
535
-		$values = array();
536
-
537
-		if ($keyName !== null) {
538
-			$this->env->currentProperty = $keyName;
539
-		}
540
-
541
-		$s = null;
542
-		while ($this->expressionList($v)) {
543
-			$values[] = $v;
544
-			$s = $this->seek();
545
-			if (!$this->literal(',')) {
546
-				break;
547
-			}
548
-		}
549
-
550
-		if ($s) {
551
-			$this->seek($s);
552
-		}
553
-
554
-		if ($keyName !== null) {
555
-			unset($this->env->currentProperty);
556
-		}
557
-
558
-		if (count($values) == 0) {
559
-			return false;
560
-		}
561
-
562
-		$value = Lessc::compressList($values, ', ');
563
-		return true;
564
-	}
565
-
566
-	protected function parenValue(&$out)
567
-	{
568
-		$exp = null;
569
-
570
-		$s = $this->seek();
571
-
572
-		// speed shortcut
573
-		if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "(") {
574
-			return false;
575
-		}
576
-
577
-		$inParens = $this->inParens;
578
-		if ($this->literal("(") &&
579
-			($this->inParens = true) && $this->expression($exp) &&
580
-			$this->literal(")")
581
-		) {
582
-			$out = $exp;
583
-			$this->inParens = $inParens;
584
-			return true;
585
-		} else {
586
-			$this->inParens = $inParens;
587
-			$this->seek($s);
588
-		}
589
-
590
-		return false;
591
-	}
592
-
593
-	// a single value
594
-	protected function value(&$value)
595
-	{
596
-		$inner = null;
597
-		$word = null;
598
-		$str = null;
599
-		$var = null;
600
-
601
-		$s = $this->seek();
602
-
603
-		// speed shortcut
604
-		if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "-") {
605
-			// negation
606
-			if ($this->literal("-", false) &&
607
-				(($this->variable($inner) && $inner = array("variable", $inner)) ||
608
-				$this->unit($inner) ||
609
-				$this->parenValue($inner))
610
-			) {
611
-				$value = array("unary", "-", $inner);
612
-				return true;
613
-			} else {
614
-				$this->seek($s);
615
-			}
616
-		}
617
-
618
-		if ($this->parenValue($value)) {
619
-			return true;
620
-		}
621
-		if ($this->unit($value)) {
622
-			return true;
623
-		}
624
-		if ($this->color($value)) {
625
-			return true;
626
-		}
627
-		if ($this->func($value)) {
628
-			return true;
629
-		}
630
-		if ($this->string($value)) {
631
-			return true;
632
-		}
633
-
634
-		if ($this->keyword($word)) {
635
-			$value = array('keyword', $word);
636
-			return true;
637
-		}
638
-
639
-		// try a variable
640
-		if ($this->variable($var)) {
641
-			$value = array('variable', $var);
642
-			return true;
643
-		}
644
-
645
-		// unquote string (should this work on any type?
646
-		if ($this->literal("~") && $this->string($str)) {
647
-			$value = array("escape", $str);
648
-			return true;
649
-		} else {
650
-			$this->seek($s);
651
-		}
652
-
653
-		// css hack: \0
654
-		$m = array();
655
-		if ($this->literal('\\') && $this->match('([0-9]+)', $m)) {
656
-			$value = array('keyword', '\\'.$m[1]);
657
-			return true;
658
-		} else {
659
-			$this->seek($s);
660
-		}
661
-
662
-		return false;
663
-	}
664
-
665
-	// an import statement
666
-	protected function import(&$out, $value = '')
667
-	{
668
-		if (!$this->literal('@import')) {
669
-			return false;
670
-		}
671
-
672
-		// @import "something.css" media;
673
-		// @import url("something.css") media;
674
-		// @import url(something.css) media;
675
-
676
-		if ($this->propertyValue($value)) {
677
-			$out = array("import", $value);
678
-			return true;
679
-		}
680
-
681
-		return false;
682
-	}
683
-
684
-	protected function mediaQueryList(&$out)
685
-	{
686
-		$list = null;
687
-
688
-		if ($this->genericList($list, "mediaQuery", ",", false)) {
689
-			$out = $list[2];
690
-			return true;
691
-		}
692
-		return false;
693
-	}
694
-
695
-	protected function mediaQuery(&$out)
696
-	{
697
-		$mediaType = null;
698
-
699
-		$s = $this->seek();
700
-
701
-		$expressions = null;
702
-		$parts = array();
703
-
704
-		if ((($this->literal("only") && ($only = true)) || ($this->literal("not") && ($not = true))) && $this->keyword($mediaType)) {
705
-			$prop = array("mediaType");
706
-			if (isset($only)) {
707
-				$prop[] = "only";
708
-			}
709
-			if (isset($not)) {
710
-				$prop[] = "not";
711
-			}
712
-			$prop[] = $mediaType;
713
-			$parts[] = $prop;
714
-		} else {
715
-			$this->seek($s);
716
-		}
717
-
718
-
719
-		if (!empty($mediaType) && !$this->literal("and")) {
720
-			// ~
721
-		} else {
722
-			$this->genericList($expressions, "mediaExpression", "and", false);
723
-			if (is_array($expressions)) {
724
-				$parts = array_merge($parts, $expressions[2]);
725
-			}
726
-		}
727
-
728
-		if (count($parts) == 0) {
729
-			$this->seek($s);
730
-			return false;
731
-		}
732
-
733
-		$out = $parts;
734
-		return true;
735
-	}
736
-
737
-	protected function mediaExpression(&$out)
738
-	{
739
-		$feature = null;
740
-		$variable = null;
741
-
742
-		$s = $this->seek();
743
-		$value = null;
744
-		if ($this->literal("(") &&
745
-			$this->keyword($feature) &&
746
-			($this->literal(":") && $this->expression($value)) &&
747
-			$this->literal(")")
748
-		) {
749
-			$out = array("mediaExp", $feature);
750
-			if ($value) {
751
-				$out[] = $value;
752
-			}
753
-			return true;
754
-		} elseif ($this->variable($variable)) {
755
-			$out = array('variable', $variable);
756
-			return true;
757
-		}
758
-
759
-		$this->seek($s);
760
-		return false;
761
-	}
762
-
763
-	// an unbounded string stopped by $end
764
-	protected function openString($end, &$out, $nestingOpen = null, $rejectStrs = null)
765
-	{
766
-		$str = null;
767
-		$inter = null;
768
-
769
-		$oldWhite = $this->eatWhiteDefault;
770
-		$this->eatWhiteDefault = false;
771
-
772
-		$stop = array("'", '"', "@{", $end);
773
-		$stop = array_map(array("lessc", "preg_quote"), $stop);
774
-		// $stop[] = self::$commentMulti;
775
-
776
-		if (!is_null($rejectStrs)) {
777
-			$stop = array_merge($stop, $rejectStrs);
778
-		}
779
-
780
-		$patt = '(.*?)('.implode("|", $stop).')';
781
-
782
-		$nestingLevel = 0;
783
-
784
-		$content = array();
785
-		$m = array();
786
-		while ($this->match($patt, $m, false)) {
787
-			if (!empty($m[1])) {
788
-				$content[] = $m[1];
789
-				if ($nestingOpen) {
790
-					$nestingLevel += substr_count($m[1], $nestingOpen);
791
-				}
792
-			}
793
-
794
-			$tok = $m[2];
795
-
796
-			$this->count -= strlen($tok);
797
-			if ($tok == $end) {
798
-				if ($nestingLevel == 0) {
799
-					break;
800
-				} else {
801
-					$nestingLevel--;
802
-				}
803
-			}
804
-
805
-			if (($tok == "'" || $tok == '"') && $this->string($str)) {
806
-				$content[] = $str;
807
-				continue;
808
-			}
809
-
810
-			if ($tok == "@{" && $this->interpolation($inter)) {
811
-				$content[] = $inter;
812
-				continue;
813
-			}
814
-
815
-			if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) {
816
-				break;
817
-			}
818
-
819
-			$content[] = $tok;
820
-			$this->count += strlen($tok);
821
-		}
822
-
823
-		$this->eatWhiteDefault = $oldWhite;
824
-
825
-		if (count($content) == 0) {
826
-			return false;
827
-		}
828
-
829
-		// trim the end
830
-		if (is_string(end($content))) {
831
-			$content[count($content) - 1] = rtrim(end($content));
832
-		}
833
-
834
-		$out = array("string", "", $content);
835
-		return true;
836
-	}
837
-
838
-	protected function string(&$out)
839
-	{
840
-		$inter = null;
841
-
842
-		$s = $this->seek();
843
-		if ($this->literal('"', false)) {
844
-			$delim = '"';
845
-		} elseif ($this->literal("'", false)) {
846
-			$delim = "'";
847
-		} else {
848
-			return false;
849
-		}
850
-
851
-		$content = array();
852
-
853
-		// look for either ending delim , escape, or string interpolation
854
-		$patt = '([^\n]*?)(@\{|\\\\|'.
855
-			Lessc::preg_quote($delim).')';
856
-
857
-		$oldWhite = $this->eatWhiteDefault;
858
-		$this->eatWhiteDefault = false;
859
-
860
-		$m = array();
861
-		while ($this->match($patt, $m, false)) {
862
-			$content[] = $m[1];
863
-			if ($m[2] == "@{") {
864
-				$this->count -= strlen($m[2]);
865
-				if ($this->interpolation($inter)) {
866
-					$content[] = $inter;
867
-				} else {
868
-					$this->count += strlen($m[2]);
869
-					$content[] = "@{"; // ignore it
870
-				}
871
-			} elseif ($m[2] == '\\') {
872
-				$content[] = $m[2];
873
-				if ($this->literal($delim, false)) {
874
-					$content[] = $delim;
875
-				}
876
-			} else {
877
-				$this->count -= strlen($delim);
878
-				break; // delim
879
-			}
880
-		}
881
-
882
-		$this->eatWhiteDefault = $oldWhite;
883
-
884
-		if ($this->literal($delim)) {
885
-			$out = array("string", $delim, $content);
886
-			return true;
887
-		}
888
-
889
-		$this->seek($s);
890
-		return false;
891
-	}
892
-
893
-	protected function interpolation(&$out)
894
-	{
895
-		$interp = array();
896
-
897
-		$oldWhite = $this->eatWhiteDefault;
898
-		$this->eatWhiteDefault = true;
899
-
900
-		$s = $this->seek();
901
-		if ($this->literal("@{") &&
902
-			$this->openString("}", $interp, null, array("'", '"', ";")) &&
903
-			$this->literal("}", false)
904
-		) {
905
-			$out = array("interpolate", $interp);
906
-			$this->eatWhiteDefault = $oldWhite;
907
-			if ($this->eatWhiteDefault) {
908
-				$this->whitespace();
909
-			}
910
-			return true;
911
-		}
912
-
913
-		$this->eatWhiteDefault = $oldWhite;
914
-		$this->seek($s);
915
-		return false;
916
-	}
917
-
918
-	protected function unit(&$unit)
919
-	{
920
-		$m = array();
921
-
922
-		// speed shortcut
923
-		if (isset($this->buffer[$this->count])) {
924
-			$char = $this->buffer[$this->count];
925
-			if (!ctype_digit($char) && $char != ".") {
926
-				return false;
927
-			}
928
-		}
929
-
930
-		if ($this->match('([0-9]+(?:\.[0-9]*)?|\.[0-9]+)([%a-zA-Z]+)?', $m)) {
931
-			$unit = array("number", $m[1], empty($m[2]) ? "" : $m[2]);
932
-			return true;
933
-		}
934
-		return false;
935
-	}
936
-
937
-	// a # color
938
-	protected function color(&$out)
939
-	{
940
-		$m = array();
941
-
942
-		if ($this->match('(#(?:[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3}))', $m)) {
943
-			if (strlen($m[1]) > 7) {
944
-				$out = array("string", "", array($m[1]));
945
-			} else {
946
-				$out = array("raw_color", $m[1]);
947
-			}
948
-			return true;
949
-		}
950
-
951
-		return false;
952
-	}
953
-
954
-	// consume an argument definition list surrounded by ()
955
-	// each argument is a variable name with optional value
956
-	// or at the end a ... or a variable named followed by ...
957
-	// arguments are separated by , unless a ; is in the list, then ; is the
958
-	// delimiter.
959
-	protected function argumentDef(&$args, &$isVararg)
960
-	{
961
-		$value = array();
962
-		$rhs = null;
963
-
964
-		$s = $this->seek();
965
-		if (!$this->literal('(')) {
966
-			return false;
967
-		}
968
-
969
-		$values = array();
970
-		$delim = ",";
971
-		$method = "expressionList";
972
-
973
-		$isVararg = false;
974
-		while (true) {
975
-			if ($this->literal("...")) {
976
-				$isVararg = true;
977
-				break;
978
-			}
979
-
980
-			if ($this->$method($value)) {
981
-				if ($value[0] == "variable") {
982
-					$arg = array("arg", $value[1]);
983
-					$ss = $this->seek();
984
-
985
-					if ($this->assign() && $this->$method($rhs)) {
986
-						$arg[] = $rhs;
987
-					} else {
988
-						$this->seek($ss);
989
-						if ($this->literal("...")) {
990
-							$arg[0] = "rest";
991
-							$isVararg = true;
992
-						}
993
-					}
994
-
995
-					$values[] = $arg;
996
-					if ($isVararg) {
997
-						break;
998
-					}
999
-					continue;
1000
-				} else {
1001
-					$values[] = array("lit", $value);
1002
-				}
1003
-			}
1004
-
1005
-
1006
-			if (!$this->literal($delim)) {
1007
-				if ($delim == "," && $this->literal(";")) {
1008
-					// found new delim, convert existing args
1009
-					$delim = ";";
1010
-					$method = "propertyValue";
1011
-
1012
-					// transform arg list
1013
-					if (isset($values[1])) { // 2 items
1014
-						$newList = array();
1015
-						foreach ($values as $i => $arg) {
1016
-							switch ($arg[0]) {
1017
-								case "arg":
1018
-									if ($i) {
1019
-										$this->throwError("Cannot mix ; and , as delimiter types");
1020
-									}
1021
-									$newList[] = $arg[2];
1022
-									break;
1023
-								case "lit":
1024
-									$newList[] = $arg[1];
1025
-									break;
1026
-								case "rest":
1027
-									$this->throwError("Unexpected rest before semicolon");
1028
-							}
1029
-						}
1030
-
1031
-						$newList = array("list", ", ", $newList);
1032
-
1033
-						switch ($values[0][0]) {
1034
-							case "arg":
1035
-								$newArg = array("arg", $values[0][1], $newList);
1036
-								break;
1037
-							case "lit":
1038
-								$newArg = array("lit", $newList);
1039
-								break;
1040
-						}
1041
-
1042
-					} elseif ($values) { // 1 item
1043
-						$newArg = $values[0];
1044
-					}
1045
-
1046
-					if ($newArg) {
1047
-						$values = array($newArg);
1048
-					}
1049
-				} else {
1050
-					break;
1051
-				}
1052
-			}
1053
-		}
1054
-
1055
-		if (!$this->literal(')')) {
1056
-			$this->seek($s);
1057
-			return false;
1058
-		}
1059
-
1060
-		$args = $values;
1061
-
1062
-		return true;
1063
-	}
1064
-
1065
-	// consume a list of tags
1066
-	// this accepts a hanging delimiter
1067
-	protected function tags(&$tags, $simple = false, $delim = ',')
1068
-	{
1069
-		$tt = array();
1070
-
1071
-		$tags = array();
1072
-		while ($this->tag($tt, $simple)) {
1073
-			$tags[] = $tt;
1074
-			if (!$this->literal($delim)) {
1075
-				break;
1076
-			}
1077
-		}
1078
-		if (count($tags) == 0) {
1079
-			return false;
1080
-		}
1081
-
1082
-		return true;
1083
-	}
1084
-
1085
-	// list of tags of specifying mixin path
1086
-	// optionally separated by > (lazy, accepts extra >)
1087
-	protected function mixinTags(&$tags)
1088
-	{
1089
-		$tt = array();
1090
-
1091
-		$tags = array();
1092
-		while ($this->tag($tt, true)) {
1093
-			$tags[] = $tt;
1094
-			$this->literal(">");
1095
-		}
1096
-
1097
-		if (!$tags) {
1098
-			return false;
1099
-		}
1100
-
1101
-		return true;
1102
-	}
1103
-
1104
-	// a bracketed value (contained within in a tag definition)
1105
-	protected function tagBracket(&$parts, &$hasExpression)
1106
-	{
1107
-		$str = null;
1108
-		$inter = null;
1109
-		$word = null;
1110
-
1111
-		// speed shortcut
1112
-		if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "[") {
1113
-			return false;
1114
-		}
1115
-
1116
-		$s = $this->seek();
1117
-
1118
-		$hasInterpolation = false;
1119
-
1120
-		if ($this->literal("[", false)) {
1121
-			$attrParts = array("[");
1122
-			// keyword, string, operator
1123
-			while (true) {
1124
-				if ($this->literal("]", false)) {
1125
-					$this->count--;
1126
-					break; // get out early
1127
-				}
1128
-
1129
-				$m = array();
1130
-				if ($this->match('\s+', $m)) {
1131
-					$attrParts[] = " ";
1132
-					continue;
1133
-				}
1134
-				if ($this->string($str)) {
1135
-					// escape parent selector, (yuck)
1136
-					foreach ($str[2] as &$chunk) {
1137
-						$chunk = str_replace($this->lessc->parentSelector, "$&$", $chunk);
1138
-					}
1139
-
1140
-					$attrParts[] = $str;
1141
-					$hasInterpolation = true;
1142
-					continue;
1143
-				}
1144
-
1145
-				if ($this->keyword($word)) {
1146
-					$attrParts[] = $word;
1147
-					continue;
1148
-				}
1149
-
1150
-				if ($this->interpolation($inter)) {
1151
-					$attrParts[] = $inter;
1152
-					$hasInterpolation = true;
1153
-					continue;
1154
-				}
1155
-
1156
-				// operator, handles attr namespace too
1157
-				if ($this->match('[|-~\$\*\^=]+', $m)) {
1158
-					$attrParts[] = $m[0];
1159
-					continue;
1160
-				}
1161
-
1162
-				break;
1163
-			}
1164
-
1165
-			if ($this->literal("]", false)) {
1166
-				$attrParts[] = "]";
1167
-				foreach ($attrParts as $part) {
1168
-					$parts[] = $part;
1169
-				}
1170
-				$hasExpression = $hasExpression || $hasInterpolation;
1171
-				return true;
1172
-			}
1173
-			$this->seek($s);
1174
-		}
1175
-
1176
-		$this->seek($s);
1177
-		return false;
1178
-	}
1179
-
1180
-	// a space separated list of selectors
1181
-	protected function tag(&$tag, $simple = false)
1182
-	{
1183
-		$interp = null;
1184
-		$unit = null;
1185
-
1186
-		if ($simple) {
1187
-			$chars = '^@,:;{}\][>\(\) "\'';
1188
-		} else {
1189
-			$chars = '^@,;{}["\'';
1190
-		}
1191
-		$s = $this->seek();
1192
-
1193
-		$hasExpression = false;
1194
-		$parts = array();
1195
-		while ($this->tagBracket($parts, $hasExpression));
1196
-
1197
-		$oldWhite = $this->eatWhiteDefault;
1198
-		$this->eatWhiteDefault = false;
1199
-
1200
-		while (true) {
1201
-			$m = array();
1202
-			if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) {
1203
-				$parts[] = $m[1];
1204
-				if ($simple) {
1205
-					break;
1206
-				}
1207
-
1208
-				while ($this->tagBracket($parts, $hasExpression));
1209
-				continue;
1210
-			}
1211
-
1212
-			if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") {
1213
-				if ($this->interpolation($interp)) {
1214
-					$hasExpression = true;
1215
-					$interp[2] = true; // don't unescape
1216
-					$parts[] = $interp;
1217
-					continue;
1218
-				}
1219
-
1220
-				if ($this->literal("@")) {
1221
-					$parts[] = "@";
1222
-					continue;
1223
-				}
1224
-			}
1225
-
1226
-			if ($this->unit($unit)) { // for keyframes
1227
-				$parts[] = $unit[1];
1228
-				$parts[] = $unit[2];
1229
-				continue;
1230
-			}
1231
-
1232
-			break;
1233
-		}
1234
-
1235
-		$this->eatWhiteDefault = $oldWhite;
1236
-		if (!$parts) {
1237
-			$this->seek($s);
1238
-			return false;
1239
-		}
1240
-
1241
-		if ($hasExpression) {
1242
-			$tag = array("exp", array("string", "", $parts));
1243
-		} else {
1244
-			$tag = trim(implode($parts));
1245
-		}
1246
-
1247
-		$this->whitespace();
1248
-		return true;
1249
-	}
1250
-
1251
-	// a css function
1252
-	protected function func(&$func)
1253
-	{
1254
-		$s = $this->seek();
1255
-
1256
-		$m = array();
1257
-		$value = array();
1258
-		$string = array();
1259
-		$name = null;
1260
-
1261
-		if ($this->match('(%|[\w\-_][\w\-_:\.]+|[\w_])', $m) && $this->literal('(')) {
1262
-			$fname = $m[1];
1263
-
1264
-			$sPreArgs = $this->seek();
1265
-
1266
-			$args = array();
1267
-			while (true) {
1268
-				$ss = $this->seek();
1269
-				// this ugly nonsense is for ie filter properties
1270
-				if ($this->keyword($name) && $this->literal('=') && $this->expressionList($value)) {
1271
-					$args[] = array("string", "", array($name, "=", $value));
1272
-				} else {
1273
-					$this->seek($ss);
1274
-					if ($this->expressionList($value)) {
1275
-						$args[] = $value;
1276
-					}
1277
-				}
1278
-
1279
-				if (!$this->literal(',')) {
1280
-					break;
1281
-				}
1282
-			}
1283
-			$args = array('list', ',', $args);
1284
-
1285
-			if ($this->literal(')')) {
1286
-				$func = array('function', $fname, $args);
1287
-				return true;
1288
-			} elseif ($fname == 'url') {
1289
-				// couldn't parse and in url? treat as string
1290
-				$this->seek($sPreArgs);
1291
-				if ($this->openString(")", $string) && $this->literal(")")) {
1292
-					$func = array('function', $fname, $string);
1293
-					return true;
1294
-				}
1295
-			}
1296
-		}
1297
-
1298
-		$this->seek($s);
1299
-		return false;
1300
-	}
1301
-
1302
-	// consume a less variable
1303
-	protected function variable(&$name)
1304
-	{
1305
-		$sub = null;
1306
-		$name = null;
1307
-
1308
-		$s = $this->seek();
1309
-		if ($this->literal($this->lessc->vPrefix, false) &&
1310
-			($this->variable($sub) || $this->keyword($name))
1311
-		) {
1312
-			if (!empty($sub)) {
1313
-				$name = array('variable', $sub);
1314
-			} else {
1315
-				$name = $this->lessc->vPrefix.$name;
1316
-			}
1317
-			return true;
1318
-		}
1319
-
1320
-		$name = null;
1321
-		$this->seek($s);
1322
-		return false;
1323
-	}
1324
-
1325
-	/**
1326
-	 * Consume an assignment operator
1327
-	 * Can optionally take a name that will be set to the current property name
1328
-	 */
1329
-	protected function assign($name = null)
1330
-	{
1331
-		if ($name) {
1332
-			$this->currentProperty = $name;
1333
-		}
1334
-		return $this->literal(':') || $this->literal('=');
1335
-	}
1336
-
1337
-	// consume a keyword
1338
-	protected function keyword(&$word)
1339
-	{
1340
-		$m = array();
1341
-		if ($this->match('([\w_\-\*!"][\w\-_"]*)', $m)) {
1342
-			$word = $m[1];
1343
-			return true;
1344
-		}
1345
-		return false;
1346
-	}
1347
-
1348
-	// consume an end of statement delimiter
1349
-	protected function end()
1350
-	{
1351
-		if ($this->literal(';', false)) {
1352
-			return true;
1353
-		} elseif ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') {
1354
-			// if there is end of file or a closing block next then we don't need a ;
1355
-			return true;
1356
-		}
1357
-		return false;
1358
-	}
1359
-
1360
-	protected function guards(&$guards)
1361
-	{
1362
-		$g = null;
1363
-
1364
-		$s = $this->seek();
1365
-
1366
-		if (!$this->literal("when")) {
1367
-			$this->seek($s);
1368
-			return false;
1369
-		}
1370
-
1371
-		$guards = array();
1372
-
1373
-		while ($this->guardGroup($g)) {
1374
-			$guards[] = $g;
1375
-			if (!$this->literal(",")) {
1376
-				break;
1377
-			}
1378
-		}
1379
-
1380
-		if (count($guards) == 0) {
1381
-			$guards = null;
1382
-			$this->seek($s);
1383
-			return false;
1384
-		}
1385
-
1386
-		return true;
1387
-	}
1388
-
1389
-	// a bunch of guards that are and'd together
1390
-	// TODO rename to guardGroup
1391
-	protected function guardGroup(&$guardGroup)
1392
-	{
1393
-		$guard = null;
1394
-
1395
-		$s = $this->seek();
1396
-		$guardGroup = array();
1397
-		while ($this->guard($guard)) {
1398
-			$guardGroup[] = $guard;
1399
-			if (!$this->literal("and")) {
1400
-				break;
1401
-			}
1402
-		}
1403
-
1404
-		if (count($guardGroup) == 0) {
1405
-			$guardGroup = null;
1406
-			$this->seek($s);
1407
-			return false;
1408
-		}
1409
-
1410
-		return true;
1411
-	}
1412
-
1413
-	protected function guard(&$guard)
1414
-	{
1415
-		$exp = null;
1416
-
1417
-		$s = $this->seek();
1418
-		$negate = $this->literal("not");
1419
-
1420
-		if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
1421
-			$guard = $exp;
1422
-			if ($negate) {
1423
-				$guard = array("negate", $guard);
1424
-			}
1425
-			return true;
1426
-		}
1427
-
1428
-		$this->seek($s);
1429
-		return false;
1430
-	}
1431
-
1432
-	/* raw parsing functions */
1433
-
1434
-	protected function literal($what, $eatWhitespace = null)
1435
-	{
1436
-		if ($eatWhitespace === null) {
1437
-			$eatWhitespace = $this->eatWhiteDefault;
1438
-		}
1439
-
1440
-		// shortcut on single letter
1441
-		if (!isset($what[1]) && isset($this->buffer[$this->count])) {
1442
-			if ($this->buffer[$this->count] == $what) {
1443
-				if (!$eatWhitespace) {
1444
-					$this->count++;
1445
-					return true;
1446
-				}
1447
-			// goes below...
1448
-			} else {
1449
-				return false;
1450
-			}
1451
-		}
1452
-
1453
-		if (!isset(self::$literalCache[$what])) {
1454
-			self::$literalCache[$what] = Lessc::preg_quote($what);
1455
-		}
1456
-
1457
-		$m = array();
1458
-		return $this->match(self::$literalCache[$what], $m, $eatWhitespace);
1459
-	}
1460
-
1461
-	protected function genericList(&$out, $parseItem, $delim = "", $flatten = true)
1462
-	{
1463
-		$value = null;
1464
-
1465
-		$s = $this->seek();
1466
-		$items = array();
1467
-		while ($this->$parseItem($value)) {
1468
-			$items[] = $value;
1469
-			if ($delim) {
1470
-				if (!$this->literal($delim)) {
1471
-					break;
1472
-				}
1473
-			}
1474
-		}
1475
-
1476
-		if (count($items) == 0) {
1477
-			$this->seek($s);
1478
-			return false;
1479
-		}
1480
-
1481
-		if ($flatten && count($items) == 1) {
1482
-			$out = $items[0];
1483
-		} else {
1484
-			$out = array("list", $delim, $items);
1485
-		}
1486
-
1487
-		return true;
1488
-	}
1489
-
1490
-
1491
-	// advance counter to next occurrence of $what
1492
-	// $until - don't include $what in advance
1493
-	// $allowNewline, if string, will be used as valid char set
1494
-	protected function to($what, &$out, $until = false, $allowNewline = false)
1495
-	{
1496
-		if (is_string($allowNewline)) {
1497
-			$validChars = $allowNewline;
1498
-		} else {
1499
-			$validChars = $allowNewline ? "." : "[^\n]";
1500
-		}
1501
-		$m = array();
1502
-		if (!$this->match('('.$validChars.'*?)'.Lessc::preg_quote($what), $m, !$until)) {
1503
-			return false;
1504
-		}
1505
-		if ($until) {
1506
-			$this->count -= strlen($what); // give back $what
1507
-		}
1508
-		$out = $m[1];
1509
-		return true;
1510
-	}
1511
-
1512
-	// try to match something on head of buffer
1513
-	protected function match($regex, &$out, $eatWhitespace = null)
1514
-	{
1515
-		if ($eatWhitespace === null) {
1516
-			$eatWhitespace = $this->eatWhiteDefault;
1517
-		}
1518
-
1519
-		$r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais';
1520
-		if (preg_match($r, $this->buffer, $out, 0, $this->count)) {
1521
-			$this->count += strlen($out[0]);
1522
-			if ($eatWhitespace && $this->writeComments) {
1523
-				$this->whitespace();
1524
-			}
1525
-			return true;
1526
-		}
1527
-		return false;
1528
-	}
1529
-
1530
-	// match some whitespace
1531
-	protected function whitespace()
1532
-	{
1533
-		if ($this->writeComments) {
1534
-			$gotWhite = false;
1535
-			$m = array();
1536
-			while (preg_match(self::$whitePattern, $this->buffer, $m, 0, $this->count)) {
1537
-				if (isset($m[1]) && empty($this->seenComments[$this->count])) {
1538
-					$this->append(array("comment", $m[1]));
1539
-					$this->seenComments[$this->count] = true;
1540
-				}
1541
-				$this->count += strlen($m[0]);
1542
-				$gotWhite = true;
1543
-			}
1544
-			return $gotWhite;
1545
-		} else {
1546
-			$this->match("", $m);
1547
-			return strlen($m[0]) > 0;
1548
-		}
1549
-	}
1550
-
1551
-	// match something without consuming it
1552
-	protected function peek($regex, &$out = null, $from = null)
1553
-	{
1554
-		if (is_null($from)) {
1555
-			$from = $this->count;
1556
-		}
1557
-		$r = '/'.$regex.'/Ais';
1558
-		$result = preg_match($r, $this->buffer, $out, 0, $from);
1559
-
1560
-		return $result;
1561
-	}
1562
-
1563
-	// seek to a spot in the buffer or return where we are on no argument
1564
-	protected function seek($where = null)
1565
-	{
1566
-		if ($where === null) {
1567
-			return $this->count;
1568
-		} else {
1569
-			$this->count = $where;
1570
-		}
1571
-		return true;
1572
-	}
1573
-
1574
-	/* misc functions */
1575
-
1576
-	public function throwError($msg = "parse error", $count = null)
1577
-	{
1578
-		$count = is_null($count) ? $this->count : $count;
1579
-
1580
-		$line = $this->line +
1581
-			substr_count(substr($this->buffer, 0, $count), "\n");
1582
-
1583
-		if (!empty($this->sourceName)) {
1584
-			$loc = "$this->sourceName on line $line";
1585
-		} else {
1586
-			$loc = "line: $line";
1587
-		}
1588
-
1589
-		// TODO this depends on $this->count
1590
-		$m = array();
1591
-		if ($this->peek("(.*?)(\n|$)", $m, $count)) {
1592
-			throw new exception("$msg: failed at `$m[1]` $loc");
1593
-		} else {
1594
-			throw new exception("$msg: $loc");
1595
-		}
1596
-	}
1597
-
1598
-	protected function pushBlock($selectors = null, $type = null)
1599
-	{
1600
-		$b = new stdclass();
1601
-		$b->parent = $this->env;
1602
-
1603
-		$b->type = $type;
1604
-		$b->id = self::$nextBlockId++;
1605
-
1606
-		$b->isVararg = false; // TODO: kill me from here
1607
-		$b->tags = $selectors;
1608
-
1609
-		$b->props = array();
1610
-		$b->children = array();
1611
-
1612
-		$this->env = $b;
1613
-		return $b;
1614
-	}
1615
-
1616
-	// push a block that doesn't multiply tags
1617
-	protected function pushSpecialBlock($type)
1618
-	{
1619
-		return $this->pushBlock(null, $type);
1620
-	}
1621
-
1622
-	// append a property to the current block
1623
-	protected function append($prop, $pos = null)
1624
-	{
1625
-		if ($pos !== null) {
1626
-			$prop[-1] = $pos;
1627
-		}
1628
-		$this->env->props[] = $prop;
1629
-	}
1630
-
1631
-	// pop something off the stack
1632
-	protected function pop()
1633
-	{
1634
-		$old = $this->env;
1635
-		$this->env = $this->env->parent;
1636
-		return $old;
1637
-	}
1638
-
1639
-	// remove comments from $text
1640
-	// todo: make it work for all functions, not just url
1641
-	protected function removeComments($text)
1642
-	{
1643
-		$look = array(
1644
-			'url(', '//', '/*', '"', "'"
1645
-		);
1646
-
1647
-		$out = '';
1648
-		$min = null;
1649
-		while (true) {
1650
-			// find the next item
1651
-			foreach ($look as $token) {
1652
-				$pos = strpos($text, $token);
1653
-				if ($pos !== false) {
1654
-					if (!isset($min) || $pos < $min[1]) {
1655
-						$min = array($token, $pos);
1656
-					}
1657
-				}
1658
-			}
1659
-
1660
-			if (is_null($min)) {
1661
-				break;
1662
-			}
1663
-
1664
-			$count = $min[1];
1665
-			$skip = 0;
1666
-			$newlines = 0;
1667
-			switch ($min[0]) {
1668
-				case 'url(':
1669
-					$m = array();
1670
-					if (preg_match('/url\(.*?\)/', $text, $m, 0, $count)) {
1671
-						$count += strlen($m[0]) - strlen($min[0]);
1672
-					}
1673
-					break;
1674
-				case '"':
1675
-				case "'":
1676
-					$m = array();
1677
-					if (preg_match('/'.$min[0].'.*?(?<!\\\\)'.$min[0].'/', $text, $m, 0, $count)) {
1678
-						$count += strlen($m[0]) - 1;
1679
-					}
1680
-					break;
1681
-				case '//':
1682
-					$skip = strpos($text, "\n", $count);
1683
-					if ($skip === false) {
1684
-						$skip = strlen($text) - $count;
1685
-					} else {
1686
-						$skip -= $count;
1687
-					}
1688
-					break;
1689
-				case '/*':
1690
-					$m = array();
1691
-					if (preg_match('/\/\*.*?\*\//s', $text, $m, 0, $count)) {
1692
-						$skip = strlen($m[0]);
1693
-						$newlines = substr_count($m[0], "\n");
1694
-					}
1695
-					break;
1696
-			}
1697
-
1698
-			if ($skip == 0) {
1699
-				$count += strlen($min[0]);
1700
-			}
1701
-
1702
-			$out .= substr($text, 0, $count).str_repeat("\n", $newlines);
1703
-			$text = substr($text, $count + $skip);
1704
-
1705
-			$min = null;
1706
-		}
1707
-
1708
-		return $out.$text;
1709
-	}
64
+    protected static $nextBlockId = 0; // used to uniquely identify blocks
65
+
66
+    protected static $precedence = array(
67
+        '=<' => 0,
68
+        '>=' => 0,
69
+        '=' => 0,
70
+        '<' => 0,
71
+        '>' => 0,
72
+
73
+        '+' => 1,
74
+        '-' => 1,
75
+        '*' => 2,
76
+        '/' => 2,
77
+        '%' => 2,
78
+    );
79
+
80
+    protected static $whitePattern;
81
+    protected static $commentMulti;
82
+
83
+    protected static $commentSingle = "//";
84
+    protected static $commentMultiLeft = "/*";
85
+    protected static $commentMultiRight = "*/";
86
+
87
+    // regex string to match any of the operators
88
+    protected static $operatorString;
89
+
90
+    // these properties will supress division unless it's inside parenthases
91
+    protected static $supressDivisionProps =
92
+        array('/border-radius$/i', '/^font$/i');
93
+
94
+    protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document", "viewport", "-moz-viewport", "-o-viewport", "-ms-viewport");
95
+    protected $lineDirectives = array("charset");
96
+
97
+    /**
98
+     * if we are in parens we can be more liberal with whitespace around
99
+     * operators because it must evaluate to a single value and thus is less
100
+     * ambiguous.
101
+     *
102
+     * Consider:
103
+     *     property1: 10 -5; // is two numbers, 10 and -5
104
+     *     property2: (10 -5); // should evaluate to 5
105
+     */
106
+    protected $inParens = false;
107
+
108
+    // caches preg escaped literals
109
+    protected static $literalCache = array();
110
+
111
+    public $env;
112
+    public $buffer;
113
+    public $count;
114
+    public $line;
115
+    public $eatWhiteDefault;
116
+    public $lessc;
117
+    public $sourceName;
118
+    public $writeComments;
119
+    public $seenComments;
120
+    public $currentProperty;
121
+    public $inExp;
122
+
123
+
124
+    public function __construct($lessc, $sourceName = null)
125
+    {
126
+        $this->eatWhiteDefault = true;
127
+        // reference to less needed for vPrefix, mPrefix, and parentSelector
128
+        $this->lessc = $lessc;
129
+
130
+        $this->sourceName = $sourceName; // name used for error messages
131
+
132
+        $this->writeComments = false;
133
+
134
+        if (!self::$operatorString) {
135
+            self::$operatorString =
136
+                '('.implode('|', array_map(
137
+                    array('lessc', 'preg_quote'),
138
+                    array_keys(self::$precedence)
139
+                )).')';
140
+
141
+            $commentSingle = Lessc::preg_quote(self::$commentSingle);
142
+            $commentMultiLeft = Lessc::preg_quote(self::$commentMultiLeft);
143
+            $commentMultiRight = Lessc::preg_quote(self::$commentMultiRight);
144
+
145
+            self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
146
+            self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
147
+        }
148
+    }
149
+
150
+    /**
151
+     * Parse a string
152
+     *
153
+     * @param       string  $buffer         String to parse
154
+     * @throws exception
155
+     * @return NULL|stdclass
156
+     */
157
+    public function parse($buffer)
158
+    {
159
+        $this->count = 0;
160
+        $this->line = 1;
161
+
162
+        $this->env = null; // block stack
163
+        $this->buffer = $this->writeComments ? $buffer : $this->removeComments($buffer);
164
+        $this->pushSpecialBlock("root");
165
+        $this->eatWhiteDefault = true;
166
+        $this->seenComments = array();
167
+
168
+        // trim whitespace on head
169
+        // if (preg_match('/^\s+/', $this->buffer, $m)) {
170
+        //  $this->line += substr_count($m[0], "\n");
171
+        //  $this->buffer = ltrim($this->buffer);
172
+        // }
173
+        $this->whitespace();
174
+
175
+        // parse the entire file
176
+        while (false !== $this->parseChunk());
177
+
178
+        if ($this->count != strlen($this->buffer)) {
179
+            $this->throwError('parse error count '.$this->count.' != len buffer '.strlen($this->buffer));
180
+
181
+        }
182
+
183
+        // TODO report where the block was opened
184
+        if (!property_exists($this->env, 'parent') || !is_null($this->env->parent)) {
185
+            throw new exception('parse error: unclosed block');
186
+        }
187
+
188
+        return $this->env;
189
+    }
190
+
191
+    /**
192
+     * Parse a single chunk off the head of the buffer and append it to the
193
+     * current parse environment.
194
+     * Returns false when the buffer is empty, or when there is an error.
195
+     *
196
+     * This function is called repeatedly until the entire document is
197
+     * parsed.
198
+     *
199
+     * This parser is most similar to a recursive descent parser. Single
200
+     * functions represent discrete grammatical rules for the language, and
201
+     * they are able to capture the text that represents those rules.
202
+     *
203
+     * Consider the function Lessc::keyword(). (all parse functions are
204
+     * structured the same)
205
+     *
206
+     * The function takes a single reference argument. When calling the
207
+     * function it will attempt to match a keyword on the head of the buffer.
208
+     * If it is successful, it will place the keyword in the referenced
209
+     * argument, advance the position in the buffer, and return true. If it
210
+     * fails then it won't advance the buffer and it will return false.
211
+     *
212
+     * All of these parse functions are powered by Lessc::match(), which behaves
213
+     * the same way, but takes a literal regular expression. Sometimes it is
214
+     * more convenient to use match instead of creating a new function.
215
+     *
216
+     * Because of the format of the functions, to parse an entire string of
217
+     * grammatical rules, you can chain them together using &&.
218
+     *
219
+     * But, if some of the rules in the chain succeed before one fails, then
220
+     * the buffer position will be left at an invalid state. In order to
221
+     * avoid this, Lessc::seek() is used to remember and set buffer positions.
222
+     *
223
+     * Before parsing a chain, use $s = $this->seek() to remember the current
224
+     * position into $s. Then if a chain fails, use $this->seek($s) to
225
+     * go back where we started.
226
+     */
227
+    protected function parseChunk()
228
+    {
229
+        if (empty($this->buffer)) {
230
+            return false;
231
+        }
232
+        $s = $this->seek();
233
+
234
+        if ($this->whitespace()) {
235
+            return true;
236
+        }
237
+
238
+        $key = null;
239
+        $value = null;
240
+        $mediaQueries = null;
241
+        $dirName = null;
242
+        $dirValue = null;
243
+        $importValue = null;
244
+        $guards = null;
245
+        $tag = null;
246
+        $args = null;
247
+        $isVararg = null;
248
+        $argv = null;
249
+        $suffix = null;
250
+        $var = null;
251
+        $tags = null;
252
+
253
+        // setting a property
254
+        if ($this->keyword($key) && $this->assign() &&
255
+            $this->propertyValue($value, $key) && $this->end()
256
+        ) {
257
+            $this->append(array('assign', $key, $value), $s);
258
+            return true;
259
+        } else {
260
+            $this->seek($s);
261
+        }
262
+
263
+
264
+        // look for special css blocks
265
+        if ($this->literal('@', false)) {
266
+            $this->count--;
267
+
268
+            // media
269
+            if ($this->literal('@media')) {
270
+                if ($this->mediaQueryList($mediaQueries)
271
+                    && $this->literal('{')
272
+                ) {
273
+                    $media = $this->pushSpecialBlock("media");
274
+                    $media->queries = is_null($mediaQueries) ? array() : $mediaQueries;
275
+                    return true;
276
+                } else {
277
+                    $this->seek($s);
278
+                    return false;
279
+                }
280
+            }
281
+
282
+            if ($this->literal("@", false) && $this->keyword($dirName)) {
283
+                if ($this->isDirective($dirName, $this->blockDirectives)) {
284
+                    if ($this->openString("{", $dirValue, null, array(";")) &&
285
+                        $this->literal("{")
286
+                    ) {
287
+                        $dir = $this->pushSpecialBlock("directive");
288
+                        $dir->name = $dirName;
289
+                        if (isset($dirValue)) {
290
+                            $dir->value = $dirValue;
291
+                        }
292
+                        return true;
293
+                    }
294
+                } elseif ($this->isDirective($dirName, $this->lineDirectives)) {
295
+                    if ($this->propertyValue($dirValue) && $this->end()) {
296
+                        $this->append(array("directive", $dirName, $dirValue));
297
+                        return true;
298
+                    }
299
+                }
300
+            }
301
+
302
+            $this->seek($s);
303
+        }
304
+
305
+        // setting a variable
306
+        if ($this->variable($var) && $this->assign() &&
307
+            $this->propertyValue($value) && $this->end()
308
+        ) {
309
+            $this->append(array('assign', $var, $value), $s);
310
+            return true;
311
+        } else {
312
+            $this->seek($s);
313
+        }
314
+
315
+        if ($this->import($importValue)) {
316
+            $this->append($importValue, $s);
317
+            return true;
318
+        }
319
+
320
+        // opening parametric mixin
321
+        if ($this->tag($tag, true) && $this->argumentDef($args, $isVararg) &&
322
+            $this->guards($guards) &&
323
+            $this->literal('{')
324
+        ) {
325
+            $block = $this->pushBlock($this->fixTags(array($tag)));
326
+            $block->args = $args;
327
+            $block->isVararg = $isVararg;
328
+            if (!empty($guards)) {
329
+                $block->guards = $guards;
330
+            }
331
+            return true;
332
+        } else {
333
+            $this->seek($s);
334
+        }
335
+
336
+        // opening a simple block
337
+        if ($this->tags($tags) && $this->literal('{', false)) {
338
+            $tags = $this->fixTags($tags);
339
+            $this->pushBlock($tags);
340
+            return true;
341
+        } else {
342
+            $this->seek($s);
343
+        }
344
+
345
+        // closing a block
346
+        if ($this->literal('}', false)) {
347
+            try {
348
+                $block = $this->pop();
349
+            } catch (exception $e) {
350
+                $this->seek($s);
351
+                $this->throwError($e->getMessage());
352
+            }
353
+
354
+            $hidden = false;
355
+            if (is_null($block->type)) {
356
+                $hidden = true;
357
+                if (!isset($block->args)) {
358
+                    foreach ($block->tags as $tag) {
359
+                        if (!is_string($tag) || $tag[0] != $this->lessc->mPrefix) {
360
+                            $hidden = false;
361
+                            break;
362
+                        }
363
+                    }
364
+                }
365
+
366
+                foreach ($block->tags as $tag) {
367
+                    if (is_string($tag)) {
368
+                        $this->env->children[$tag][] = $block;
369
+                    }
370
+                }
371
+            }
372
+
373
+            if (!$hidden) {
374
+                $this->append(array('block', $block), $s);
375
+            }
376
+
377
+            // this is done here so comments aren't bundled into he block that
378
+            // was just closed
379
+            $this->whitespace();
380
+            return true;
381
+        }
382
+
383
+        // mixin
384
+        if ($this->mixinTags($tags) &&
385
+            $this->argumentDef($argv, $isVararg) &&
386
+            $this->keyword($suffix)  && $this->end()
387
+        ) {
388
+            $tags = $this->fixTags($tags);
389
+            $this->append(array('mixin', $tags, $argv, $suffix), $s);
390
+            return true;
391
+        } else {
392
+            $this->seek($s);
393
+        }
394
+
395
+        // spare ;
396
+        if ($this->literal(';')) {
397
+            return true;
398
+        }
399
+
400
+        return false; // got nothing, throw error
401
+    }
402
+
403
+    protected function isDirective($dirname, $directives)
404
+    {
405
+        // TODO: cache pattern in parser
406
+        $pattern = implode(
407
+            "|",
408
+            array_map(array("lessc", "preg_quote"), $directives)
409
+        );
410
+        $pattern = '/^(-[a-z-]+-)?('.$pattern.')$/i';
411
+
412
+        return preg_match($pattern, $dirname);
413
+    }
414
+
415
+    protected function fixTags($tags)
416
+    {
417
+        // move @ tags out of variable namespace
418
+        foreach ($tags as &$tag) {
419
+            if ($tag[0] == $this->lessc->vPrefix) {
420
+                $tag[0] = $this->lessc->mPrefix;
421
+            }
422
+        }
423
+        return $tags;
424
+    }
425
+
426
+    // a list of expressions
427
+    protected function expressionList(&$exps)
428
+    {
429
+        $exp = null;
430
+
431
+        $values = array();
432
+
433
+        while ($this->expression($exp)) {
434
+            $values[] = $exp;
435
+        }
436
+
437
+        if (count($values) == 0) {
438
+            return false;
439
+        }
440
+
441
+        $exps = Lessc::compressList($values, ' ');
442
+        return true;
443
+    }
444
+
445
+    /**
446
+     * Attempt to consume an expression.
447
+     * @link http://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudo-code
448
+     */
449
+    protected function expression(&$out)
450
+    {
451
+        $lhs = null;
452
+        $rhs = null;
453
+
454
+        if ($this->value($lhs)) {
455
+            $out = $this->expHelper($lhs, 0);
456
+
457
+            // look for / shorthand
458
+            if (!empty($this->env->supressedDivision)) {
459
+                unset($this->env->supressedDivision);
460
+                $s = $this->seek();
461
+                if ($this->literal("/") && $this->value($rhs)) {
462
+                    $out = array("list", "",
463
+                        array($out, array("keyword", "/"), $rhs));
464
+                } else {
465
+                    $this->seek($s);
466
+                }
467
+            }
468
+
469
+            return true;
470
+        }
471
+        return false;
472
+    }
473
+
474
+    /**
475
+     * recursively parse infix equation with $lhs at precedence $minP
476
+     */
477
+    protected function expHelper($lhs, $minP)
478
+    {
479
+        $next = null;
480
+        $rhs = null;
481
+
482
+        $this->inExp = true;
483
+        $ss = $this->seek();
484
+
485
+        while (true) {
486
+            $whiteBefore = isset($this->buffer[$this->count - 1]) &&
487
+                ctype_space($this->buffer[$this->count - 1]);
488
+
489
+            // If there is whitespace before the operator, then we require
490
+            // whitespace after the operator for it to be an expression
491
+            $needWhite = $whiteBefore && !$this->inParens;
492
+
493
+            $m = array();
494
+            if ($this->match(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) {
495
+                if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) {
496
+                    foreach (self::$supressDivisionProps as $pattern) {
497
+                        if (preg_match($pattern, $this->env->currentProperty)) {
498
+                            $this->env->supressedDivision = true;
499
+                            break 2;
500
+                        }
501
+                    }
502
+                }
503
+
504
+
505
+                $whiteAfter = isset($this->buffer[$this->count - 1]) &&
506
+                    ctype_space($this->buffer[$this->count - 1]);
507
+
508
+                if (!$this->value($rhs)) {
509
+                    break;
510
+                }
511
+
512
+                // peek for next operator to see what to do with rhs
513
+                if ($this->peek(self::$operatorString, $next) && self::$precedence[$next[1]] > self::$precedence[$m[1]]) {
514
+                    $rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
515
+                }
516
+
517
+                $lhs = array('expression', $m[1], $lhs, $rhs, $whiteBefore, $whiteAfter);
518
+                $ss = $this->seek();
519
+
520
+                continue;
521
+            }
522
+
523
+            break;
524
+        }
525
+
526
+        $this->seek($ss);
527
+
528
+        return $lhs;
529
+    }
530
+
531
+    // consume a list of values for a property
532
+    public function propertyValue(&$value, $keyName = null)
533
+    {
534
+        $v = null;
535
+        $values = array();
536
+
537
+        if ($keyName !== null) {
538
+            $this->env->currentProperty = $keyName;
539
+        }
540
+
541
+        $s = null;
542
+        while ($this->expressionList($v)) {
543
+            $values[] = $v;
544
+            $s = $this->seek();
545
+            if (!$this->literal(',')) {
546
+                break;
547
+            }
548
+        }
549
+
550
+        if ($s) {
551
+            $this->seek($s);
552
+        }
553
+
554
+        if ($keyName !== null) {
555
+            unset($this->env->currentProperty);
556
+        }
557
+
558
+        if (count($values) == 0) {
559
+            return false;
560
+        }
561
+
562
+        $value = Lessc::compressList($values, ', ');
563
+        return true;
564
+    }
565
+
566
+    protected function parenValue(&$out)
567
+    {
568
+        $exp = null;
569
+
570
+        $s = $this->seek();
571
+
572
+        // speed shortcut
573
+        if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "(") {
574
+            return false;
575
+        }
576
+
577
+        $inParens = $this->inParens;
578
+        if ($this->literal("(") &&
579
+            ($this->inParens = true) && $this->expression($exp) &&
580
+            $this->literal(")")
581
+        ) {
582
+            $out = $exp;
583
+            $this->inParens = $inParens;
584
+            return true;
585
+        } else {
586
+            $this->inParens = $inParens;
587
+            $this->seek($s);
588
+        }
589
+
590
+        return false;
591
+    }
592
+
593
+    // a single value
594
+    protected function value(&$value)
595
+    {
596
+        $inner = null;
597
+        $word = null;
598
+        $str = null;
599
+        $var = null;
600
+
601
+        $s = $this->seek();
602
+
603
+        // speed shortcut
604
+        if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "-") {
605
+            // negation
606
+            if ($this->literal("-", false) &&
607
+                (($this->variable($inner) && $inner = array("variable", $inner)) ||
608
+                $this->unit($inner) ||
609
+                $this->parenValue($inner))
610
+            ) {
611
+                $value = array("unary", "-", $inner);
612
+                return true;
613
+            } else {
614
+                $this->seek($s);
615
+            }
616
+        }
617
+
618
+        if ($this->parenValue($value)) {
619
+            return true;
620
+        }
621
+        if ($this->unit($value)) {
622
+            return true;
623
+        }
624
+        if ($this->color($value)) {
625
+            return true;
626
+        }
627
+        if ($this->func($value)) {
628
+            return true;
629
+        }
630
+        if ($this->string($value)) {
631
+            return true;
632
+        }
633
+
634
+        if ($this->keyword($word)) {
635
+            $value = array('keyword', $word);
636
+            return true;
637
+        }
638
+
639
+        // try a variable
640
+        if ($this->variable($var)) {
641
+            $value = array('variable', $var);
642
+            return true;
643
+        }
644
+
645
+        // unquote string (should this work on any type?
646
+        if ($this->literal("~") && $this->string($str)) {
647
+            $value = array("escape", $str);
648
+            return true;
649
+        } else {
650
+            $this->seek($s);
651
+        }
652
+
653
+        // css hack: \0
654
+        $m = array();
655
+        if ($this->literal('\\') && $this->match('([0-9]+)', $m)) {
656
+            $value = array('keyword', '\\'.$m[1]);
657
+            return true;
658
+        } else {
659
+            $this->seek($s);
660
+        }
661
+
662
+        return false;
663
+    }
664
+
665
+    // an import statement
666
+    protected function import(&$out, $value = '')
667
+    {
668
+        if (!$this->literal('@import')) {
669
+            return false;
670
+        }
671
+
672
+        // @import "something.css" media;
673
+        // @import url("something.css") media;
674
+        // @import url(something.css) media;
675
+
676
+        if ($this->propertyValue($value)) {
677
+            $out = array("import", $value);
678
+            return true;
679
+        }
680
+
681
+        return false;
682
+    }
683
+
684
+    protected function mediaQueryList(&$out)
685
+    {
686
+        $list = null;
687
+
688
+        if ($this->genericList($list, "mediaQuery", ",", false)) {
689
+            $out = $list[2];
690
+            return true;
691
+        }
692
+        return false;
693
+    }
694
+
695
+    protected function mediaQuery(&$out)
696
+    {
697
+        $mediaType = null;
698
+
699
+        $s = $this->seek();
700
+
701
+        $expressions = null;
702
+        $parts = array();
703
+
704
+        if ((($this->literal("only") && ($only = true)) || ($this->literal("not") && ($not = true))) && $this->keyword($mediaType)) {
705
+            $prop = array("mediaType");
706
+            if (isset($only)) {
707
+                $prop[] = "only";
708
+            }
709
+            if (isset($not)) {
710
+                $prop[] = "not";
711
+            }
712
+            $prop[] = $mediaType;
713
+            $parts[] = $prop;
714
+        } else {
715
+            $this->seek($s);
716
+        }
717
+
718
+
719
+        if (!empty($mediaType) && !$this->literal("and")) {
720
+            // ~
721
+        } else {
722
+            $this->genericList($expressions, "mediaExpression", "and", false);
723
+            if (is_array($expressions)) {
724
+                $parts = array_merge($parts, $expressions[2]);
725
+            }
726
+        }
727
+
728
+        if (count($parts) == 0) {
729
+            $this->seek($s);
730
+            return false;
731
+        }
732
+
733
+        $out = $parts;
734
+        return true;
735
+    }
736
+
737
+    protected function mediaExpression(&$out)
738
+    {
739
+        $feature = null;
740
+        $variable = null;
741
+
742
+        $s = $this->seek();
743
+        $value = null;
744
+        if ($this->literal("(") &&
745
+            $this->keyword($feature) &&
746
+            ($this->literal(":") && $this->expression($value)) &&
747
+            $this->literal(")")
748
+        ) {
749
+            $out = array("mediaExp", $feature);
750
+            if ($value) {
751
+                $out[] = $value;
752
+            }
753
+            return true;
754
+        } elseif ($this->variable($variable)) {
755
+            $out = array('variable', $variable);
756
+            return true;
757
+        }
758
+
759
+        $this->seek($s);
760
+        return false;
761
+    }
762
+
763
+    // an unbounded string stopped by $end
764
+    protected function openString($end, &$out, $nestingOpen = null, $rejectStrs = null)
765
+    {
766
+        $str = null;
767
+        $inter = null;
768
+
769
+        $oldWhite = $this->eatWhiteDefault;
770
+        $this->eatWhiteDefault = false;
771
+
772
+        $stop = array("'", '"', "@{", $end);
773
+        $stop = array_map(array("lessc", "preg_quote"), $stop);
774
+        // $stop[] = self::$commentMulti;
775
+
776
+        if (!is_null($rejectStrs)) {
777
+            $stop = array_merge($stop, $rejectStrs);
778
+        }
779
+
780
+        $patt = '(.*?)('.implode("|", $stop).')';
781
+
782
+        $nestingLevel = 0;
783
+
784
+        $content = array();
785
+        $m = array();
786
+        while ($this->match($patt, $m, false)) {
787
+            if (!empty($m[1])) {
788
+                $content[] = $m[1];
789
+                if ($nestingOpen) {
790
+                    $nestingLevel += substr_count($m[1], $nestingOpen);
791
+                }
792
+            }
793
+
794
+            $tok = $m[2];
795
+
796
+            $this->count -= strlen($tok);
797
+            if ($tok == $end) {
798
+                if ($nestingLevel == 0) {
799
+                    break;
800
+                } else {
801
+                    $nestingLevel--;
802
+                }
803
+            }
804
+
805
+            if (($tok == "'" || $tok == '"') && $this->string($str)) {
806
+                $content[] = $str;
807
+                continue;
808
+            }
809
+
810
+            if ($tok == "@{" && $this->interpolation($inter)) {
811
+                $content[] = $inter;
812
+                continue;
813
+            }
814
+
815
+            if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) {
816
+                break;
817
+            }
818
+
819
+            $content[] = $tok;
820
+            $this->count += strlen($tok);
821
+        }
822
+
823
+        $this->eatWhiteDefault = $oldWhite;
824
+
825
+        if (count($content) == 0) {
826
+            return false;
827
+        }
828
+
829
+        // trim the end
830
+        if (is_string(end($content))) {
831
+            $content[count($content) - 1] = rtrim(end($content));
832
+        }
833
+
834
+        $out = array("string", "", $content);
835
+        return true;
836
+    }
837
+
838
+    protected function string(&$out)
839
+    {
840
+        $inter = null;
841
+
842
+        $s = $this->seek();
843
+        if ($this->literal('"', false)) {
844
+            $delim = '"';
845
+        } elseif ($this->literal("'", false)) {
846
+            $delim = "'";
847
+        } else {
848
+            return false;
849
+        }
850
+
851
+        $content = array();
852
+
853
+        // look for either ending delim , escape, or string interpolation
854
+        $patt = '([^\n]*?)(@\{|\\\\|'.
855
+            Lessc::preg_quote($delim).')';
856
+
857
+        $oldWhite = $this->eatWhiteDefault;
858
+        $this->eatWhiteDefault = false;
859
+
860
+        $m = array();
861
+        while ($this->match($patt, $m, false)) {
862
+            $content[] = $m[1];
863
+            if ($m[2] == "@{") {
864
+                $this->count -= strlen($m[2]);
865
+                if ($this->interpolation($inter)) {
866
+                    $content[] = $inter;
867
+                } else {
868
+                    $this->count += strlen($m[2]);
869
+                    $content[] = "@{"; // ignore it
870
+                }
871
+            } elseif ($m[2] == '\\') {
872
+                $content[] = $m[2];
873
+                if ($this->literal($delim, false)) {
874
+                    $content[] = $delim;
875
+                }
876
+            } else {
877
+                $this->count -= strlen($delim);
878
+                break; // delim
879
+            }
880
+        }
881
+
882
+        $this->eatWhiteDefault = $oldWhite;
883
+
884
+        if ($this->literal($delim)) {
885
+            $out = array("string", $delim, $content);
886
+            return true;
887
+        }
888
+
889
+        $this->seek($s);
890
+        return false;
891
+    }
892
+
893
+    protected function interpolation(&$out)
894
+    {
895
+        $interp = array();
896
+
897
+        $oldWhite = $this->eatWhiteDefault;
898
+        $this->eatWhiteDefault = true;
899
+
900
+        $s = $this->seek();
901
+        if ($this->literal("@{") &&
902
+            $this->openString("}", $interp, null, array("'", '"', ";")) &&
903
+            $this->literal("}", false)
904
+        ) {
905
+            $out = array("interpolate", $interp);
906
+            $this->eatWhiteDefault = $oldWhite;
907
+            if ($this->eatWhiteDefault) {
908
+                $this->whitespace();
909
+            }
910
+            return true;
911
+        }
912
+
913
+        $this->eatWhiteDefault = $oldWhite;
914
+        $this->seek($s);
915
+        return false;
916
+    }
917
+
918
+    protected function unit(&$unit)
919
+    {
920
+        $m = array();
921
+
922
+        // speed shortcut
923
+        if (isset($this->buffer[$this->count])) {
924
+            $char = $this->buffer[$this->count];
925
+            if (!ctype_digit($char) && $char != ".") {
926
+                return false;
927
+            }
928
+        }
929
+
930
+        if ($this->match('([0-9]+(?:\.[0-9]*)?|\.[0-9]+)([%a-zA-Z]+)?', $m)) {
931
+            $unit = array("number", $m[1], empty($m[2]) ? "" : $m[2]);
932
+            return true;
933
+        }
934
+        return false;
935
+    }
936
+
937
+    // a # color
938
+    protected function color(&$out)
939
+    {
940
+        $m = array();
941
+
942
+        if ($this->match('(#(?:[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3}))', $m)) {
943
+            if (strlen($m[1]) > 7) {
944
+                $out = array("string", "", array($m[1]));
945
+            } else {
946
+                $out = array("raw_color", $m[1]);
947
+            }
948
+            return true;
949
+        }
950
+
951
+        return false;
952
+    }
953
+
954
+    // consume an argument definition list surrounded by ()
955
+    // each argument is a variable name with optional value
956
+    // or at the end a ... or a variable named followed by ...
957
+    // arguments are separated by , unless a ; is in the list, then ; is the
958
+    // delimiter.
959
+    protected function argumentDef(&$args, &$isVararg)
960
+    {
961
+        $value = array();
962
+        $rhs = null;
963
+
964
+        $s = $this->seek();
965
+        if (!$this->literal('(')) {
966
+            return false;
967
+        }
968
+
969
+        $values = array();
970
+        $delim = ",";
971
+        $method = "expressionList";
972
+
973
+        $isVararg = false;
974
+        while (true) {
975
+            if ($this->literal("...")) {
976
+                $isVararg = true;
977
+                break;
978
+            }
979
+
980
+            if ($this->$method($value)) {
981
+                if ($value[0] == "variable") {
982
+                    $arg = array("arg", $value[1]);
983
+                    $ss = $this->seek();
984
+
985
+                    if ($this->assign() && $this->$method($rhs)) {
986
+                        $arg[] = $rhs;
987
+                    } else {
988
+                        $this->seek($ss);
989
+                        if ($this->literal("...")) {
990
+                            $arg[0] = "rest";
991
+                            $isVararg = true;
992
+                        }
993
+                    }
994
+
995
+                    $values[] = $arg;
996
+                    if ($isVararg) {
997
+                        break;
998
+                    }
999
+                    continue;
1000
+                } else {
1001
+                    $values[] = array("lit", $value);
1002
+                }
1003
+            }
1004
+
1005
+
1006
+            if (!$this->literal($delim)) {
1007
+                if ($delim == "," && $this->literal(";")) {
1008
+                    // found new delim, convert existing args
1009
+                    $delim = ";";
1010
+                    $method = "propertyValue";
1011
+
1012
+                    // transform arg list
1013
+                    if (isset($values[1])) { // 2 items
1014
+                        $newList = array();
1015
+                        foreach ($values as $i => $arg) {
1016
+                            switch ($arg[0]) {
1017
+                                case "arg":
1018
+                                    if ($i) {
1019
+                                        $this->throwError("Cannot mix ; and , as delimiter types");
1020
+                                    }
1021
+                                    $newList[] = $arg[2];
1022
+                                    break;
1023
+                                case "lit":
1024
+                                    $newList[] = $arg[1];
1025
+                                    break;
1026
+                                case "rest":
1027
+                                    $this->throwError("Unexpected rest before semicolon");
1028
+                            }
1029
+                        }
1030
+
1031
+                        $newList = array("list", ", ", $newList);
1032
+
1033
+                        switch ($values[0][0]) {
1034
+                            case "arg":
1035
+                                $newArg = array("arg", $values[0][1], $newList);
1036
+                                break;
1037
+                            case "lit":
1038
+                                $newArg = array("lit", $newList);
1039
+                                break;
1040
+                        }
1041
+
1042
+                    } elseif ($values) { // 1 item
1043
+                        $newArg = $values[0];
1044
+                    }
1045
+
1046
+                    if ($newArg) {
1047
+                        $values = array($newArg);
1048
+                    }
1049
+                } else {
1050
+                    break;
1051
+                }
1052
+            }
1053
+        }
1054
+
1055
+        if (!$this->literal(')')) {
1056
+            $this->seek($s);
1057
+            return false;
1058
+        }
1059
+
1060
+        $args = $values;
1061
+
1062
+        return true;
1063
+    }
1064
+
1065
+    // consume a list of tags
1066
+    // this accepts a hanging delimiter
1067
+    protected function tags(&$tags, $simple = false, $delim = ',')
1068
+    {
1069
+        $tt = array();
1070
+
1071
+        $tags = array();
1072
+        while ($this->tag($tt, $simple)) {
1073
+            $tags[] = $tt;
1074
+            if (!$this->literal($delim)) {
1075
+                break;
1076
+            }
1077
+        }
1078
+        if (count($tags) == 0) {
1079
+            return false;
1080
+        }
1081
+
1082
+        return true;
1083
+    }
1084
+
1085
+    // list of tags of specifying mixin path
1086
+    // optionally separated by > (lazy, accepts extra >)
1087
+    protected function mixinTags(&$tags)
1088
+    {
1089
+        $tt = array();
1090
+
1091
+        $tags = array();
1092
+        while ($this->tag($tt, true)) {
1093
+            $tags[] = $tt;
1094
+            $this->literal(">");
1095
+        }
1096
+
1097
+        if (!$tags) {
1098
+            return false;
1099
+        }
1100
+
1101
+        return true;
1102
+    }
1103
+
1104
+    // a bracketed value (contained within in a tag definition)
1105
+    protected function tagBracket(&$parts, &$hasExpression)
1106
+    {
1107
+        $str = null;
1108
+        $inter = null;
1109
+        $word = null;
1110
+
1111
+        // speed shortcut
1112
+        if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "[") {
1113
+            return false;
1114
+        }
1115
+
1116
+        $s = $this->seek();
1117
+
1118
+        $hasInterpolation = false;
1119
+
1120
+        if ($this->literal("[", false)) {
1121
+            $attrParts = array("[");
1122
+            // keyword, string, operator
1123
+            while (true) {
1124
+                if ($this->literal("]", false)) {
1125
+                    $this->count--;
1126
+                    break; // get out early
1127
+                }
1128
+
1129
+                $m = array();
1130
+                if ($this->match('\s+', $m)) {
1131
+                    $attrParts[] = " ";
1132
+                    continue;
1133
+                }
1134
+                if ($this->string($str)) {
1135
+                    // escape parent selector, (yuck)
1136
+                    foreach ($str[2] as &$chunk) {
1137
+                        $chunk = str_replace($this->lessc->parentSelector, "$&$", $chunk);
1138
+                    }
1139
+
1140
+                    $attrParts[] = $str;
1141
+                    $hasInterpolation = true;
1142
+                    continue;
1143
+                }
1144
+
1145
+                if ($this->keyword($word)) {
1146
+                    $attrParts[] = $word;
1147
+                    continue;
1148
+                }
1149
+
1150
+                if ($this->interpolation($inter)) {
1151
+                    $attrParts[] = $inter;
1152
+                    $hasInterpolation = true;
1153
+                    continue;
1154
+                }
1155
+
1156
+                // operator, handles attr namespace too
1157
+                if ($this->match('[|-~\$\*\^=]+', $m)) {
1158
+                    $attrParts[] = $m[0];
1159
+                    continue;
1160
+                }
1161
+
1162
+                break;
1163
+            }
1164
+
1165
+            if ($this->literal("]", false)) {
1166
+                $attrParts[] = "]";
1167
+                foreach ($attrParts as $part) {
1168
+                    $parts[] = $part;
1169
+                }
1170
+                $hasExpression = $hasExpression || $hasInterpolation;
1171
+                return true;
1172
+            }
1173
+            $this->seek($s);
1174
+        }
1175
+
1176
+        $this->seek($s);
1177
+        return false;
1178
+    }
1179
+
1180
+    // a space separated list of selectors
1181
+    protected function tag(&$tag, $simple = false)
1182
+    {
1183
+        $interp = null;
1184
+        $unit = null;
1185
+
1186
+        if ($simple) {
1187
+            $chars = '^@,:;{}\][>\(\) "\'';
1188
+        } else {
1189
+            $chars = '^@,;{}["\'';
1190
+        }
1191
+        $s = $this->seek();
1192
+
1193
+        $hasExpression = false;
1194
+        $parts = array();
1195
+        while ($this->tagBracket($parts, $hasExpression));
1196
+
1197
+        $oldWhite = $this->eatWhiteDefault;
1198
+        $this->eatWhiteDefault = false;
1199
+
1200
+        while (true) {
1201
+            $m = array();
1202
+            if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) {
1203
+                $parts[] = $m[1];
1204
+                if ($simple) {
1205
+                    break;
1206
+                }
1207
+
1208
+                while ($this->tagBracket($parts, $hasExpression));
1209
+                continue;
1210
+            }
1211
+
1212
+            if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") {
1213
+                if ($this->interpolation($interp)) {
1214
+                    $hasExpression = true;
1215
+                    $interp[2] = true; // don't unescape
1216
+                    $parts[] = $interp;
1217
+                    continue;
1218
+                }
1219
+
1220
+                if ($this->literal("@")) {
1221
+                    $parts[] = "@";
1222
+                    continue;
1223
+                }
1224
+            }
1225
+
1226
+            if ($this->unit($unit)) { // for keyframes
1227
+                $parts[] = $unit[1];
1228
+                $parts[] = $unit[2];
1229
+                continue;
1230
+            }
1231
+
1232
+            break;
1233
+        }
1234
+
1235
+        $this->eatWhiteDefault = $oldWhite;
1236
+        if (!$parts) {
1237
+            $this->seek($s);
1238
+            return false;
1239
+        }
1240
+
1241
+        if ($hasExpression) {
1242
+            $tag = array("exp", array("string", "", $parts));
1243
+        } else {
1244
+            $tag = trim(implode($parts));
1245
+        }
1246
+
1247
+        $this->whitespace();
1248
+        return true;
1249
+    }
1250
+
1251
+    // a css function
1252
+    protected function func(&$func)
1253
+    {
1254
+        $s = $this->seek();
1255
+
1256
+        $m = array();
1257
+        $value = array();
1258
+        $string = array();
1259
+        $name = null;
1260
+
1261
+        if ($this->match('(%|[\w\-_][\w\-_:\.]+|[\w_])', $m) && $this->literal('(')) {
1262
+            $fname = $m[1];
1263
+
1264
+            $sPreArgs = $this->seek();
1265
+
1266
+            $args = array();
1267
+            while (true) {
1268
+                $ss = $this->seek();
1269
+                // this ugly nonsense is for ie filter properties
1270
+                if ($this->keyword($name) && $this->literal('=') && $this->expressionList($value)) {
1271
+                    $args[] = array("string", "", array($name, "=", $value));
1272
+                } else {
1273
+                    $this->seek($ss);
1274
+                    if ($this->expressionList($value)) {
1275
+                        $args[] = $value;
1276
+                    }
1277
+                }
1278
+
1279
+                if (!$this->literal(',')) {
1280
+                    break;
1281
+                }
1282
+            }
1283
+            $args = array('list', ',', $args);
1284
+
1285
+            if ($this->literal(')')) {
1286
+                $func = array('function', $fname, $args);
1287
+                return true;
1288
+            } elseif ($fname == 'url') {
1289
+                // couldn't parse and in url? treat as string
1290
+                $this->seek($sPreArgs);
1291
+                if ($this->openString(")", $string) && $this->literal(")")) {
1292
+                    $func = array('function', $fname, $string);
1293
+                    return true;
1294
+                }
1295
+            }
1296
+        }
1297
+
1298
+        $this->seek($s);
1299
+        return false;
1300
+    }
1301
+
1302
+    // consume a less variable
1303
+    protected function variable(&$name)
1304
+    {
1305
+        $sub = null;
1306
+        $name = null;
1307
+
1308
+        $s = $this->seek();
1309
+        if ($this->literal($this->lessc->vPrefix, false) &&
1310
+            ($this->variable($sub) || $this->keyword($name))
1311
+        ) {
1312
+            if (!empty($sub)) {
1313
+                $name = array('variable', $sub);
1314
+            } else {
1315
+                $name = $this->lessc->vPrefix.$name;
1316
+            }
1317
+            return true;
1318
+        }
1319
+
1320
+        $name = null;
1321
+        $this->seek($s);
1322
+        return false;
1323
+    }
1324
+
1325
+    /**
1326
+     * Consume an assignment operator
1327
+     * Can optionally take a name that will be set to the current property name
1328
+     */
1329
+    protected function assign($name = null)
1330
+    {
1331
+        if ($name) {
1332
+            $this->currentProperty = $name;
1333
+        }
1334
+        return $this->literal(':') || $this->literal('=');
1335
+    }
1336
+
1337
+    // consume a keyword
1338
+    protected function keyword(&$word)
1339
+    {
1340
+        $m = array();
1341
+        if ($this->match('([\w_\-\*!"][\w\-_"]*)', $m)) {
1342
+            $word = $m[1];
1343
+            return true;
1344
+        }
1345
+        return false;
1346
+    }
1347
+
1348
+    // consume an end of statement delimiter
1349
+    protected function end()
1350
+    {
1351
+        if ($this->literal(';', false)) {
1352
+            return true;
1353
+        } elseif ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') {
1354
+            // if there is end of file or a closing block next then we don't need a ;
1355
+            return true;
1356
+        }
1357
+        return false;
1358
+    }
1359
+
1360
+    protected function guards(&$guards)
1361
+    {
1362
+        $g = null;
1363
+
1364
+        $s = $this->seek();
1365
+
1366
+        if (!$this->literal("when")) {
1367
+            $this->seek($s);
1368
+            return false;
1369
+        }
1370
+
1371
+        $guards = array();
1372
+
1373
+        while ($this->guardGroup($g)) {
1374
+            $guards[] = $g;
1375
+            if (!$this->literal(",")) {
1376
+                break;
1377
+            }
1378
+        }
1379
+
1380
+        if (count($guards) == 0) {
1381
+            $guards = null;
1382
+            $this->seek($s);
1383
+            return false;
1384
+        }
1385
+
1386
+        return true;
1387
+    }
1388
+
1389
+    // a bunch of guards that are and'd together
1390
+    // TODO rename to guardGroup
1391
+    protected function guardGroup(&$guardGroup)
1392
+    {
1393
+        $guard = null;
1394
+
1395
+        $s = $this->seek();
1396
+        $guardGroup = array();
1397
+        while ($this->guard($guard)) {
1398
+            $guardGroup[] = $guard;
1399
+            if (!$this->literal("and")) {
1400
+                break;
1401
+            }
1402
+        }
1403
+
1404
+        if (count($guardGroup) == 0) {
1405
+            $guardGroup = null;
1406
+            $this->seek($s);
1407
+            return false;
1408
+        }
1409
+
1410
+        return true;
1411
+    }
1412
+
1413
+    protected function guard(&$guard)
1414
+    {
1415
+        $exp = null;
1416
+
1417
+        $s = $this->seek();
1418
+        $negate = $this->literal("not");
1419
+
1420
+        if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
1421
+            $guard = $exp;
1422
+            if ($negate) {
1423
+                $guard = array("negate", $guard);
1424
+            }
1425
+            return true;
1426
+        }
1427
+
1428
+        $this->seek($s);
1429
+        return false;
1430
+    }
1431
+
1432
+    /* raw parsing functions */
1433
+
1434
+    protected function literal($what, $eatWhitespace = null)
1435
+    {
1436
+        if ($eatWhitespace === null) {
1437
+            $eatWhitespace = $this->eatWhiteDefault;
1438
+        }
1439
+
1440
+        // shortcut on single letter
1441
+        if (!isset($what[1]) && isset($this->buffer[$this->count])) {
1442
+            if ($this->buffer[$this->count] == $what) {
1443
+                if (!$eatWhitespace) {
1444
+                    $this->count++;
1445
+                    return true;
1446
+                }
1447
+            // goes below...
1448
+            } else {
1449
+                return false;
1450
+            }
1451
+        }
1452
+
1453
+        if (!isset(self::$literalCache[$what])) {
1454
+            self::$literalCache[$what] = Lessc::preg_quote($what);
1455
+        }
1456
+
1457
+        $m = array();
1458
+        return $this->match(self::$literalCache[$what], $m, $eatWhitespace);
1459
+    }
1460
+
1461
+    protected function genericList(&$out, $parseItem, $delim = "", $flatten = true)
1462
+    {
1463
+        $value = null;
1464
+
1465
+        $s = $this->seek();
1466
+        $items = array();
1467
+        while ($this->$parseItem($value)) {
1468
+            $items[] = $value;
1469
+            if ($delim) {
1470
+                if (!$this->literal($delim)) {
1471
+                    break;
1472
+                }
1473
+            }
1474
+        }
1475
+
1476
+        if (count($items) == 0) {
1477
+            $this->seek($s);
1478
+            return false;
1479
+        }
1480
+
1481
+        if ($flatten && count($items) == 1) {
1482
+            $out = $items[0];
1483
+        } else {
1484
+            $out = array("list", $delim, $items);
1485
+        }
1486
+
1487
+        return true;
1488
+    }
1489
+
1490
+
1491
+    // advance counter to next occurrence of $what
1492
+    // $until - don't include $what in advance
1493
+    // $allowNewline, if string, will be used as valid char set
1494
+    protected function to($what, &$out, $until = false, $allowNewline = false)
1495
+    {
1496
+        if (is_string($allowNewline)) {
1497
+            $validChars = $allowNewline;
1498
+        } else {
1499
+            $validChars = $allowNewline ? "." : "[^\n]";
1500
+        }
1501
+        $m = array();
1502
+        if (!$this->match('('.$validChars.'*?)'.Lessc::preg_quote($what), $m, !$until)) {
1503
+            return false;
1504
+        }
1505
+        if ($until) {
1506
+            $this->count -= strlen($what); // give back $what
1507
+        }
1508
+        $out = $m[1];
1509
+        return true;
1510
+    }
1511
+
1512
+    // try to match something on head of buffer
1513
+    protected function match($regex, &$out, $eatWhitespace = null)
1514
+    {
1515
+        if ($eatWhitespace === null) {
1516
+            $eatWhitespace = $this->eatWhiteDefault;
1517
+        }
1518
+
1519
+        $r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais';
1520
+        if (preg_match($r, $this->buffer, $out, 0, $this->count)) {
1521
+            $this->count += strlen($out[0]);
1522
+            if ($eatWhitespace && $this->writeComments) {
1523
+                $this->whitespace();
1524
+            }
1525
+            return true;
1526
+        }
1527
+        return false;
1528
+    }
1529
+
1530
+    // match some whitespace
1531
+    protected function whitespace()
1532
+    {
1533
+        if ($this->writeComments) {
1534
+            $gotWhite = false;
1535
+            $m = array();
1536
+            while (preg_match(self::$whitePattern, $this->buffer, $m, 0, $this->count)) {
1537
+                if (isset($m[1]) && empty($this->seenComments[$this->count])) {
1538
+                    $this->append(array("comment", $m[1]));
1539
+                    $this->seenComments[$this->count] = true;
1540
+                }
1541
+                $this->count += strlen($m[0]);
1542
+                $gotWhite = true;
1543
+            }
1544
+            return $gotWhite;
1545
+        } else {
1546
+            $this->match("", $m);
1547
+            return strlen($m[0]) > 0;
1548
+        }
1549
+    }
1550
+
1551
+    // match something without consuming it
1552
+    protected function peek($regex, &$out = null, $from = null)
1553
+    {
1554
+        if (is_null($from)) {
1555
+            $from = $this->count;
1556
+        }
1557
+        $r = '/'.$regex.'/Ais';
1558
+        $result = preg_match($r, $this->buffer, $out, 0, $from);
1559
+
1560
+        return $result;
1561
+    }
1562
+
1563
+    // seek to a spot in the buffer or return where we are on no argument
1564
+    protected function seek($where = null)
1565
+    {
1566
+        if ($where === null) {
1567
+            return $this->count;
1568
+        } else {
1569
+            $this->count = $where;
1570
+        }
1571
+        return true;
1572
+    }
1573
+
1574
+    /* misc functions */
1575
+
1576
+    public function throwError($msg = "parse error", $count = null)
1577
+    {
1578
+        $count = is_null($count) ? $this->count : $count;
1579
+
1580
+        $line = $this->line +
1581
+            substr_count(substr($this->buffer, 0, $count), "\n");
1582
+
1583
+        if (!empty($this->sourceName)) {
1584
+            $loc = "$this->sourceName on line $line";
1585
+        } else {
1586
+            $loc = "line: $line";
1587
+        }
1588
+
1589
+        // TODO this depends on $this->count
1590
+        $m = array();
1591
+        if ($this->peek("(.*?)(\n|$)", $m, $count)) {
1592
+            throw new exception("$msg: failed at `$m[1]` $loc");
1593
+        } else {
1594
+            throw new exception("$msg: $loc");
1595
+        }
1596
+    }
1597
+
1598
+    protected function pushBlock($selectors = null, $type = null)
1599
+    {
1600
+        $b = new stdclass();
1601
+        $b->parent = $this->env;
1602
+
1603
+        $b->type = $type;
1604
+        $b->id = self::$nextBlockId++;
1605
+
1606
+        $b->isVararg = false; // TODO: kill me from here
1607
+        $b->tags = $selectors;
1608
+
1609
+        $b->props = array();
1610
+        $b->children = array();
1611
+
1612
+        $this->env = $b;
1613
+        return $b;
1614
+    }
1615
+
1616
+    // push a block that doesn't multiply tags
1617
+    protected function pushSpecialBlock($type)
1618
+    {
1619
+        return $this->pushBlock(null, $type);
1620
+    }
1621
+
1622
+    // append a property to the current block
1623
+    protected function append($prop, $pos = null)
1624
+    {
1625
+        if ($pos !== null) {
1626
+            $prop[-1] = $pos;
1627
+        }
1628
+        $this->env->props[] = $prop;
1629
+    }
1630
+
1631
+    // pop something off the stack
1632
+    protected function pop()
1633
+    {
1634
+        $old = $this->env;
1635
+        $this->env = $this->env->parent;
1636
+        return $old;
1637
+    }
1638
+
1639
+    // remove comments from $text
1640
+    // todo: make it work for all functions, not just url
1641
+    protected function removeComments($text)
1642
+    {
1643
+        $look = array(
1644
+            'url(', '//', '/*', '"', "'"
1645
+        );
1646
+
1647
+        $out = '';
1648
+        $min = null;
1649
+        while (true) {
1650
+            // find the next item
1651
+            foreach ($look as $token) {
1652
+                $pos = strpos($text, $token);
1653
+                if ($pos !== false) {
1654
+                    if (!isset($min) || $pos < $min[1]) {
1655
+                        $min = array($token, $pos);
1656
+                    }
1657
+                }
1658
+            }
1659
+
1660
+            if (is_null($min)) {
1661
+                break;
1662
+            }
1663
+
1664
+            $count = $min[1];
1665
+            $skip = 0;
1666
+            $newlines = 0;
1667
+            switch ($min[0]) {
1668
+                case 'url(':
1669
+                    $m = array();
1670
+                    if (preg_match('/url\(.*?\)/', $text, $m, 0, $count)) {
1671
+                        $count += strlen($m[0]) - strlen($min[0]);
1672
+                    }
1673
+                    break;
1674
+                case '"':
1675
+                case "'":
1676
+                    $m = array();
1677
+                    if (preg_match('/'.$min[0].'.*?(?<!\\\\)'.$min[0].'/', $text, $m, 0, $count)) {
1678
+                        $count += strlen($m[0]) - 1;
1679
+                    }
1680
+                    break;
1681
+                case '//':
1682
+                    $skip = strpos($text, "\n", $count);
1683
+                    if ($skip === false) {
1684
+                        $skip = strlen($text) - $count;
1685
+                    } else {
1686
+                        $skip -= $count;
1687
+                    }
1688
+                    break;
1689
+                case '/*':
1690
+                    $m = array();
1691
+                    if (preg_match('/\/\*.*?\*\//s', $text, $m, 0, $count)) {
1692
+                        $skip = strlen($m[0]);
1693
+                        $newlines = substr_count($m[0], "\n");
1694
+                    }
1695
+                    break;
1696
+            }
1697
+
1698
+            if ($skip == 0) {
1699
+                $count += strlen($min[0]);
1700
+            }
1701
+
1702
+            $out .= substr($text, 0, $count).str_repeat("\n", $newlines);
1703
+            $text = substr($text, $count + $skip);
1704
+
1705
+            $min = null;
1706
+        }
1707
+
1708
+        return $out.$text;
1709
+    }
1710 1710
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -133,17 +133,17 @@  discard block
 block discarded – undo
133 133
 
134 134
 		if (!self::$operatorString) {
135 135
 			self::$operatorString =
136
-				'('.implode('|', array_map(
136
+				'(' . implode('|', array_map(
137 137
 					array('lessc', 'preg_quote'),
138 138
 					array_keys(self::$precedence)
139
-				)).')';
139
+				)) . ')';
140 140
 
141 141
 			$commentSingle = Lessc::preg_quote(self::$commentSingle);
142 142
 			$commentMultiLeft = Lessc::preg_quote(self::$commentMultiLeft);
143 143
 			$commentMultiRight = Lessc::preg_quote(self::$commentMultiRight);
144 144
 
145
-			self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
146
-			self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
145
+			self::$commentMulti = $commentMultiLeft . '.*?' . $commentMultiRight;
146
+			self::$whitePattern = '/' . $commentSingle . '[^\n]*\s*|(' . self::$commentMulti . ')\s*|\s+/Ais';
147 147
 		}
148 148
 	}
149 149
 
@@ -176,7 +176,7 @@  discard block
 block discarded – undo
176 176
 		while (false !== $this->parseChunk());
177 177
 
178 178
 		if ($this->count != strlen($this->buffer)) {
179
-			$this->throwError('parse error count '.$this->count.' != len buffer '.strlen($this->buffer));
179
+			$this->throwError('parse error count ' . $this->count . ' != len buffer ' . strlen($this->buffer));
180 180
 
181 181
 		}
182 182
 
@@ -383,7 +383,7 @@  discard block
 block discarded – undo
383 383
 		// mixin
384 384
 		if ($this->mixinTags($tags) &&
385 385
 			$this->argumentDef($argv, $isVararg) &&
386
-			$this->keyword($suffix)  && $this->end()
386
+			$this->keyword($suffix) && $this->end()
387 387
 		) {
388 388
 			$tags = $this->fixTags($tags);
389 389
 			$this->append(array('mixin', $tags, $argv, $suffix), $s);
@@ -407,7 +407,7 @@  discard block
 block discarded – undo
407 407
 			"|",
408 408
 			array_map(array("lessc", "preg_quote"), $directives)
409 409
 		);
410
-		$pattern = '/^(-[a-z-]+-)?('.$pattern.')$/i';
410
+		$pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i';
411 411
 
412 412
 		return preg_match($pattern, $dirname);
413 413
 	}
@@ -491,7 +491,7 @@  discard block
 block discarded – undo
491 491
 			$needWhite = $whiteBefore && !$this->inParens;
492 492
 
493 493
 			$m = array();
494
-			if ($this->match(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) {
494
+			if ($this->match(self::$operatorString . ($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) {
495 495
 				if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) {
496 496
 					foreach (self::$supressDivisionProps as $pattern) {
497 497
 						if (preg_match($pattern, $this->env->currentProperty)) {
@@ -653,7 +653,7 @@  discard block
 block discarded – undo
653 653
 		// css hack: \0
654 654
 		$m = array();
655 655
 		if ($this->literal('\\') && $this->match('([0-9]+)', $m)) {
656
-			$value = array('keyword', '\\'.$m[1]);
656
+			$value = array('keyword', '\\' . $m[1]);
657 657
 			return true;
658 658
 		} else {
659 659
 			$this->seek($s);
@@ -777,7 +777,7 @@  discard block
 block discarded – undo
777 777
 			$stop = array_merge($stop, $rejectStrs);
778 778
 		}
779 779
 
780
-		$patt = '(.*?)('.implode("|", $stop).')';
780
+		$patt = '(.*?)(' . implode("|", $stop) . ')';
781 781
 
782 782
 		$nestingLevel = 0;
783 783
 
@@ -851,8 +851,8 @@  discard block
 block discarded – undo
851 851
 		$content = array();
852 852
 
853 853
 		// look for either ending delim , escape, or string interpolation
854
-		$patt = '([^\n]*?)(@\{|\\\\|'.
855
-			Lessc::preg_quote($delim).')';
854
+		$patt = '([^\n]*?)(@\{|\\\\|' .
855
+			Lessc::preg_quote($delim) . ')';
856 856
 
857 857
 		$oldWhite = $this->eatWhiteDefault;
858 858
 		$this->eatWhiteDefault = false;
@@ -1199,7 +1199,7 @@  discard block
 block discarded – undo
1199 1199
 
1200 1200
 		while (true) {
1201 1201
 			$m = array();
1202
-			if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) {
1202
+			if ($this->match('([' . $chars . '0-9][' . $chars . ']*)', $m)) {
1203 1203
 				$parts[] = $m[1];
1204 1204
 				if ($simple) {
1205 1205
 					break;
@@ -1312,7 +1312,7 @@  discard block
 block discarded – undo
1312 1312
 			if (!empty($sub)) {
1313 1313
 				$name = array('variable', $sub);
1314 1314
 			} else {
1315
-				$name = $this->lessc->vPrefix.$name;
1315
+				$name = $this->lessc->vPrefix . $name;
1316 1316
 			}
1317 1317
 			return true;
1318 1318
 		}
@@ -1499,7 +1499,7 @@  discard block
 block discarded – undo
1499 1499
 			$validChars = $allowNewline ? "." : "[^\n]";
1500 1500
 		}
1501 1501
 		$m = array();
1502
-		if (!$this->match('('.$validChars.'*?)'.Lessc::preg_quote($what), $m, !$until)) {
1502
+		if (!$this->match('(' . $validChars . '*?)' . Lessc::preg_quote($what), $m, !$until)) {
1503 1503
 			return false;
1504 1504
 		}
1505 1505
 		if ($until) {
@@ -1516,7 +1516,7 @@  discard block
 block discarded – undo
1516 1516
 			$eatWhitespace = $this->eatWhiteDefault;
1517 1517
 		}
1518 1518
 
1519
-		$r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais';
1519
+		$r = '/' . $regex . ($eatWhitespace && !$this->writeComments ? '\s*' : '') . '/Ais';
1520 1520
 		if (preg_match($r, $this->buffer, $out, 0, $this->count)) {
1521 1521
 			$this->count += strlen($out[0]);
1522 1522
 			if ($eatWhitespace && $this->writeComments) {
@@ -1554,7 +1554,7 @@  discard block
 block discarded – undo
1554 1554
 		if (is_null($from)) {
1555 1555
 			$from = $this->count;
1556 1556
 		}
1557
-		$r = '/'.$regex.'/Ais';
1557
+		$r = '/' . $regex . '/Ais';
1558 1558
 		$result = preg_match($r, $this->buffer, $out, 0, $from);
1559 1559
 
1560 1560
 		return $result;
@@ -1674,7 +1674,7 @@  discard block
 block discarded – undo
1674 1674
 				case '"':
1675 1675
 				case "'":
1676 1676
 					$m = array();
1677
-					if (preg_match('/'.$min[0].'.*?(?<!\\\\)'.$min[0].'/', $text, $m, 0, $count)) {
1677
+					if (preg_match('/' . $min[0] . '.*?(?<!\\\\)' . $min[0] . '/', $text, $m, 0, $count)) {
1678 1678
 						$count += strlen($m[0]) - 1;
1679 1679
 					}
1680 1680
 					break;
@@ -1699,12 +1699,12 @@  discard block
 block discarded – undo
1699 1699
 				$count += strlen($min[0]);
1700 1700
 			}
1701 1701
 
1702
-			$out .= substr($text, 0, $count).str_repeat("\n", $newlines);
1702
+			$out .= substr($text, 0, $count) . str_repeat("\n", $newlines);
1703 1703
 			$text = substr($text, $count + $skip);
1704 1704
 
1705 1705
 			$min = null;
1706 1706
 		}
1707 1707
 
1708
-		return $out.$text;
1708
+		return $out . $text;
1709 1709
 	}
1710 1710
 }
Please login to merge, or discard this patch.
Dolibarr/Code/Core/Classes/lessc_formatter_classic.php 2 patches
Indentation   +103 added lines, -103 removed lines patch added patch discarded remove patch
@@ -59,107 +59,107 @@
 block discarded – undo
59 59
 
60 60
 class lessc_formatter_classic
61 61
 {
62
-	public $indentChar = "  ";
63
-
64
-	public $break = "\n";
65
-	public $open = " {";
66
-	public $close = "}";
67
-	public $selectorSeparator = ", ";
68
-	public $assignSeparator = ":";
69
-
70
-	public $openSingle = " { ";
71
-	public $closeSingle = " }";
72
-
73
-	public $disableSingle = false;
74
-	public $breakSelectors = false;
75
-
76
-	public $compressColors = false;
77
-	public $indentLevel;
78
-
79
-	public function __construct()
80
-	{
81
-		$this->indentLevel = 0;
82
-	}
83
-
84
-	public function indentStr($n = 0)
85
-	{
86
-		return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
87
-	}
88
-
89
-	public function property($name, $value)
90
-	{
91
-		return $name.$this->assignSeparator.$value.";";
92
-	}
93
-
94
-	protected function isEmpty($block)
95
-	{
96
-		if (empty($block->lines)) {
97
-			foreach ($block->children as $child) {
98
-				if (!$this->isEmpty($child)) {
99
-					return false;
100
-				}
101
-			}
102
-
103
-			return true;
104
-		}
105
-		return false;
106
-	}
107
-
108
-	public function block($block)
109
-	{
110
-		if ($this->isEmpty($block)) {
111
-			return;
112
-		}
113
-
114
-		$inner = $pre = $this->indentStr();
115
-
116
-		$isSingle = !$this->disableSingle &&
117
-			is_null($block->type) && count($block->lines) == 1;
118
-
119
-		if (!empty($block->selectors)) {
120
-			$this->indentLevel++;
121
-
122
-			if ($this->breakSelectors) {
123
-				$selectorSeparator = $this->selectorSeparator.$this->break.$pre;
124
-			} else {
125
-				$selectorSeparator = $this->selectorSeparator;
126
-			}
127
-
128
-			echo $pre.
129
-				implode($selectorSeparator, $block->selectors);
130
-			if ($isSingle) {
131
-				echo $this->openSingle;
132
-				$inner = "";
133
-			} else {
134
-				echo $this->open.$this->break;
135
-				$inner = $this->indentStr();
136
-			}
137
-		}
138
-
139
-		if (!empty($block->lines)) {
140
-			$glue = $this->break.$inner;
141
-			echo $inner.implode($glue, $block->lines);
142
-			if (!$isSingle && !empty($block->children)) {
143
-				echo $this->break;
144
-			}
145
-		}
146
-
147
-		foreach ($block->children as $child) {
148
-			$this->block($child);
149
-		}
150
-
151
-		if (!empty($block->selectors)) {
152
-			if (!$isSingle && empty($block->children)) {
153
-				echo $this->break;
154
-			}
155
-
156
-			if ($isSingle) {
157
-				echo $this->closeSingle.$this->break;
158
-			} else {
159
-				echo $pre.$this->close.$this->break;
160
-			}
161
-
162
-			$this->indentLevel--;
163
-		}
164
-	}
62
+    public $indentChar = "  ";
63
+
64
+    public $break = "\n";
65
+    public $open = " {";
66
+    public $close = "}";
67
+    public $selectorSeparator = ", ";
68
+    public $assignSeparator = ":";
69
+
70
+    public $openSingle = " { ";
71
+    public $closeSingle = " }";
72
+
73
+    public $disableSingle = false;
74
+    public $breakSelectors = false;
75
+
76
+    public $compressColors = false;
77
+    public $indentLevel;
78
+
79
+    public function __construct()
80
+    {
81
+        $this->indentLevel = 0;
82
+    }
83
+
84
+    public function indentStr($n = 0)
85
+    {
86
+        return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
87
+    }
88
+
89
+    public function property($name, $value)
90
+    {
91
+        return $name.$this->assignSeparator.$value.";";
92
+    }
93
+
94
+    protected function isEmpty($block)
95
+    {
96
+        if (empty($block->lines)) {
97
+            foreach ($block->children as $child) {
98
+                if (!$this->isEmpty($child)) {
99
+                    return false;
100
+                }
101
+            }
102
+
103
+            return true;
104
+        }
105
+        return false;
106
+    }
107
+
108
+    public function block($block)
109
+    {
110
+        if ($this->isEmpty($block)) {
111
+            return;
112
+        }
113
+
114
+        $inner = $pre = $this->indentStr();
115
+
116
+        $isSingle = !$this->disableSingle &&
117
+            is_null($block->type) && count($block->lines) == 1;
118
+
119
+        if (!empty($block->selectors)) {
120
+            $this->indentLevel++;
121
+
122
+            if ($this->breakSelectors) {
123
+                $selectorSeparator = $this->selectorSeparator.$this->break.$pre;
124
+            } else {
125
+                $selectorSeparator = $this->selectorSeparator;
126
+            }
127
+
128
+            echo $pre.
129
+                implode($selectorSeparator, $block->selectors);
130
+            if ($isSingle) {
131
+                echo $this->openSingle;
132
+                $inner = "";
133
+            } else {
134
+                echo $this->open.$this->break;
135
+                $inner = $this->indentStr();
136
+            }
137
+        }
138
+
139
+        if (!empty($block->lines)) {
140
+            $glue = $this->break.$inner;
141
+            echo $inner.implode($glue, $block->lines);
142
+            if (!$isSingle && !empty($block->children)) {
143
+                echo $this->break;
144
+            }
145
+        }
146
+
147
+        foreach ($block->children as $child) {
148
+            $this->block($child);
149
+        }
150
+
151
+        if (!empty($block->selectors)) {
152
+            if (!$isSingle && empty($block->children)) {
153
+                echo $this->break;
154
+            }
155
+
156
+            if ($isSingle) {
157
+                echo $this->closeSingle.$this->break;
158
+            } else {
159
+                echo $pre.$this->close.$this->break;
160
+            }
161
+
162
+            $this->indentLevel--;
163
+        }
164
+    }
165 165
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
 
89 89
 	public function property($name, $value)
90 90
 	{
91
-		return $name.$this->assignSeparator.$value.";";
91
+		return $name . $this->assignSeparator . $value . ";";
92 92
 	}
93 93
 
94 94
 	protected function isEmpty($block)
@@ -120,25 +120,25 @@  discard block
 block discarded – undo
120 120
 			$this->indentLevel++;
121 121
 
122 122
 			if ($this->breakSelectors) {
123
-				$selectorSeparator = $this->selectorSeparator.$this->break.$pre;
123
+				$selectorSeparator = $this->selectorSeparator . $this->break . $pre;
124 124
 			} else {
125 125
 				$selectorSeparator = $this->selectorSeparator;
126 126
 			}
127 127
 
128
-			echo $pre.
128
+			echo $pre .
129 129
 				implode($selectorSeparator, $block->selectors);
130 130
 			if ($isSingle) {
131 131
 				echo $this->openSingle;
132 132
 				$inner = "";
133 133
 			} else {
134
-				echo $this->open.$this->break;
134
+				echo $this->open . $this->break;
135 135
 				$inner = $this->indentStr();
136 136
 			}
137 137
 		}
138 138
 
139 139
 		if (!empty($block->lines)) {
140
-			$glue = $this->break.$inner;
141
-			echo $inner.implode($glue, $block->lines);
140
+			$glue = $this->break . $inner;
141
+			echo $inner . implode($glue, $block->lines);
142 142
 			if (!$isSingle && !empty($block->children)) {
143 143
 				echo $this->break;
144 144
 			}
@@ -154,9 +154,9 @@  discard block
 block discarded – undo
154 154
 			}
155 155
 
156 156
 			if ($isSingle) {
157
-				echo $this->closeSingle.$this->break;
157
+				echo $this->closeSingle . $this->break;
158 158
 			} else {
159
-				echo $pre.$this->close.$this->break;
159
+				echo $pre . $this->close . $this->break;
160 160
 			}
161 161
 
162 162
 			$this->indentLevel--;
Please login to merge, or discard this patch.
Dolibarr/Code/Core/Classes/lessc_formatter_lessjs.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -62,8 +62,8 @@
 block discarded – undo
62 62
  */
63 63
 class lessc_formatter_lessjs extends lessc_formatter_classic
64 64
 {
65
-	public $disableSingle = true;
66
-	public $breakSelectors = true;
67
-	public $assignSeparator = ": ";
68
-	public $selectorSeparator = ",";
65
+    public $disableSingle = true;
66
+    public $breakSelectors = true;
67
+    public $assignSeparator = ": ";
68
+    public $selectorSeparator = ",";
69 69
 }
Please login to merge, or discard this patch.
Dolibarr/Code/Core/Classes/lessc_formatter_compressed.php 1 patch
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -62,15 +62,15 @@
 block discarded – undo
62 62
  */
63 63
 class lessc_formatter_compressed extends lessc_formatter_classic
64 64
 {
65
-	public $disableSingle = true;
66
-	public $open = "{";
67
-	public $selectorSeparator = ",";
68
-	public $assignSeparator = ":";
69
-	public $break = "";
70
-	public $compressColors = true;
65
+    public $disableSingle = true;
66
+    public $open = "{";
67
+    public $selectorSeparator = ",";
68
+    public $assignSeparator = ":";
69
+    public $break = "";
70
+    public $compressColors = true;
71 71
 
72
-	public function indentStr($n = 0)
73
-	{
74
-		return "";
75
-	}
72
+    public function indentStr($n = 0)
73
+    {
74
+        return "";
75
+    }
76 76
 }
Please login to merge, or discard this patch.
Dolibarr/Code/Commande/Classes/OrderLine.php 1 patch
Indentation   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -624,7 +624,7 @@  discard block
 block discarded – undo
624 624
         }
625 625
     }
626 626
 
627
-	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
627
+    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
628 628
     /**
629 629
      *  Update DB line fields total_xxx
630 630
      *  Used by migration
@@ -633,7 +633,7 @@  discard block
 block discarded – undo
633 633
      */
634 634
     public function update_total()
635 635
     {
636
-		// phpcs:enable
636
+        // phpcs:enable
637 637
         $this->db->begin();
638 638
 
639 639
         // Clean parameters
Please login to merge, or discard this patch.
Dolibarr/Code/Comm/Classes/PropaleLigne.php 1 patch
Indentation   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -665,7 +665,7 @@  discard block
 block discarded – undo
665 665
         }
666 666
     }
667 667
 
668
-	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
668
+    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
669 669
     /**
670 670
      *  Update DB line fields total_xxx
671 671
      *  Used by migration
@@ -674,7 +674,7 @@  discard block
 block discarded – undo
674 674
      */
675 675
     public function update_total()
676 676
     {
677
-		// phpcs:enable
677
+        // phpcs:enable
678 678
         $this->db->begin();
679 679
 
680 680
         // Mise a jour ligne en base
Please login to merge, or discard this patch.