Skip to content

Commit 77a8adf

Browse files
committed
Introduce parser.start/reset to support back-tracking
Adjusting parser's `self.index` always felt like a hack, and it becomes more important as I need to store more state in my "lossless syntax tree" prototype.
1 parent 06fe8db commit 77a8adf

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

src/parser.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ macro_rules! parser_err {
3434
};
3535
}
3636

37+
/// The parser state
38+
pub struct Marker {
39+
/// position in the token stream (`parser.index`)
40+
index: usize,
41+
}
42+
3743
#[derive(PartialEq)]
3844
pub enum IsOptional {
3945
Optional,
@@ -742,6 +748,14 @@ impl Parser {
742748
}
743749
}
744750

751+
pub fn start(&mut self) -> Marker {
752+
Marker { index: self.index }
753+
}
754+
755+
pub fn reset(&mut self, m: Marker) {
756+
self.index = m.index;
757+
}
758+
745759
/// Return the first non-whitespace token that has not yet been processed
746760
/// (or None if reached end-of-file)
747761
pub fn peek_token(&self) -> Option<Token> {
@@ -827,12 +841,10 @@ impl Parser {
827841
/// Look for an expected sequence of keywords and consume them if they exist
828842
#[must_use]
829843
pub fn parse_keywords(&mut self, keywords: Vec<&'static str>) -> bool {
830-
let index = self.index;
844+
let checkpoint = self.start();
831845
for keyword in keywords {
832846
if !self.parse_keyword(&keyword) {
833-
//println!("parse_keywords aborting .. did not find {}", keyword);
834-
// reset index and return immediately
835-
self.index = index;
847+
self.reset(checkpoint);
836848
return false;
837849
}
838850
}
@@ -1920,7 +1932,7 @@ impl Parser {
19201932
}
19211933

19221934
if self.consume_token(&Token::LParen) {
1923-
let index = self.index;
1935+
let checkpoint = self.start();
19241936
// A left paren introduces either a derived table (i.e., a subquery)
19251937
// or a nested join. It's nearly impossible to determine ahead of
19261938
// time which it is... so we just try to parse both.
@@ -1948,7 +1960,7 @@ impl Parser {
19481960
// the '(' we've recently consumed does not start a derived table
19491961
// (cases 1, 2, or 4). Ignore the error and back up to where we
19501962
// were before - right after the opening '('.
1951-
self.index = index;
1963+
self.reset(checkpoint);
19521964

19531965
// Inside the parentheses we expect to find a table factor
19541966
// followed by some joins or another level of nesting.

0 commit comments

Comments
 (0)