@@ -63,20 +63,32 @@ public static function parse(Parser $parser, TokensList $list, array $options =
63
63
$ ret = empty ($ options ['type ' ]) ? new ArrayObj () : array ();
64
64
65
65
/**
66
- * The state of the parser .
66
+ * The last raw expression .
67
67
*
68
- * Below are the states of the parser.
69
- *
70
- * 0 -----------------------[ ( ]------------------------> 1
68
+ * @var string $lastRaw
69
+ */
70
+ $ lastRaw = '' ;
71
+
72
+ /**
73
+ * The last value.
71
74
*
72
- * 1 ------------------[ array element ]-----------------> 2
75
+ * @var string $lastValue
76
+ */
77
+ $ lastValue = '' ;
78
+
79
+ /**
80
+ * Counts brackets.
73
81
*
74
- * 2 ------------------------[ , ]-----------------------> 1
75
- * 2 ------------------------[ ) ]-----------------------> (END)
82
+ * @var int $brackets
83
+ */
84
+ $ brackets = 0 ;
85
+
86
+ /**
87
+ * Last separator (bracket or comma).
76
88
*
77
- * @var int $state
89
+ * @var boolean $isCommaLast
78
90
*/
79
- $ state = 0 ;
91
+ $ isCommaLast = false ;
80
92
81
93
for (; $ list ->idx < $ list ->count ; ++$ list ->idx ) {
82
94
/**
@@ -92,49 +104,72 @@ public static function parse(Parser $parser, TokensList $list, array $options =
92
104
}
93
105
94
106
// Skipping whitespaces and comments.
95
- if (($ token ->type === Token::TYPE_WHITESPACE ) || ($ token ->type === Token::TYPE_COMMENT )) {
107
+ if (($ token ->type === Token::TYPE_WHITESPACE )
108
+ || ($ token ->type === Token::TYPE_COMMENT )
109
+ ) {
110
+ $ lastRaw .= $ token ->token ;
111
+ $ lastValue = trim ($ lastValue ) .' ' ;
96
112
continue ;
97
113
}
98
114
99
- if ($ state === 0 ) {
100
- if (($ token ->type !== Token::TYPE_OPERATOR ) || ($ token ->value !== '( ' )) {
101
- $ parser ->error (
102
- __ ('An opening bracket was expected. ' ),
103
- $ token
104
- );
105
- break ;
106
- }
107
- $ state = 1 ;
108
- } elseif ($ state === 1 ) {
109
- if (($ token ->type === Token::TYPE_OPERATOR ) && ($ token ->value === ') ' )) {
110
- // Empty array.
111
- break ;
112
- }
113
- if (empty ($ options ['type ' ])) {
114
- $ ret ->values [] = $ token ->value ;
115
- $ ret ->raw [] = $ token ->token ;
116
- } else {
117
- $ ret [] = $ options ['type ' ]::parse (
118
- $ parser ,
119
- $ list ,
120
- empty ($ options ['typeOptions ' ]) ? array () : $ options ['typeOptions ' ]
121
- );
122
- }
123
- $ state = 2 ;
124
- } elseif ($ state === 2 ) {
125
- if (($ token ->type !== Token::TYPE_OPERATOR ) || (($ token ->value !== ', ' ) && ($ token ->value !== ') ' ))) {
126
- $ parser ->error (
127
- __ ('A comma or a closing bracket was expected ' ),
128
- $ token
129
- );
130
- break ;
131
- }
132
- if ($ token ->value === ', ' ) {
133
- $ state = 1 ;
134
- } else { // )
135
- break ;
115
+ if (($ brackets === 0 )
116
+ && (($ token ->type !== Token::TYPE_OPERATOR )
117
+ || ($ token ->value !== '( ' ))
118
+ ) {
119
+ $ parser ->error (__ ('An opening bracket was expected. ' ), $ token );
120
+ break ;
121
+ }
122
+
123
+ if ($ token ->type === Token::TYPE_OPERATOR ) {
124
+ if ($ token ->value === '( ' ) {
125
+ if (++$ brackets === 1 ) { // 1 is the base level.
126
+ continue ;
127
+ }
128
+ } elseif ($ token ->value === ') ' ) {
129
+ if (--$ brackets === 0 ) { // Array ended.
130
+ break ;
131
+ }
132
+ } elseif ($ token ->value === ', ' ) {
133
+ if ($ brackets === 1 ) {
134
+ $ isCommaLast = true ;
135
+ if (empty ($ options ['type ' ])) {
136
+ $ ret ->raw [] = trim ($ lastRaw );
137
+ $ ret ->values [] = trim ($ lastValue );
138
+ $ lastRaw = $ lastValue = '' ;
139
+ }
140
+ }
141
+ continue ;
136
142
}
137
143
}
144
+
145
+ if (empty ($ options ['type ' ])) {
146
+ $ lastRaw .= $ token ->token ;
147
+ $ lastValue .= $ token ->value ;
148
+ } else {
149
+ $ ret [] = $ options ['type ' ]::parse (
150
+ $ parser ,
151
+ $ list ,
152
+ empty ($ options ['typeOptions ' ]) ? array () : $ options ['typeOptions ' ]
153
+ );
154
+ }
155
+ }
156
+
157
+ // Handling last element.
158
+ //
159
+ // This is treated differently to treat the following cases:
160
+ //
161
+ // => array()
162
+ // (,) => array('', '')
163
+ // () => array()
164
+ // (a,) => array('a', '')
165
+ // (a) => array('a')
166
+ //
167
+ $ lastRaw = trim ($ lastRaw );
168
+ if ((empty ($ options ['type ' ]))
169
+ && ((strlen ($ lastRaw ) > 0 ) || ($ isCommaLast ))
170
+ ) {
171
+ $ ret ->raw [] = $ lastRaw ;
172
+ $ ret ->values [] = trim ($ lastValue );
138
173
}
139
174
140
175
return $ ret ;
0 commit comments