SassScriptLexer.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <?php
  2. /* SVN FILE: $Id: SassScriptLexer.php 118 2010-09-21 09:45:11Z chris.l.yates@gmail.com $ */
  3. /**
  4. * SassScriptLexer class file.
  5. * @author Chris Yates <chris.l.yates@gmail.com>
  6. * @copyright Copyright (c) 2010 PBM Web Development
  7. * @license http://phamlp.googlecode.com/files/license.txt
  8. * @package PHamlP
  9. * @subpackage Sass.script
  10. */
  11. require_once('literals/SassBoolean.php');
  12. require_once('literals/SassColour.php');
  13. require_once('literals/SassNumber.php');
  14. require_once('literals/SassString.php');
  15. require_once('SassScriptFunction.php');
  16. require_once('SassScriptOperation.php');
  17. require_once('SassScriptVariable.php');
  18. /**
  19. * SassScriptLexer class.
  20. * Lexes SassSCript into tokens for the parser.
  21. *
  22. * 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.
  23. * @package PHamlP
  24. * @subpackage Sass.script
  25. */
  26. class SassScriptLexer {
  27. const MATCH_WHITESPACE = '/^\s+/';
  28. /**
  29. * @var SassScriptParser the parser object
  30. */
  31. private $parser;
  32. /**
  33. * SassScriptLexer constructor.
  34. * @return SassScriptLexer
  35. */
  36. public function __construct($parser) {
  37. $this->parser = $parser;
  38. }
  39. /**
  40. * Lex an expression into SassScript tokens.
  41. * @param string expression to lex
  42. * @param SassContext the context in which the expression is lexed
  43. * @return array tokens
  44. */
  45. public function lex($string, $context) {
  46. $tokens = array();
  47. while ($string !== false) {
  48. if (($match = $this->isWhitespace($string)) !== false) {
  49. $tokens[] = null;
  50. }
  51. elseif (($match = SassScriptFunction::isa($string)) !== false) {
  52. preg_match(SassScriptFunction::MATCH_FUNC, $match, $matches);
  53. $args = array();
  54. foreach (SassScriptFunction::extractArgs($matches[SassScriptFunction::ARGS])
  55. as $expression) {
  56. $args[] = $this->parser->evaluate($expression, $context);
  57. }
  58. $tokens[] = new SassScriptFunction(
  59. $matches[SassScriptFunction::NAME], $args);
  60. }
  61. elseif (($match = SassString::isa($string)) !== false) {
  62. $tokens[] = new SassString($match);
  63. }
  64. elseif (($match = SassBoolean::isa($string)) !== false) {
  65. $tokens[] = new SassBoolean($match);
  66. }
  67. elseif (($match = SassColour::isa($string)) !== false) {
  68. $tokens[] = new SassColour($match);
  69. }
  70. elseif (($match = SassNumber::isa($string)) !== false) {
  71. $tokens[] = new SassNumber($match);
  72. }
  73. elseif (($match = SassScriptOperation::isa($string)) !== false) {
  74. $tokens[] = new SassScriptOperation($match);
  75. }
  76. elseif (($match = SassScriptVariable::isa($string)) !== false) {
  77. $tokens[] = new SassScriptVariable($match);
  78. }
  79. else {
  80. $_string = $string;
  81. $match = '';
  82. while (strlen($_string) && !$this->isWhitespace($_string)) {
  83. foreach (SassScriptOperation::$inStrOperators as $operator) {
  84. if (substr($_string, 0, strlen($operator)) == $operator) {
  85. break 2;
  86. }
  87. }
  88. $match .= $_string[0];
  89. $_string = substr($_string, 1);
  90. }
  91. $tokens[] = new SassString($match);
  92. }
  93. $string = substr($string, strlen($match));
  94. }
  95. return $tokens;
  96. }
  97. /**
  98. * Returns a value indicating if a token of this type can be matched at
  99. * the start of the subject string.
  100. * @param string the subject string
  101. * @return mixed match at the start of the string or false if no match
  102. */
  103. public function isWhitespace($subject) {
  104. return (preg_match(self::MATCH_WHITESPACE, $subject, $matches) ? $matches[0] : false);
  105. }
  106. }