@@ -355,7 +355,7 @@ private function doParse(string $value, int $flags)
355
355
}
356
356
357
357
try {
358
- return Inline::parse ($ this ->parseQuotedString ( $ this -> currentLine ), $ flags , $ this ->refs );
358
+ return Inline::parse ($ this ->lexInlineQuotedString ( ), $ flags , $ this ->refs );
359
359
} catch (ParseException $ e ) {
360
360
$ e ->setParsedLine ($ this ->getRealCurrentLineNb () + 1 );
361
361
$ e ->setSnippet ($ this ->currentLine );
@@ -368,7 +368,7 @@ private function doParse(string $value, int $flags)
368
368
}
369
369
370
370
try {
371
- $ parsedMapping = Inline::parse ($ this ->lexInlineMapping ($ this -> currentLine ), $ flags , $ this ->refs );
371
+ $ parsedMapping = Inline::parse ($ this ->lexInlineMapping (), $ flags , $ this ->refs );
372
372
373
373
while ($ this ->moveToNextLine ()) {
374
374
if (!$ this ->isCurrentLineEmpty ()) {
@@ -389,7 +389,7 @@ private function doParse(string $value, int $flags)
389
389
}
390
390
391
391
try {
392
- $ parsedSequence = Inline::parse ($ this ->lexInlineSequence ($ this -> currentLine ), $ flags , $ this ->refs );
392
+ $ parsedSequence = Inline::parse ($ this ->lexInlineSequence (), $ flags , $ this ->refs );
393
393
394
394
while ($ this ->moveToNextLine ()) {
395
395
if (!$ this ->isCurrentLineEmpty ()) {
@@ -736,9 +736,13 @@ private function parseValue(string $value, int $flags, string $context)
736
736
737
737
try {
738
738
if ('' !== $ value && '{ ' === $ value [0 ]) {
739
- return Inline::parse ($ this ->lexInlineMapping ($ value ), $ flags , $ this ->refs );
739
+ $ cursor = \strlen ($ this ->currentLine ) - \strlen ($ value );
740
+
741
+ return Inline::parse ($ this ->lexInlineMapping ($ cursor ), $ flags , $ this ->refs );
740
742
} elseif ('' !== $ value && '[ ' === $ value [0 ]) {
741
- return Inline::parse ($ this ->lexInlineSequence ($ value ), $ flags , $ this ->refs );
743
+ $ cursor = \strlen ($ this ->currentLine ) - \strlen ($ value );
744
+
745
+ return Inline::parse ($ this ->lexInlineSequence ($ cursor ), $ flags , $ this ->refs );
742
746
}
743
747
744
748
$ quotation = '' !== $ value && ('" ' === $ value [0 ] || "' " === $ value [0 ]) ? $ value [0 ] : null ;
@@ -1137,106 +1141,148 @@ private function getLineTag(string $value, int $flags, bool $nextLineCheck = tru
1137
1141
throw new ParseException (sprintf ('Tags support is not enabled. You must use the flag "Yaml::PARSE_CUSTOM_TAGS" to use "%s". ' , $ matches ['tag ' ]), $ this ->getRealCurrentLineNb () + 1 , $ value , $ this ->filename );
1138
1142
}
1139
1143
1140
- private function parseQuotedString ( string $ yaml ): ? string
1144
+ private function lexInlineQuotedString ( int & $ cursor = 0 ): string
1141
1145
{
1142
- if ('' === $ yaml || ('" ' !== $ yaml [0 ] && "' " !== $ yaml [0 ])) {
1143
- throw new \InvalidArgumentException (sprintf ('"%s" is not a quoted string. ' , $ yaml ));
1144
- }
1145
-
1146
- $ lines = [$ yaml ];
1146
+ $ quotation = $ this ->currentLine [$ cursor ];
1147
+ $ value = $ quotation ;
1148
+ ++$ cursor ;
1147
1149
1148
- while ( $ this -> moveToNextLine ()) {
1149
- $ lines [] = $ this -> currentLine ;
1150
+ $ previousLineWasNewline = true ;
1151
+ $ previousLineWasTerminatedWithBackslash = false ;
1150
1152
1151
- if (!$ this ->isCurrentLineEmpty () && $ yaml [0 ] === $ this ->currentLine [-1 ]) {
1152
- break ;
1153
- }
1154
- }
1155
-
1156
- $ value = '' ;
1157
-
1158
- for ($ i = 0 , $ linesCount = \count ($ lines ), $ previousLineWasNewline = false , $ previousLineWasTerminatedWithBackslash = false ; $ i < $ linesCount ; ++$ i ) {
1159
- if ('' === trim ($ lines [$ i ])) {
1153
+ do {
1154
+ if ($ this ->isCurrentLineBlank ()) {
1160
1155
$ value .= "\n" ;
1161
1156
} elseif (!$ previousLineWasNewline && !$ previousLineWasTerminatedWithBackslash ) {
1162
1157
$ value .= ' ' ;
1163
1158
}
1164
1159
1165
- if ('' !== trim ($ lines [$ i ]) && '\\' === substr ($ lines [$ i ], -1 )) {
1166
- $ value .= ltrim (substr ($ lines [$ i ], 0 , -1 ));
1167
- } elseif ('' !== trim ($ lines [$ i ])) {
1168
- $ value .= trim ($ lines [$ i ]);
1160
+ for (; \strlen ($ this ->currentLine ) > $ cursor ; ++$ cursor ) {
1161
+ switch ($ this ->currentLine [$ cursor ]) {
1162
+ case '\\' :
1163
+ if (isset ($ this ->currentLine [++$ cursor ])) {
1164
+ $ value .= '\\' .$ this ->currentLine [$ cursor ];
1165
+ }
1166
+
1167
+ break ;
1168
+ case $ quotation :
1169
+ ++$ cursor ;
1170
+
1171
+ if ("' " === $ quotation && isset ($ this ->currentLine [$ cursor ]) && "' " === $ this ->currentLine [$ cursor ]) {
1172
+ $ value .= "'' " ;
1173
+ break ;
1174
+ }
1175
+
1176
+ return $ value .$ quotation ;
1177
+ default :
1178
+ $ value .= $ this ->currentLine [$ cursor ];
1179
+ }
1169
1180
}
1170
1181
1171
- if ('' === trim ($ lines [$ i ])) {
1182
+ if (isset ($ this ->currentLine [$ cursor ]) && $ this ->currentLine [$ cursor ] === $ quotation ) {
1183
+ ++$ cursor ;
1184
+
1185
+ return $ value .$ quotation ;
1186
+ }
1187
+
1188
+ if ($ this ->isCurrentLineBlank ()) {
1172
1189
$ previousLineWasNewline = true ;
1173
1190
$ previousLineWasTerminatedWithBackslash = false ;
1174
- } elseif ('\\' === substr ( $ lines [ $ i ], - 1 ) ) {
1191
+ } elseif ('\\' === $ this -> currentLine [- 1 ] ) {
1175
1192
$ previousLineWasNewline = false ;
1176
1193
$ previousLineWasTerminatedWithBackslash = true ;
1177
1194
} else {
1178
1195
$ previousLineWasNewline = false ;
1179
1196
$ previousLineWasTerminatedWithBackslash = false ;
1180
1197
}
1181
- }
1198
+
1199
+ $ cursor = 0 ;
1200
+ } while ($ this ->moveToNextLine ());
1182
1201
1183
1202
return $ value ;
1184
1203
}
1185
1204
1186
- private function lexInlineMapping ( string $ yaml ): string
1205
+ private function lexUnquotedString ( int & $ cursor ): string
1187
1206
{
1188
- if ('' === $ yaml || '{ ' !== $ yaml [0 ]) {
1189
- throw new \InvalidArgumentException (sprintf ('"%s" is not a sequence. ' , $ yaml ));
1190
- }
1191
-
1192
- for ($ i = 1 ; isset ($ yaml [$ i ]) && '} ' !== $ yaml [$ i ]; ++$ i ) {
1193
- }
1194
-
1195
- if (isset ($ yaml [$ i ]) && '} ' === $ yaml [$ i ]) {
1196
- return $ yaml ;
1197
- }
1198
-
1199
- $ lines = [$ yaml ];
1200
-
1201
- while ($ this ->moveToNextLine ()) {
1202
- $ lines [] = $ this ->currentLine ;
1203
- }
1207
+ $ offset = $ cursor ;
1208
+ $ cursor += strcspn ($ this ->currentLine , '[]{},: ' , $ cursor );
1204
1209
1205
- return implode ( "\n" , $ lines );
1210
+ return substr ( $ this -> currentLine , $ offset , $ cursor - $ offset );
1206
1211
}
1207
1212
1208
- private function lexInlineSequence ( string $ yaml ): string
1213
+ private function lexInlineMapping ( int & $ cursor = 0 ): string
1209
1214
{
1210
- if ('' === $ yaml || '[ ' !== $ yaml [0 ]) {
1211
- throw new \InvalidArgumentException (sprintf ('"%s" is not a sequence. ' , $ yaml ));
1212
- }
1215
+ return $ this ->lexInlineStructure ($ cursor , '} ' );
1216
+ }
1213
1217
1214
- for ($ i = 1 ; isset ($ yaml [$ i ]) && '] ' !== $ yaml [$ i ]; ++$ i ) {
1215
- }
1218
+ private function lexInlineSequence (int &$ cursor = 0 ): string
1219
+ {
1220
+ return $ this ->lexInlineStructure ($ cursor , '] ' );
1221
+ }
1216
1222
1217
- if (isset ($ yaml [$ i ]) && '] ' === $ yaml [$ i ]) {
1218
- return $ yaml ;
1219
- }
1223
+ private function lexInlineStructure (int &$ cursor , string $ closingTag ): string
1224
+ {
1225
+ $ value = $ this ->currentLine [$ cursor ];
1226
+ ++$ cursor ;
1220
1227
1221
- $ value = $ yaml ;
1228
+ do {
1229
+ $ this ->consumeWhitespaces ($ cursor );
1230
+
1231
+ while (isset ($ this ->currentLine [$ cursor ])) {
1232
+ switch ($ this ->currentLine [$ cursor ]) {
1233
+ case '" ' :
1234
+ case "' " :
1235
+ $ value .= $ this ->lexInlineQuotedString ($ cursor );
1236
+ break ;
1237
+ case ': ' :
1238
+ case ', ' :
1239
+ $ value .= $ this ->currentLine [$ cursor ];
1240
+ ++$ cursor ;
1241
+ break ;
1242
+ case '{ ' :
1243
+ $ value .= $ this ->lexInlineMapping ($ cursor );
1244
+ break ;
1245
+ case '[ ' :
1246
+ $ value .= $ this ->lexInlineSequence ($ cursor );
1247
+ break ;
1248
+ case $ closingTag :
1249
+ $ value .= $ this ->currentLine [$ cursor ];
1250
+ ++$ cursor ;
1251
+
1252
+ return $ value ;
1253
+ case '# ' :
1254
+ break 2 ;
1255
+ default :
1256
+ $ value .= $ this ->lexUnquotedString ($ cursor );
1257
+ }
1222
1258
1223
- while ($ this ->moveToNextLine ()) {
1224
- for ($ i = 1 ; isset ($ this ->currentLine [$ i ]) && '] ' !== $ this ->currentLine [$ i ]; ++$ i ) {
1259
+ if ($ this ->consumeWhitespaces ($ cursor )) {
1260
+ $ value .= ' ' ;
1261
+ }
1225
1262
}
1226
1263
1227
- $ trimmedValue = trim ($ this ->currentLine );
1264
+ $ cursor = 0 ;
1265
+ } while ($ this ->moveToNextLine ());
1228
1266
1229
- if ('' !== $ trimmedValue && '# ' === $ trimmedValue [0 ]) {
1230
- continue ;
1231
- }
1267
+ return $ value ;
1268
+ }
1269
+
1270
+ private function consumeWhitespaces (int &$ cursor ): bool
1271
+ {
1272
+ $ whitespacesConsumed = 0 ;
1232
1273
1233
- $ value .= $ trimmedValue ;
1274
+ do {
1275
+ $ whitespaceOnlyTokenLength = strspn ($ this ->currentLine , ' ' , $ cursor );
1276
+ $ whitespacesConsumed += $ whitespaceOnlyTokenLength ;
1277
+ $ cursor += $ whitespaceOnlyTokenLength ;
1234
1278
1235
- if (isset ($ this ->currentLine [$ i ]) && ' ] ' === $ this -> currentLine [ $ i ] ) {
1236
- break ;
1279
+ if (isset ($ this ->currentLine [$ cursor ]) ) {
1280
+ return 0 < $ whitespacesConsumed ;
1237
1281
}
1238
- }
1239
1282
1240
- return $ value ;
1283
+ $ cursor = 0 ;
1284
+ } while ($ this ->moveToNextLine ());
1285
+
1286
+ return 0 < $ whitespacesConsumed ;
1241
1287
}
1242
1288
}
0 commit comments