@@ -139,14 +139,38 @@ impl<'i> Parser<'i> {
139139 self . offset += width;
140140 }
141141
142+ /// Skip to the beginning of the next line (or end of input). This is used
143+ /// when an error is encountered; we attempt to recover back to a newline
144+ /// as that may well be in a parent scope and we can continue.
145+ fn skip_to_next_line ( & mut self ) {
146+ if let Some ( pos) = self
147+ . source
148+ . find ( '\n' )
149+ {
150+ self . advance ( pos + 1 ) ;
151+ } else {
152+ self . advance (
153+ self . source
154+ . len ( ) ,
155+ ) ;
156+ }
157+ }
158+
142159 fn parse_collecting_errors ( & mut self ) -> ParseResult < ' i > {
143160 // Clear any existing errors
144161 self . problems
145162 . clear ( ) ;
146163
147- // Parse header, collecting errors instead of propagating
164+ // Parse header, collecting errors if encountered
148165 let header = if is_magic_line ( self . source ) {
149- Some ( self . read_technique_header ( ) ?)
166+ match self . read_technique_header ( ) {
167+ Ok ( header) => Some ( header) ,
168+ Err ( error) => {
169+ self . problems
170+ . push ( error) ;
171+ None
172+ }
173+ }
150174 } else {
151175 None
152176 } ;
@@ -162,9 +186,8 @@ impl<'i> Parser<'i> {
162186 break ;
163187 }
164188
165- // Check if this Technique is a a single set of one or more
189+ // Check if this Technique is a single set of one or more
166190 // top-level Scope::SectionChunk
167-
168191 if is_section ( self . source ) && procedures. is_empty ( ) {
169192 while !self . is_finished ( ) {
170193 self . trim_whitespace ( ) ;
@@ -173,10 +196,18 @@ impl<'i> Parser<'i> {
173196 }
174197
175198 if is_section ( self . source ) {
176- let section = self . read_section ( ) ?;
177- sections. push ( section) ;
199+ match self . read_section ( ) {
200+ Ok ( section) => sections. push ( section) ,
201+ Err ( error) => {
202+ self . problems
203+ . push ( error) ;
204+ self . skip_to_next_line ( ) ;
205+ }
206+ }
178207 } else {
179- return Err ( ParsingError :: Unrecognized ( self . offset ) ) ;
208+ self . problems
209+ . push ( ParsingError :: Unrecognized ( self . offset ) ) ;
210+ self . skip_to_next_line ( ) ;
180211 }
181212 }
182213 break ;
@@ -230,7 +261,9 @@ impl<'i> Parser<'i> {
230261 // is_procedure_declaration() failed, which is undefined.
231262 return Err ( ParsingError :: IllegalParserState ( self . offset ) ) ;
232263 } else {
233- return Err ( ParsingError :: Unrecognized ( self . offset ) ) ;
264+ self . problems
265+ . push ( ParsingError :: Unrecognized ( self . offset ) ) ;
266+ self . skip_to_next_line ( ) ;
234267 }
235268 }
236269
@@ -242,7 +275,9 @@ impl<'i> Parser<'i> {
242275 None
243276 } ;
244277
245- Ok ( Document { header, body } )
278+ let document = Document { header, body } ;
279+ let errors = std:: mem:: take ( & mut self . problems ) ;
280+ ParseResult { document, errors }
246281 }
247282
248283 /// consume up to but not including newline (or end), then take newline
0 commit comments