Skip to content

Commit 8f6b0d8

Browse files
committed
Support parser backtracking in the GreenNodeBuilder, part 2
This adds a `reset()` method to the GreenNodeBuilder previously imported from rowan and uses it to fix the CST in the testcases where parser has to backtrack in `parse_table_factor`.
1 parent b5fbe42 commit 8f6b0d8

File tree

4 files changed

+13
-7
lines changed

4 files changed

+13
-7
lines changed

src/builder.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
//! Based on the code from rowan:
1616
//! https://github.com/rust-analyzer/rowan/blob/v0.10.0/src/green/builder.rs
1717
//!
18+
//! This version adds the ability to reset the builder to a previous checkpoint
19+
//! to support backtracking in the SQL parser.
20+
//!
1821
//! The deviations are marked with `CHANGED(sqlparser)`.
1922
2023
// CHANGED(sqlparser): parts of the imported code may be unused
@@ -101,7 +104,7 @@ impl<T: Default> Default for MaybeOwned<'_, T> {
101104

102105
/// A checkpoint for maybe wrapping a node. See `GreenNodeBuilder::checkpoint` for details.
103106
#[derive(Clone, Copy, Debug)]
104-
pub struct Checkpoint(usize);
107+
pub struct Checkpoint(usize, usize); // CHANGED(sqlparser): added the depth field
105108

106109
/// A builder for a green tree.
107110
#[derive(Default, Debug)]
@@ -178,14 +181,20 @@ impl GreenNodeBuilder<'_> {
178181
/// ```
179182
#[inline]
180183
pub fn checkpoint(&self) -> Checkpoint {
181-
Checkpoint(self.children.len())
184+
Checkpoint(self.parents.len(), self.children.len())
185+
}
186+
187+
// CHANGED(sqlparser): added reset()
188+
pub fn reset(&mut self, checkpoint: Checkpoint) {
189+
self.parents.truncate(checkpoint.0);
190+
self.children.truncate(checkpoint.1);
182191
}
183192

184193
/// Wrap the previous branch marked by `checkpoint` in a new branch and
185194
/// make it current.
186195
#[inline]
187196
pub fn start_node_at(&mut self, checkpoint: Checkpoint, kind: SyntaxKind) {
188-
let Checkpoint(checkpoint) = checkpoint;
197+
let Checkpoint(_, checkpoint) = checkpoint; // CHANGED(sqlparser)
189198
assert!(
190199
checkpoint <= self.children.len(),
191200
"checkpoint no longer valid, was finish_node called early?"

src/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ impl Parser {
827827
pub fn reset(&mut self, m: Marker) {
828828
self.index = m.index;
829829
self.pending.truncate(0);
830-
// TBD: rowan's builder does not allow reverting to a checkpoint
830+
self.builder.reset(m.builder_checkpoint);
831831
}
832832

833833
pub fn complete<T>(&mut self, m: Marker, kind: cst::SyntaxKind, rv: T) -> T {

tests/sqlparser_common.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,7 +1942,6 @@ fn parse_complex_join() {
19421942
}
19431943

19441944
#[test]
1945-
#[ignore = "TBD (fixed in a later commit): backtracking"]
19461945
fn parse_join_nesting() {
19471946
fn table(name: impl Into<String>) -> TableFactor {
19481947
TableFactor::Table {
@@ -2110,7 +2109,6 @@ fn parse_cte_renamed_columns() {
21102109
}
21112110

21122111
#[test]
2113-
#[ignore = "TBD (fixed in a later commit): backtracking"]
21142112
fn parse_derived_tables() {
21152113
let sql = "SELECT a.x, b.y FROM (SELECT x FROM foo) AS a CROSS JOIN (SELECT y FROM bar) AS b";
21162114
let _ = verified_only_select(sql);

tests/sqlparser_postgres.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,6 @@ fn parse_create_table_if_not_exists() {
251251
}
252252

253253
#[test]
254-
#[ignore = "TBD (fixed in a later commit): backtracking"]
255254
fn parse_bad_if_not_exists() {
256255
let res = pg().parse_sql_statements("CREATE TABLE NOT EXISTS uk_cities ()");
257256
assert_eq!(

0 commit comments

Comments
 (0)