forked from MarcWeber/phamlp
-
Notifications
You must be signed in to change notification settings - Fork 83
/
SassScriptLexer.php
executable file
·139 lines (131 loc) · 4.52 KB
/
SassScriptLexer.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<?php
/* SVN FILE: $Id$ */
/**
* SassScriptLexer class file.
* @author Chris Yates <chris.l.yates@gmail.com>
* @copyright Copyright (c) 2010 PBM Web Development
* @license http://phamlp.googlecode.com/files/license.txt
* @package PHamlP
* @subpackage Sass.script
*/
require_once 'literals/SassBoolean.php';
require_once 'literals/SassColour.php';
require_once 'literals/SassNumber.php';
require_once 'literals/SassString.php';
require_once 'literals/SassList.php';
require_once 'SassScriptFunction.php';
require_once 'SassScriptOperation.php';
require_once 'SassScriptVariable.php';
/**
* SassScriptLexer class.
* Lexes SassSCript into tokens for the parser.
*
* Implements a {@link http://en.wikipedia.org/wiki/Shunting-yard_algorithm Shunting-yard algorithm} to provide {@link http://en.wikipedia.org/wiki/Reverse_Polish_notation Reverse Polish notation} output.
* @package PHamlP
* @subpackage Sass.script
*/
class SassScriptLexer
{
const MATCH_WHITESPACE = '/^\s+/';
/**
* Static holder for last instance of SassScriptLexer
*/
public static $instance;
/**
* @var SassScriptParser the parser object
*/
public $parser;
/**
* SassScriptLexer constructor.
* @return SassScriptLexer
*/
public function __construct($parser)
{
$this->parser = $parser;
self::$instance = $this;
}
/**
* Lex an expression into SassScript tokens.
* @param string $string expression to lex
* @param SassContext $context the context in which the expression is lexed
* @return array tokens
*/
public function lex($string, $context)
{
// if it's already lexed, just return it as-is
if (is_object($string)) {
return array($string);
}
if (is_array($string)) {
return $string;
}
$tokens = array();
// whilst the string is not empty, split it into it's tokens.
while ($string !== false) {
if (($match = $this->isWhitespace($string)) !== false) {
$tokens[] = null;
} elseif (($match = SassScriptFunction::isa($string)) !== false) {
preg_match(SassScriptFunction::MATCH_FUNC, $match, $matches);
$args = array();
foreach (SassScriptFunction::extractArgs($matches[SassScriptFunction::ARGS], false, $context) as $key => $expression) {
$args[$key] = $this->parser->evaluate($expression, $context);
}
$tokens[] = new SassScriptFunction($matches[SassScriptFunction::NAME], $args);
} elseif (($match = SassBoolean::isa($string)) !== false) {
$tokens[] = new SassBoolean($match);
} elseif (($match = SassColour::isa($string)) !== false) {
$tokens[] = new SassColour($match);
} elseif (($match = SassNumber::isa($string)) !== false) {
$tokens[] = new SassNumber($match);
} elseif (($match = SassString::isa($string)) !== false) {
$stringed = new SassString($match);
if (
strlen($stringed->quote) == 0 &&
SassList::isa($string) !== false &&
// recursion loop prevented for expressions
// like "transition: -webkit-transform 1s"
!preg_match("/^\-\w+\-\w+$/", $stringed->value)
) {
$tokens[] = new SassList($string);
} else {
$tokens[] = $stringed;
}
} elseif ($string == '()') {
$match = $string;
$tokens[] = new SassList($match);
} elseif (($match = SassScriptOperation::isa($string)) !== false) {
$tokens[] = new SassScriptOperation($match);
} elseif (($match = SassScriptVariable::isa($string)) !== false) {
$tokens[] = new SassScriptVariable($match);
} else {
$_string = $string;
$match = '';
while (strlen($_string) && !$this->isWhitespace($_string)) {
foreach (SassScriptOperation::$inStrOperators as $operator) {
if (substr($_string, 0, strlen($operator)) == $operator) {
break 2;
}
}
$match .= $_string[0];
$_string = substr($_string, 1);
}
$tokens[] = new SassString($match);
}
$string = substr($string, strlen($match));
if ($string === '') {
$string = false;
}
}
return $tokens;
}
/**
* Returns a value indicating if a token of this type can be matched at
* the start of the subject string.
* @param string $subject the subject string
* @return mixed match at the start of the string or false if no match
*/
public function isWhitespace($subject)
{
return (preg_match(self::MATCH_WHITESPACE, $subject, $matches) ? $matches[0] : false);
}
}