Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/pgt_lexer/src/lexed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub struct LexDiagnostic {
}

/// Result of lexing a string, providing access to tokens and diagnostics
#[derive(Debug)]
pub struct Lexed<'a> {
pub(crate) text: &'a str,
pub(crate) kind: Vec<SyntaxKind>,
Expand Down
8 changes: 7 additions & 1 deletion crates/pgt_statement_splitter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub fn split(sql: &str) -> SplitResult {

let mut splitter = Splitter::new(&lexed);

source(&mut splitter);
let _ = source(&mut splitter);

let split_result = splitter.finish();

Expand Down Expand Up @@ -587,4 +587,10 @@ VALUES
TextRange::new(0.into(), 6.into()),
)]);
}

#[test]
fn does_not_panic_on_incomplete_statements() {
// does not panic
let _ = Tester::from("select case ");
}
}
29 changes: 19 additions & 10 deletions crates/pgt_statement_splitter/src/splitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pub use common::source;
use pgt_lexer::{Lexed, SyntaxKind};
use pgt_text_size::TextRange;

use crate::splitter::common::{ReachedEOFException, SplitterResult};

pub struct SplitResult {
pub ranges: Vec<TextRange>,
pub errors: Vec<SplitError>,
Expand All @@ -29,6 +31,7 @@ pub struct SplitError {
pub token: usize,
}

#[derive(Debug)]
pub struct Splitter<'a> {
lexed: &'a Lexed<'a>,
current_pos: usize,
Expand Down Expand Up @@ -102,12 +105,12 @@ impl<'a> Splitter<'a> {
self.lexed.kind(self.current_pos)
}

fn eat(&mut self, kind: SyntaxKind) -> bool {
fn eat(&mut self, kind: SyntaxKind) -> Result<bool, ReachedEOFException> {
if self.current() == kind {
self.advance();
true
self.advance()?;
Ok(true)
} else {
false
Ok(false)
}
}

Expand All @@ -118,13 +121,17 @@ impl<'a> Splitter<'a> {
/// Advances the parser to the next relevant token and returns it.
///
/// NOTE: This will skip trivia tokens.
fn advance(&mut self) -> SyntaxKind {
fn advance(&mut self) -> Result<SyntaxKind, ReachedEOFException> {
if self.current() == SyntaxKind::EOF {
return Err(ReachedEOFException);
}

let pos = (self.current_pos + 1..self.lexed.len())
.find(|&idx| !self.is_trivia(idx))
.expect("lexed should have non-trivia eof token");
.unwrap();

self.current_pos = pos;
self.lexed.kind(pos)
Ok(self.lexed.kind(pos))
}

fn look_ahead(&self, ignore_trivia: bool) -> SyntaxKind {
Expand Down Expand Up @@ -164,9 +171,9 @@ impl<'a> Splitter<'a> {

/// Will advance if the `kind` matches the current token.
/// Otherwise, will add a diagnostic to the internal `errors`.
fn expect(&mut self, kind: SyntaxKind) {
fn expect(&mut self, kind: SyntaxKind) -> SplitterResult {
if self.current() == kind {
self.advance();
self.advance()?;
} else {
let token = if self.current() == SyntaxKind::EOF {
self.current_pos - 1
Expand All @@ -178,6 +185,8 @@ impl<'a> Splitter<'a> {
msg: format!("Expected {:#?}", kind),
token,
});
}
};

Ok(())
}
}
Loading