Skip to content

Commit dc64ce4

Browse files
authored
Encapsulate parser and parse state. (#135)
1 parent 7c2d9cd commit dc64ce4

File tree

8 files changed

+65
-29
lines changed

8 files changed

+65
-29
lines changed

partiql-conformance-test-generator/src/generator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn test_case_to_function(test_case: &TestCase) -> Function {
4545
match &test_case.test_kind {
4646
Parse(ParseTestCase { parse_assertions }) => {
4747
test_fn.line(format!("let query = r#\"{}\"#;", &test_case.statement));
48-
test_fn.line("let res = partiql_parser::parse_partiql(query);");
48+
test_fn.line("let res = partiql_parser::Parser::default().parse(query);");
4949
match parse_assertions {
5050
ParseAssertions::ParsePass => test_fn
5151
.line(r#"assert!(res.is_ok(), "For `{}`, expected `Ok(_)`, but was `{:#?}`", query, res);"#),

partiql-parser/src/result.rs renamed to partiql-parser/src/error.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,14 @@
55
use std::borrow::Cow;
66
use std::fmt::{Debug, Display};
77

8-
use partiql_ast::ast;
98
use partiql_source_map::location::{LineAndColumn, Located};
109
use thiserror::Error;
1110

1211
/// [`Error`] type for errors in the lexical structure for the PartiQL parser.
13-
pub type LexicalError<'input> = crate::result::LexError<'input>;
12+
pub type LexicalError<'input> = crate::error::LexError<'input>;
1413

1514
/// [`Error`] type for errors in the syntactic structure for the PartiQL parser.
16-
pub type ParserError<'input> = crate::result::ParseError<'input, LineAndColumn>;
17-
18-
/// General [`Result`] type for the PartiQL parser.
19-
pub type ParserResult<'input> = Result<Box<ast::Expr>, Vec<ParserError<'input>>>;
15+
pub type ParserError<'input> = crate::error::ParseError<'input, LineAndColumn>;
2016

2117
/// Errors in the lexical structure of a PartiQL query.
2218
///

partiql-parser/src/lexer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::cmp::max;
88
use std::fmt;
99
use std::fmt::Formatter;
1010

11-
use crate::result::{LexError, ParseError};
11+
use crate::error::{LexError, ParseError};
1212
use partiql_source_map::line_offset_tracker::LineOffsetTracker;
1313

1414
/// A 3-tuple of (start, `Tok`, end) denoting a token and it start and end offsets.

partiql-parser/src/lib.rs

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,64 @@
55
//! # Usage
66
//!
77
//! ```
8-
//! use partiql_parser::{parse_partiql, ParserError, ParserResult};
8+
//! use partiql_parser::{Parser, ParserError, ParserResult};
99
//!
10-
//! let ast = parse_partiql("SELECT g FROM data GROUP BY a").expect("successful parse");
10+
//! let parser = Parser::default();
1111
//!
12-
//! let errs: Vec<ParserError> = parse_partiql("SELECT").expect_err("expected error");
13-
//! assert_eq!(errs[0].to_string(), "Unexpected end of input");
12+
//! let parsed = parser.parse("SELECT g FROM data GROUP BY a").expect("successful parse");
13+
//!
14+
//! let errs: Vec<ParserError> = parser.parse("SELECT").expect_err("expected error");
1415
//!
1516
//! let errs_at: Vec<ParserError> =
16-
//! parse_partiql("SELECT * FROM a AY a CROSS JOIN c AS c AT q").unwrap_err();
17+
//! parser.parse("SELECT * FROM a AY a CROSS JOIN c AS c AT q").unwrap_err();
1718
//! assert_eq!(errs_at[0].to_string(), "Unexpected token `<a:UNQUOTED_IDENT>` at `(1:20..1:21)`");
1819
//! ```
1920
//!
2021
//! [partiql]: https://partiql.org
2122
23+
mod error;
2224
mod lexer;
2325
mod parse;
2426
mod preprocessor;
25-
mod result;
2627
mod token_parser;
2728

28-
pub use result::LexError;
29-
pub use result::LexicalError;
30-
pub use result::ParseError;
31-
pub use result::ParserError;
32-
pub use result::ParserResult;
29+
use parse::parse_partiql;
30+
use partiql_ast::ast;
31+
use partiql_source_map::line_offset_tracker::LineOffsetTracker;
32+
33+
pub use error::LexError;
34+
pub use error::LexicalError;
35+
pub use error::ParseError;
36+
pub use error::ParserError;
37+
38+
/// General [`Result`] type for the PartiQL [`Parser`].
39+
pub type ParserResult<'input> = Result<Parsed<'input>, Vec<ParserError<'input>>>;
40+
41+
/// A PartiQL parser from statement strings to AST.
42+
#[non_exhaustive]
43+
#[derive(Debug)]
44+
pub struct Parser {}
45+
46+
impl Default for Parser {
47+
fn default() -> Self {
48+
Parser {}
49+
}
50+
}
51+
52+
impl Parser {
53+
/// Parse a PartiQL statement into an AST.
54+
pub fn parse<'input>(&self, text: &'input str) -> ParserResult<'input> {
55+
let mut offsets = LineOffsetTracker::default();
56+
let ast = parse_partiql(text, &mut offsets)?;
57+
Ok(Parsed { text, offsets, ast })
58+
}
59+
}
3360

34-
pub use parse::parse_partiql;
61+
/// The output of parsing PartiQL statement strings: an AST and auxiliary data.
62+
#[non_exhaustive]
63+
#[derive(Debug)]
64+
pub struct Parsed<'input> {
65+
text: &'input str,
66+
offsets: LineOffsetTracker,
67+
ast: Box<ast::Expr>,
68+
}

partiql-parser/src/parse/mod.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
//! Provides the [`parse_partiql`] function to parse a PartiQL query.
44
5-
use crate::lexer;
5+
use crate::error::{ParseError, UnexpectedTokenData};
66
use crate::preprocessor::{built_ins, FnExprSet, PreprocessingPartiqlLexer};
7-
use crate::result::{ParseError, ParserResult, UnexpectedTokenData};
7+
use crate::{lexer, ParserError};
88
use lalrpop_util as lpop;
99
use lazy_static::lazy_static;
1010
use partiql_ast::ast;
@@ -30,19 +30,20 @@ type LalrpopResult<'input> = Result<Box<ast::Expr>, LalrpopError<'input>>;
3030
type LalrpopErrorRecovery<'input> =
3131
lpop::ErrorRecovery<ByteOffset, lexer::Token<'input>, ParseError<'input, BytePosition>>;
3232

33+
pub(crate) type AstResult<'input> = Result<Box<ast::Expr>, Vec<ParserError<'input>>>;
34+
3335
lazy_static! {
3436
static ref BUILT_INS: FnExprSet<'static> = built_ins();
3537
}
3638

3739
/// Parse PartiQL query text.
38-
pub fn parse_partiql(s: &str) -> ParserResult {
39-
let mut offsets = LineOffsetTracker::default();
40+
pub fn parse_partiql<'input>(s: &'input str, offsets: &mut LineOffsetTracker) -> AstResult<'input> {
4041
let mut errors: Vec<LalrpopErrorRecovery> = vec![];
41-
let lexer = PreprocessingPartiqlLexer::new(s, &mut offsets, &*BUILT_INS);
42+
let lexer = PreprocessingPartiqlLexer::new(s, offsets, &*BUILT_INS);
4243

4344
let parsed: LalrpopResult = grammar::QueryParser::new().parse(s, &mut errors, lexer);
4445

45-
process_errors(s, &offsets, parsed, errors)
46+
process_errors(s, offsets, parsed, errors)
4647
}
4748

4849
fn process_errors<'input, T>(
@@ -124,6 +125,10 @@ impl<'input> From<LalrpopError<'input>> for ParseError<'input, BytePosition> {
124125
#[cfg(test)]
125126
mod tests {
126127
use super::*;
128+
pub fn parse_partiql(s: &str) -> AstResult {
129+
let mut offsets = LineOffsetTracker::default();
130+
super::parse_partiql(s, &mut offsets)
131+
}
127132

128133
macro_rules! parse {
129134
($q:expr) => {{
@@ -578,7 +583,7 @@ mod tests {
578583

579584
mod errors {
580585
use super::*;
581-
use crate::result::{LexicalError, UnexpectedToken, UnexpectedTokenData};
586+
use crate::error::{LexicalError, UnexpectedToken, UnexpectedTokenData};
582587
use partiql_source_map::location::{
583588
CharOffset, LineAndCharPosition, LineOffset, Located, Location,
584589
};

partiql-parser/src/parse/partiql.lalrpop

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::parse::lexer;
2-
use crate::result::ParseError;
2+
use crate::error::ParseError;
33

44
use lalrpop_util as lpop;
55

partiql-parser/src/preprocessor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::collections::VecDeque;
55

66
use std::ops::Range;
77

8-
use crate::result::LexError;
8+
use crate::error::LexError;
99

1010
use crate::lexer::{InternalLexResult, LexResult, PartiqlLexer, Spanned, Token};
1111

partiql-source-map/src/line_offset_tracker.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use std::ops::Range;
2727
/// assert_eq!(tracker.at(source, ByteOffset(30).into()), Ok(LineAndCharPosition::new(3,4)));
2828
/// assert_eq!(tracker.at(source, ByteOffset(300).into()), Err(LineOffsetError::EndOfInput));
2929
/// ```
30+
#[derive(Debug)]
3031
pub struct LineOffsetTracker {
3132
line_starts: SmallVec<[ByteOffset; 16]>,
3233
}

0 commit comments

Comments
 (0)