Skip to content

Commit 9563ec6

Browse files
authored
Adds initial PEG, basic recognizer API, and Error/Result APIs. (#8)
Adds `pest`/`pest_derive` dependencies and a very basic PEG definition that is just a stream of PartiQL keywords. This implementation is just to flesh out some of the usage of `pest`, namely the derivation macro and its error APIs. This commit exposes a function `recognize_partiql` that runs the parser over an input slice and returns `()` on success or fails on invalid syntax. Given that the syntax is just a stream of keywords, this is not particularly interesting right now. Adds the following modules: * `result` contains the main `ParserError` enum, `Position`, and `ParserResult` alias. * `prelude` exports most of `result` and will be used in the future for things like traits as well. * `peg` is the module that hosts the low-level Pest PEG parser and the grammar definition file. Other notes: * Adds `From` implementation for `pest::error::Error` for `ParserError` to do basic translation of the relatively obtuse Pest error to something a bit more friendly. * Updates README around versioning. * Changes stub tests to just be no-op for the non-parser packages. * Adds dependency for `thiserror` for less boilerplate error definitions. * Adds dev dependency for `rstest` for table driven testing.
1 parent 28e8d3b commit 9563ec6

File tree

10 files changed

+431
-18
lines changed

10 files changed

+431
-18
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,14 @@ This is a collection of crates to provide Rust support for the [PartiQL][partiql
1111
***The crates in this repository are considered experimental, under active/early development,
1212
and APIs are subject to change.***
1313

14-
This project uses [workspaces][workspaces] to manage the crates in this repository.
14+
This project uses [workspaces][workspaces] to manage the crates in this repository. The `partiql` crate is intended
15+
to be the crate that exports all the relevant `partiql-*` sub-crate functionality. It is factored in this way
16+
to make applications needing only some sub-component of the PartiQL implementation possible (e.g. an application
17+
that only requires the PartiQL parser can depend on `partiql-parser` directly).
18+
19+
Due to the lack of namespacing in [crates.io][crates], we have published `0.0.0` versions for the sub-crates we know
20+
we will need. A crate with a version `0.1.0` or higher, should have real, albeit potentially very experimental and/or
21+
early implementations.
1522

1623
## Security
1724

@@ -22,4 +29,5 @@ See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more inform
2229
This project is licensed under the Apache-2.0 License.
2330

2431
[partiql]: https://partiql.org/
25-
[workspaces]: https://doc.rust-lang.org/stable/cargo/reference/workspaces.html
32+
[workspaces]: https://doc.rust-lang.org/stable/cargo/reference/workspaces.html
33+
[crates]: https://crates.io/policies

partiql-eval/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#[cfg(test)]
22
mod tests {
33
#[test]
4-
fn it_works() {
5-
assert_eq!(2 + 2, 4);
6-
}
4+
fn todo() {}
75
}

partiql-irgen/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#[cfg(test)]
22
mod tests {
33
#[test]
4-
fn it_works() {
5-
assert_eq!(2 + 2, 4);
6-
}
4+
fn todo() {}
75
}

partiql-parser/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,9 @@ version = "0.0.0"
2020
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
2121

2222
[dependencies]
23+
pest = "~2.1.3"
24+
pest_derive = "~2.1.0"
25+
thiserror = "~1.0.24"
26+
27+
[dev-dependencies]
28+
rstest = "~0.9.0"

partiql-parser/src/lib.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
#[cfg(test)]
2-
mod tests {
3-
#[test]
4-
fn it_works() {
5-
assert_eq!(2 + 2, 4);
6-
}
7-
}
1+
// Copyright Amazon.com, Inc. or its affiliates.
2+
3+
//! Provides a parser for the [PartiQL][partiql] query language.
4+
//!
5+
//! [partiql]: https://partiql.org
6+
7+
mod peg;
8+
pub mod prelude;
9+
pub mod result;
10+
11+
pub use peg::recognize_partiql;

partiql-parser/src/partiql.pest

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
WHITESPACE = _{ " " | "\t" | "\x0B" | "\x0C" | "\r" | "\n" }
2+
3+
// really basic rules to just detect a sequence of keywords
4+
// two dip our toes in Pest
5+
6+
Keywords = _{ SOI ~ Keyword+ ~ EOI}
7+
8+
Keyword = { AllKeywords }
9+
10+
AllKeywords = _{
11+
SqlKeywords
12+
| PartiqlKeywords
13+
}
14+
15+
SqlKeywords = _{
16+
^"absolute"
17+
| ^"action"
18+
| ^"add"
19+
| ^"all"
20+
| ^"allocate"
21+
| ^"alter"
22+
| ^"and"
23+
| ^"any"
24+
| ^"are"
25+
| ^"as"
26+
| ^"asc"
27+
| ^"assertion"
28+
| ^"at"
29+
| ^"authorization"
30+
| ^"avg"
31+
| ^"begin"
32+
| ^"between"
33+
| ^"bit"
34+
| ^"bit_length"
35+
| ^"by"
36+
| ^"cascade"
37+
| ^"cascaded"
38+
| ^"case"
39+
| ^"cast"
40+
| ^"catalog"
41+
| ^"char"
42+
| ^"character"
43+
| ^"character_length"
44+
| ^"char_length"
45+
| ^"check"
46+
| ^"close"
47+
| ^"coalesce"
48+
| ^"collate"
49+
| ^"collation"
50+
| ^"column"
51+
| ^"commit"
52+
| ^"connect"
53+
| ^"connection"
54+
| ^"constraint"
55+
| ^"constraints"
56+
| ^"continue"
57+
| ^"convert"
58+
| ^"corresponding"
59+
| ^"count"
60+
| ^"create"
61+
| ^"cross"
62+
| ^"current"
63+
| ^"current_date"
64+
| ^"current_time"
65+
| ^"current_timestamp"
66+
| ^"current_user"
67+
| ^"cursor"
68+
| ^"date"
69+
| ^"deallocate"
70+
| ^"dec"
71+
| ^"decimal"
72+
| ^"declare"
73+
| ^"default"
74+
| ^"deferrable"
75+
| ^"deferred"
76+
| ^"delete"
77+
| ^"desc"
78+
| ^"describe"
79+
| ^"descriptor"
80+
| ^"diagnostics"
81+
| ^"disconnect"
82+
| ^"distinct"
83+
| ^"domain"
84+
| ^"double"
85+
| ^"drop"
86+
| ^"else"
87+
| ^"end"
88+
| ^"end-exec"
89+
| ^"escape"
90+
| ^"except"
91+
| ^"exception"
92+
| ^"exec"
93+
| ^"execute"
94+
| ^"exists"
95+
| ^"external"
96+
| ^"extract"
97+
| ^"date_add"
98+
| ^"date_diff"
99+
| ^"false"
100+
| ^"fetch"
101+
| ^"first"
102+
| ^"float"
103+
| ^"for"
104+
| ^"foreign"
105+
| ^"found"
106+
| ^"from"
107+
| ^"full"
108+
| ^"get"
109+
| ^"global"
110+
| ^"go"
111+
| ^"goto"
112+
| ^"grant"
113+
| ^"group"
114+
| ^"having"
115+
| ^"identity"
116+
| ^"immediate"
117+
| ^"in"
118+
| ^"indicator"
119+
| ^"initially"
120+
| ^"inner"
121+
| ^"input"
122+
| ^"insensitive"
123+
| ^"insert"
124+
| ^"int"
125+
| ^"integer"
126+
| ^"intersect"
127+
| ^"interval"
128+
| ^"into"
129+
| ^"is"
130+
| ^"isolation"
131+
| ^"join"
132+
| ^"key"
133+
| ^"language"
134+
| ^"last"
135+
| ^"left"
136+
| ^"level"
137+
| ^"like"
138+
| ^"local"
139+
| ^"lower"
140+
| ^"match"
141+
| ^"max"
142+
| ^"min"
143+
| ^"module"
144+
| ^"names"
145+
| ^"national"
146+
| ^"natural"
147+
| ^"nchar"
148+
| ^"next"
149+
| ^"no"
150+
| ^"not"
151+
| ^"null"
152+
| ^"nullif"
153+
| ^"numeric"
154+
| ^"octet_length"
155+
| ^"of"
156+
| ^"on"
157+
| ^"only"
158+
| ^"open"
159+
| ^"option"
160+
| ^"or"
161+
| ^"order"
162+
| ^"outer"
163+
| ^"output"
164+
| ^"overlaps"
165+
| ^"pad"
166+
| ^"partial"
167+
| ^"position"
168+
| ^"precision"
169+
| ^"prepare"
170+
| ^"preserve"
171+
| ^"primary"
172+
| ^"prior"
173+
| ^"privileges"
174+
| ^"procedure"
175+
| ^"public"
176+
| ^"read"
177+
| ^"real"
178+
| ^"references"
179+
| ^"relative"
180+
| ^"restrict"
181+
| ^"revoke"
182+
| ^"right"
183+
| ^"rollback"
184+
| ^"rows"
185+
| ^"schema"
186+
| ^"scroll"
187+
| ^"section"
188+
| ^"select"
189+
| ^"session"
190+
| ^"session_user"
191+
| ^"set"
192+
| ^"size"
193+
| ^"smallint"
194+
| ^"some"
195+
| ^"space"
196+
| ^"sql"
197+
| ^"sqlcode"
198+
| ^"sqlerror"
199+
| ^"sqlstate"
200+
| ^"substring"
201+
| ^"sum"
202+
| ^"system_user"
203+
| ^"table"
204+
| ^"temporary"
205+
| ^"then"
206+
| ^"time"
207+
| ^"timestamp"
208+
| ^"to"
209+
| ^"transaction"
210+
| ^"translate"
211+
| ^"translation"
212+
| ^"trim"
213+
| ^"true"
214+
| ^"union"
215+
| ^"unique"
216+
| ^"unknown"
217+
| ^"update"
218+
| ^"upper"
219+
| ^"usage"
220+
| ^"user"
221+
| ^"using"
222+
| ^"value"
223+
| ^"values"
224+
| ^"varchar"
225+
| ^"varying"
226+
| ^"view"
227+
| ^"when"
228+
| ^"whenever"
229+
| ^"where"
230+
| ^"with"
231+
| ^"work"
232+
| ^"write"
233+
| ^"zone"
234+
}
235+
236+
PartiqlKeywords = _{
237+
^"missing"
238+
| ^"pivot"
239+
| ^"unpivot"
240+
| ^"limit"
241+
| ^"tuple"
242+
| ^"remove"
243+
| ^"index"
244+
| ^"conflict"
245+
| ^"do"
246+
| ^"nothing"
247+
| ^"returning"
248+
| ^"modified"
249+
| ^"all"
250+
| ^"new"
251+
| ^"old"
252+
| ^"let"
253+
| ^"bool"
254+
| ^"boolean"
255+
| ^"string"
256+
| ^"symbol"
257+
| ^"clob"
258+
| ^"blob"
259+
| ^"struct"
260+
| ^"list"
261+
| ^"sexp"
262+
| ^"bag"
263+
}

partiql-parser/src/peg.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright Amazon.com, Inc. or its affiliates.
2+
3+
//! Contains the [Pest](https://pest.rs) defined parser for PartiQL and a wrapper APIs that
4+
//! can be exported for users to consume.
5+
6+
use crate::prelude::*;
7+
use pest::Parser;
8+
use pest_derive::Parser;
9+
10+
#[derive(Parser)]
11+
#[grammar = "partiql.pest"]
12+
struct PartiQLParser;
13+
14+
/// Recognizer for PartiQL queries.
15+
///
16+
/// Returns `Ok(())` in the case that the input is valid PartiQL. Returns `Err([ParserError])`
17+
/// in the case that the input is not valid PartiQL.
18+
///
19+
/// This API will be replaced with one that produces an AST in the future.
20+
pub fn recognize_partiql(input: &str) -> ParserResult<()> {
21+
PartiQLParser::parse(Rule::Keywords, input)?;
22+
Ok(())
23+
}
24+
25+
#[cfg(test)]
26+
mod tests {
27+
use super::*;
28+
29+
#[test]
30+
fn simple() -> ParserResult<()> {
31+
recognize_partiql("SELECT FROM WHERE")
32+
}
33+
34+
#[test]
35+
fn error() -> ParserResult<()> {
36+
match recognize_partiql("SELECT FROM MOO") {
37+
Err(ParserError::SyntaxError { position, .. }) => assert_eq!(
38+
Position::At {
39+
line: 1,
40+
column: 13
41+
},
42+
position
43+
),
44+
_ => panic!("Expected Syntax Error"),
45+
};
46+
Ok(())
47+
}
48+
}

partiql-parser/src/prelude.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright Amazon.com, Inc. or its affiliates.
2+
3+
//! Convenience export of common traits and basic types that are almost always
4+
//! needed when using the parser APIs.
5+
6+
pub use crate::result::ParserError;
7+
pub use crate::result::ParserResult;
8+
pub use crate::result::Position;

0 commit comments

Comments
 (0)