[fine] Fix a problem with a stuck parser
Whoops
This commit is contained in:
parent
5f0a0b3268
commit
11cb7199e9
2 changed files with 44 additions and 3 deletions
|
|
@ -361,7 +361,7 @@ impl<'a> CParser<'a> {
|
|||
|
||||
fn advance(&mut self) {
|
||||
assert!(!self.eof()); // Don't try to advance past EOF
|
||||
self.fuel.set(256); // Consuming a token, rest stuck detector
|
||||
self.fuel.set(256); // Consuming a token, reset stuck detector
|
||||
self.events.push(ParseEvent::Advance {
|
||||
token: self.current.clone(),
|
||||
});
|
||||
|
|
@ -381,11 +381,20 @@ impl<'a> CParser<'a> {
|
|||
}
|
||||
|
||||
fn peek(&self) -> TokenKind {
|
||||
assert!(self.fuel.get() > 0, "parser is stuck!");
|
||||
if self.fuel.get() == 0 {
|
||||
panic!(
|
||||
"parser is stuck at '{}' ({})!",
|
||||
self.current, self.current.start
|
||||
);
|
||||
}
|
||||
self.fuel.set(self.fuel.get() - 1);
|
||||
self.current.kind
|
||||
}
|
||||
|
||||
// fn trace(&self, msg: &str) {
|
||||
// eprintln!("{}: {}: {}", self.current.start, self.current, msg);
|
||||
// }
|
||||
|
||||
fn at(&self, kind: TokenKind) -> bool {
|
||||
self.peek() == kind
|
||||
}
|
||||
|
|
@ -511,6 +520,14 @@ fn file(p: &mut CParser) {
|
|||
while !p.eof() {
|
||||
match p.peek() {
|
||||
TokenKind::Class => class(p),
|
||||
TokenKind::RightBrace => {
|
||||
// An error parsing mismatched braces can leave me at an
|
||||
// un-balanced right brace, which unfortunately will not be
|
||||
// consumed by the statement below. (Statement currently
|
||||
// falls through to expression_statement, which checks for
|
||||
// the right-brace that a block would end with.)
|
||||
p.advance_with_error("unbalanced '}'");
|
||||
}
|
||||
_ => statement(p),
|
||||
}
|
||||
}
|
||||
|
|
@ -542,7 +559,11 @@ fn class(p: &mut CParser) {
|
|||
p.expect(TokenKind::Identifier, "expected a class name");
|
||||
if p.eat(TokenKind::LeftBrace) {
|
||||
while !p.at(TokenKind::RightBrace) && !p.eof() {
|
||||
field_decl(p);
|
||||
if p.at(TokenKind::Identifier) {
|
||||
field_decl(p);
|
||||
} else {
|
||||
p.advance_with_error("expected a field declaration");
|
||||
}
|
||||
}
|
||||
}
|
||||
p.expect(TokenKind::RightBrace, "expected a class to end with a '}'");
|
||||
|
|
|
|||
20
fine/tests/errors/unbalanced_right_brace.fine
Normal file
20
fine/tests/errors/unbalanced_right_brace.fine
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
fun foo() { }
|
||||
|
||||
} // <- Whoopsie!
|
||||
|
||||
// @concrete:
|
||||
// | File
|
||||
// | FunctionDecl
|
||||
// | Fun:'"fun"'
|
||||
// | Identifier:'"foo"'
|
||||
// | ParamList
|
||||
// | LeftParen:'"("'
|
||||
// | RightParen:'")"'
|
||||
// | Block
|
||||
// | LeftBrace:'"{"'
|
||||
// | RightBrace:'"}"'
|
||||
// | Error
|
||||
// | Error:'"Error at '}': unbalanced '}'"'
|
||||
// | RightBrace:'"}"'
|
||||
// |
|
||||
//
|
||||
Loading…
Add table
Add a link
Reference in a new issue