@@ -24,6 +24,7 @@ class Parser
24
24
const BLOCK_SCALAR_HEADER_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)? ' ;
25
25
26
26
private $ offset = 0 ;
27
+ private $ totalNumberOfLines ;
27
28
private $ lines = array ();
28
29
private $ currentLineNb = -1 ;
29
30
private $ currentLine = '' ;
@@ -32,11 +33,13 @@ class Parser
32
33
/**
33
34
* Constructor.
34
35
*
35
- * @param int $offset The offset of YAML document (used for line numbers in error messages)
36
+ * @param int $offset The offset of YAML document (used for line numbers in error messages)
37
+ * @param int|null $totalNumberOfLines The overall number of lines being parsed
36
38
*/
37
- public function __construct ($ offset = 0 )
39
+ public function __construct ($ offset = 0 , $ totalNumberOfLines = null )
38
40
{
39
41
$ this ->offset = $ offset ;
42
+ $ this ->totalNumberOfLines = $ totalNumberOfLines ;
40
43
}
41
44
42
45
/**
@@ -85,6 +88,10 @@ public function parse($value, $flags = 0)
85
88
$ value = $ this ->cleanup ($ value );
86
89
$ this ->lines = explode ("\n" , $ value );
87
90
91
+ if (null === $ this ->totalNumberOfLines ) {
92
+ $ this ->totalNumberOfLines = count ($ this ->lines );
93
+ }
94
+
88
95
if (2 /* MB_OVERLOAD_STRING */ & (int ) ini_get ('mbstring.func_overload ' )) {
89
96
$ mbEncoding = mb_internal_encoding ();
90
97
mb_internal_encoding ('UTF-8 ' );
@@ -106,7 +113,7 @@ public function parse($value, $flags = 0)
106
113
$ isRef = $ mergeNode = false ;
107
114
if (preg_match ('#^\-((?P<leadspaces>\s+)(?P<value>.+?))?\s*$#u ' , $ this ->currentLine , $ values )) {
108
115
if ($ context && 'mapping ' == $ context ) {
109
- throw new ParseException ('You cannot define a sequence item when in a mapping ' );
116
+ throw new ParseException ('You cannot define a sequence item when in a mapping ' , $ this -> getRealCurrentLineNb () + 1 , $ this -> currentLine );
110
117
}
111
118
$ context = 'sequence ' ;
112
119
@@ -118,7 +125,7 @@ public function parse($value, $flags = 0)
118
125
// array
119
126
if (!isset ($ values ['value ' ]) || '' == trim ($ values ['value ' ], ' ' ) || 0 === strpos (ltrim ($ values ['value ' ], ' ' ), '# ' )) {
120
127
$ c = $ this ->getRealCurrentLineNb () + 1 ;
121
- $ parser = new self ($ c );
128
+ $ parser = new self ($ c, $ this -> totalNumberOfLines );
122
129
$ parser ->refs = &$ this ->refs ;
123
130
$ data [] = $ parser ->parse ($ this ->getNextEmbedBlock (null , true ), $ flags );
124
131
} else {
@@ -127,7 +134,7 @@ public function parse($value, $flags = 0)
127
134
) {
128
135
// this is a compact notation element, add to next block and parse
129
136
$ c = $ this ->getRealCurrentLineNb ();
130
- $ parser = new self ($ c );
137
+ $ parser = new self ($ c, $ this -> totalNumberOfLines );
131
138
$ parser ->refs = &$ this ->refs ;
132
139
133
140
$ block = $ values ['value ' ];
@@ -145,7 +152,7 @@ public function parse($value, $flags = 0)
145
152
}
146
153
} elseif (preg_match ('#^(?P<key> ' .Inline::REGEX_QUOTED_STRING .'|[^ \'"\[\{].*?) *\:(\s+(?P<value>.+?))?\s*$#u ' , $ this ->currentLine , $ values ) && (false === strpos ($ values ['key ' ], ' # ' ) || in_array ($ values ['key ' ][0 ], array ('" ' , "' " )))) {
147
154
if ($ context && 'sequence ' == $ context ) {
148
- throw new ParseException ('You cannot define a mapping item when in a sequence ' );
155
+ throw new ParseException ('You cannot define a mapping item when in a sequence ' , $ this -> currentLineNb + 1 , $ this -> currentLine );
149
156
}
150
157
$ context = 'mapping ' ;
151
158
@@ -192,7 +199,7 @@ public function parse($value, $flags = 0)
192
199
$ value = $ this ->getNextEmbedBlock ();
193
200
}
194
201
$ c = $ this ->getRealCurrentLineNb () + 1 ;
195
- $ parser = new self ($ c );
202
+ $ parser = new self ($ c, $ this -> totalNumberOfLines );
196
203
$ parser ->refs = &$ this ->refs ;
197
204
$ parsed = $ parser ->parse ($ value , $ flags );
198
205
@@ -243,7 +250,7 @@ public function parse($value, $flags = 0)
243
250
}
244
251
} else {
245
252
$ c = $ this ->getRealCurrentLineNb () + 1 ;
246
- $ parser = new self ($ c );
253
+ $ parser = new self ($ c, $ this -> totalNumberOfLines );
247
254
$ parser ->refs = &$ this ->refs ;
248
255
$ value = $ parser ->parse ($ this ->getNextEmbedBlock (), $ flags );
249
256
// Spec: Keys MUST be unique; first one wins.
@@ -266,7 +273,7 @@ public function parse($value, $flags = 0)
266
273
} else {
267
274
// multiple documents are not supported
268
275
if ('--- ' === $ this ->currentLine ) {
269
- throw new ParseException ('Multiple documents are not supported. ' );
276
+ throw new ParseException ('Multiple documents are not supported. ' , $ this -> currentLineNb + 1 , $ this -> currentLine );
270
277
}
271
278
272
279
// 1-liner optionally followed by newline(s)
@@ -511,7 +518,7 @@ private function parseValue($value, $flags, $context)
511
518
}
512
519
513
520
if (!array_key_exists ($ value , $ this ->refs )) {
514
- throw new ParseException (sprintf ('Reference "%s" does not exist. ' , $ value ), $ this ->currentLine );
521
+ throw new ParseException (sprintf ('Reference "%s" does not exist. ' , $ value ), $ this ->currentLineNb + 1 , $ this -> currentLine );
515
522
}
516
523
517
524
return $ this ->refs [$ value ];
@@ -609,6 +616,8 @@ private function parseBlockScalar($style, $chomping = '', $indentation = 0)
609
616
if ($ notEOF ) {
610
617
$ blockLines [] = '' ;
611
618
$ this ->moveToPreviousLine ();
619
+ } elseif (!$ notEOF && !$ this ->isCurrentLineLastLineInDocument ()) {
620
+ $ blockLines [] = '' ;
612
621
}
613
622
614
623
// folded style
@@ -715,6 +724,11 @@ private function isCurrentLineComment()
715
724
return '' !== $ ltrimmedLine && $ ltrimmedLine [0 ] === '# ' ;
716
725
}
717
726
727
+ private function isCurrentLineLastLineInDocument ()
728
+ {
729
+ return ($ this ->offset + $ this ->currentLineNb ) >= ($ this ->totalNumberOfLines - 1 );
730
+ }
731
+
718
732
/**
719
733
* Cleanups a YAML string to be parsed.
720
734
*
@@ -792,7 +806,7 @@ private function isNextLineUnIndentedCollection()
792
806
*/
793
807
private function isStringUnIndentedCollectionItem ()
794
808
{
795
- return 0 === strpos ($ this ->currentLine , '- ' );
809
+ return ' - ' === rtrim ( $ this -> currentLine ) || 0 === strpos ($ this ->currentLine , '- ' );
796
810
}
797
811
798
812
/**
0 commit comments