1<?php 2 3namespace JMS\Serializer; 4 5/** 6 * Parses a serializer type. 7 * 8 * @author Johannes M. Schmitt <schmittjoh@gmail.com> 9 */ 10final class TypeParser extends \JMS\Parser\AbstractParser 11{ 12 const T_NAME = 1; 13 const T_STRING = 2; 14 const T_OPEN_BRACKET = 3; 15 const T_CLOSE_BRACKET = 4; 16 const T_COMMA = 5; 17 const T_NONE = 6; 18 19 public function __construct() 20 { 21 parent::__construct(new \JMS\Parser\SimpleLexer( 22 '/ 23 # PHP Class Names 24 ((?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*) 25 26 # Strings 27 |("(?:[^"]|"")*"|\'(?:[^\']|\'\')*\') 28 29 # Ignore whitespace 30 |\s* 31 32 # Terminals 33 |(.) 34 /x', 35 array(self::T_NAME => 'T_NAME', self::T_STRING => 'T_STRING', self::T_OPEN_BRACKET => 'T_OPEN_BRACKET', 36 self::T_CLOSE_BRACKET => 'T_CLOSE_BRACKET', self::T_COMMA => 'T_COMMA', self::T_NONE => 'T_NONE'), 37 function ($value) { 38 switch ($value[0]) { 39 case '"': 40 case "'": 41 return array(TypeParser::T_STRING, substr($value, 1, -1)); 42 43 case '<': 44 return array(TypeParser::T_OPEN_BRACKET, '<'); 45 46 case '>': 47 return array(TypeParser::T_CLOSE_BRACKET, '>'); 48 49 case ',': 50 return array(TypeParser::T_COMMA, ','); 51 52 default: 53 if (preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $value)) { 54 return array(TypeParser::T_NAME, $value); 55 } 56 57 return array(TypeParser::T_NONE, $value); 58 } 59 } 60 )); 61 } 62 63 /** 64 * @return array of the format ["name" => string, "params" => array] 65 */ 66 protected function parseInternal() 67 { 68 $typeName = $this->match(self::T_NAME); 69 if (!$this->lexer->isNext(self::T_OPEN_BRACKET)) { 70 return array('name' => $typeName, 'params' => array()); 71 } 72 73 $this->match(self::T_OPEN_BRACKET); 74 $params = array(); 75 do { 76 if ($this->lexer->isNext(self::T_NAME)) { 77 $params[] = $this->parseInternal(); 78 } else if ($this->lexer->isNext(self::T_STRING)) { 79 $params[] = $this->match(self::T_STRING); 80 } else { 81 $this->matchAny(array(self::T_NAME, self::T_STRING)); // Will throw an exception. 82 } 83 } while ($this->lexer->isNext(self::T_COMMA) && $this->lexer->moveNext()); 84 85 $this->match(self::T_CLOSE_BRACKET); 86 87 return array('name' => $typeName, 'params' => $params); 88 } 89} 90