1 | <?php |
||
5 | class Parser |
||
6 | { |
||
7 | protected $reserved = ['true', 'false']; |
||
8 | |||
9 | protected $rules = [ |
||
10 | '/^(true|false)$/i' => '_parseBooleanConstant', |
||
11 | '/^([\'"])(?:(?!\\1).)*\\1$/' => '_parseStringConstant', |
||
12 | '/^[a-zA-Z]+$/' => '_parseIdentifier', |
||
13 | '/^_$/' => '_parseWildcard', |
||
14 | '/^\\[.*\\]$/' => '_parseArray', |
||
15 | '/^\\(.+:.+\\)$/' => '_parseCons', |
||
16 | '/^[a-zA-Z]+@.+$/' => '_parseAs', |
||
17 | ]; |
||
18 | |||
19 | protected function _parseBooleanConstant($value, $pattern) |
||
24 | |||
25 | protected function _parseStringConstant($value, $pattern) |
||
30 | |||
31 | protected function _parseIdentifier($value, $pattern) |
||
35 | |||
36 | protected function _parseWildcard() |
||
40 | |||
41 | protected function _parseArray($value, $pattern) |
||
42 | { |
||
43 | 1 | $patterns = $this->_split(',', '[', ']', substr($pattern, 1, -1)); |
|
44 | |||
45 | 1 | if(count($patterns) === 0) { |
|
46 | 1 | return count($value) === 0 ? [] : false; |
|
47 | } |
||
48 | |||
49 | 1 | return $this->_recurse($value, $patterns); |
|
50 | } |
||
51 | |||
52 | protected function _parseCons($value, $pattern) |
||
53 | { |
||
54 | 1 | $patterns = $this->_split(':', '(', ')', substr($pattern, 1, -1)); |
|
55 | 1 | $last_pattern = array_pop($patterns); |
|
56 | |||
57 | 1 | $results = $this->_recurse($value, $patterns); |
|
58 | |||
59 | 1 | if($results !== false) { |
|
60 | 1 | $last_result = $this->parse(array_splice($value, count($patterns)), $last_pattern); |
|
61 | |||
62 | 1 | $results = $last_result === false ? false : array_merge($results, $last_result); |
|
63 | 1 | } |
|
64 | |||
65 | 1 | return $results; |
|
66 | } |
||
67 | |||
68 | protected function _parseAs($value, $pattern) |
||
75 | |||
76 | /** |
||
77 | * @param mixed $value |
||
78 | * @param string $pattern |
||
79 | * @return bool|array |
||
80 | */ |
||
81 | public function parse($value, $pattern) |
||
108 | |||
109 | protected function _split($delimiter, $start, $stop, $pattern) |
||
|
|||
110 | { |
||
111 | 1 | $result = split_enclosed($delimiter, $start, $stop, $pattern); |
|
112 | |||
113 | 1 | if($result === false) { |
|
114 | 1 | $this->_invalidPattern($pattern); |
|
115 | } |
||
116 | |||
117 | 1 | return $result; |
|
118 | } |
||
119 | |||
120 | protected function _recurse($value, $patterns) |
||
121 | { |
||
122 | 1 | if(! is_array($value) || count($patterns) > count($value)) { |
|
123 | 1 | return false; |
|
124 | } |
||
125 | |||
126 | 1 | $results = []; |
|
127 | 1 | foreach($patterns as $p) { |
|
128 | 1 | $new = $this->parse(array_shift($value), $p); |
|
129 | |||
130 | 1 | if($new === false) { |
|
131 | 1 | return false; |
|
132 | } |
||
133 | |||
134 | 1 | $results = array_merge($results, $new); |
|
135 | 1 | } |
|
136 | |||
137 | 1 | return $results; |
|
138 | } |
||
139 | |||
140 | protected function _invalidPattern($pattern) |
||
144 | } |
Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a
@return
annotation as described here.