Differences Between: [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]
1 <?php 2 3 namespace Sabberworm\CSS\Value; 4 5 use Sabberworm\CSS\Parsing\ParserState; 6 use Sabberworm\CSS\Parsing\UnexpectedTokenException; 7 use Sabberworm\CSS\Renderable; 8 9 abstract class Value implements Renderable { 10 protected $iLineNo; 11 12 public function __construct($iLineNo = 0) { 13 $this->iLineNo = $iLineNo; 14 } 15 16 public static function parseValue(ParserState $oParserState, $aListDelimiters = array()) { 17 $aStack = array(); 18 $oParserState->consumeWhiteSpace(); 19 //Build a list of delimiters and parsed values 20 while (!($oParserState->comes('}') || $oParserState->comes(';') || $oParserState->comes('!') || $oParserState->comes(')') || $oParserState->comes('\\'))) { 21 if (count($aStack) > 0) { 22 $bFoundDelimiter = false; 23 foreach ($aListDelimiters as $sDelimiter) { 24 if ($oParserState->comes($sDelimiter)) { 25 array_push($aStack, $oParserState->consume($sDelimiter)); 26 $oParserState->consumeWhiteSpace(); 27 $bFoundDelimiter = true; 28 break; 29 } 30 } 31 if (!$bFoundDelimiter) { 32 //Whitespace was the list delimiter 33 array_push($aStack, ' '); 34 } 35 } 36 array_push($aStack, self::parsePrimitiveValue($oParserState)); 37 $oParserState->consumeWhiteSpace(); 38 } 39 //Convert the list to list objects 40 foreach ($aListDelimiters as $sDelimiter) { 41 if (count($aStack) === 1) { 42 return $aStack[0]; 43 } 44 $iStartPosition = null; 45 while (($iStartPosition = array_search($sDelimiter, $aStack, true)) !== false) { 46 $iLength = 2; //Number of elements to be joined 47 for ($i = $iStartPosition + 2; $i < count($aStack); $i+=2, ++$iLength) { 48 if ($sDelimiter !== $aStack[$i]) { 49 break; 50 } 51 } 52 $oList = new RuleValueList($sDelimiter, $oParserState->currentLine()); 53 for ($i = $iStartPosition - 1; $i - $iStartPosition + 1 < $iLength * 2; $i+=2) { 54 $oList->addListComponent($aStack[$i]); 55 } 56 array_splice($aStack, $iStartPosition - 1, $iLength * 2 - 1, array($oList)); 57 } 58 } 59 if (!isset($aStack[0])) { 60 throw new UnexpectedTokenException(" {$oParserState->peek()} ", $oParserState->peek(1, -1) . $oParserState->peek(2), 'literal', $oParserState->currentLine()); 61 } 62 return $aStack[0]; 63 } 64 65 public static function parseIdentifierOrFunction(ParserState $oParserState, $bIgnoreCase = false) { 66 $sResult = $oParserState->parseIdentifier($bIgnoreCase); 67 68 if ($oParserState->comes('(')) { 69 $oParserState->consume('('); 70 $aArguments = Value::parseValue($oParserState, array('=', ' ', ',')); 71 $sResult = new CSSFunction($sResult, $aArguments, ',', $oParserState->currentLine()); 72 $oParserState->consume(')'); 73 } 74 75 return $sResult; 76 } 77 78 public static function parsePrimitiveValue(ParserState $oParserState) { 79 $oValue = null; 80 $oParserState->consumeWhiteSpace(); 81 if (is_numeric($oParserState->peek()) || ($oParserState->comes('-.') && is_numeric($oParserState->peek(1, 2))) || (($oParserState->comes('-') || $oParserState->comes('.')) && is_numeric($oParserState->peek(1, 1)))) { 82 $oValue = Size::parse($oParserState); 83 } else if ($oParserState->comes('#') || $oParserState->comes('rgb', true) || $oParserState->comes('hsl', true)) { 84 $oValue = Color::parse($oParserState); 85 } else if ($oParserState->comes('url', true)) { 86 $oValue = URL::parse($oParserState); 87 } else if ($oParserState->comes('calc', true) || $oParserState->comes('-webkit-calc', true) || $oParserState->comes('-moz-calc', true)) { 88 $oValue = CalcFunction::parse($oParserState); 89 } else if ($oParserState->comes("'") || $oParserState->comes('"')) { 90 $oValue = CSSString::parse($oParserState); 91 } else if ($oParserState->comes("progid:") && $oParserState->getSettings()->bLenientParsing) { 92 $oValue = self::parseMicrosoftFilter($oParserState); 93 } else if ($oParserState->comes("[")) { 94 $oValue = LineName::parse($oParserState); 95 } else if ($oParserState->comes("U+")) { 96 $oValue = self::parseUnicodeRangeValue($oParserState); 97 } else { 98 $oValue = self::parseIdentifierOrFunction($oParserState); 99 } 100 $oParserState->consumeWhiteSpace(); 101 return $oValue; 102 } 103 104 private static function parseMicrosoftFilter(ParserState $oParserState) { 105 $sFunction = $oParserState->consumeUntil('(', false, true); 106 $aArguments = Value::parseValue($oParserState, array(',', '=')); 107 return new CSSFunction($sFunction, $aArguments, ',', $oParserState->currentLine()); 108 } 109 110 private static function parseUnicodeRangeValue(ParserState $oParserState) { 111 $iCodepointMaxLenth = 6; // Code points outside BMP can use up to six digits 112 $sRange = ""; 113 $oParserState->consume("U+"); 114 do { 115 if ($oParserState->comes('-')) $iCodepointMaxLenth = 13; // Max length is 2 six digit code points + the dash(-) between them 116 $sRange .= $oParserState->consume(1); 117 } while (strlen($sRange) < $iCodepointMaxLenth && preg_match("/[A-Fa-f0-9\?-]/", $oParserState->peek())); 118 return "U+{$sRange}"; 119 } 120 121 /** 122 * @return int 123 */ 124 public function getLineNo() { 125 return $this->iLineNo; 126 } 127 128 //Methods are commented out because re-declaring them here is a fatal error in PHP < 5.3.9 129 //public abstract function __toString(); 130 //public abstract function render(\Sabberworm\CSS\OutputFormat $oOutputFormat); 131 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body