Skip to content

Commit 5604c6b

Browse files
committed
Helper method to skip to next line on error
1 parent 0b981d1 commit 5604c6b

File tree

1 file changed

+44
-9
lines changed

1 file changed

+44
-9
lines changed

src/parsing/parser.rs

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)