surql_parser/upstream/syn/parser/basic/
mod.rs1use crate::upstream::sql::Param;
2use crate::upstream::sql::language::Language;
3use crate::upstream::syn::error::bail;
4use crate::upstream::syn::lexer::Lexer;
5use crate::upstream::syn::lexer::compound::{self, ParsedInt};
6use crate::upstream::syn::parser::mac::unexpected;
7use crate::upstream::syn::parser::{ParseResult, Parser};
8use crate::upstream::syn::token::{Span, TokenKind, t};
9use rust_decimal::Decimal;
10mod number;
11pub trait TokenValue: Sized {
13 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self>;
14}
15impl TokenValue for Language {
16 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
17 let peek = parser.peek();
18 match peek.kind {
19 TokenKind::Language(x) => {
20 parser.pop_peek();
21 Ok(x)
22 }
23 t!("NO") => {
24 parser.pop_peek();
25 Ok(Language::Norwegian)
26 }
27 _ => unexpected!(parser, peek, "a language"),
28 }
29 }
30}
31impl TokenValue for Param {
32 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
33 let peek = parser.peek();
34 match peek.kind {
35 TokenKind::Parameter => {
36 parser.pop_peek();
37 let mut span = peek.span;
38 span.offset += 1;
39 span.len -= 1;
40 let ident = parser.unescape_ident_span(span)?;
41 Ok(Param::new(ident.to_owned()))
42 }
43 _ => unexpected!(parser, peek, "a parameter"),
44 }
45 }
46}
47impl TokenValue for surrealdb_types::Duration {
48 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
49 let token = parser.peek();
50 match token.kind {
51 TokenKind::Digits => {
52 parser.pop_peek();
53 let v = parser.lexer.lex_compound(token, compound::duration)?.value;
54 Ok(surrealdb_types::Duration::from(v))
55 }
56 _ => unexpected!(parser, token, "a duration"),
57 }
58 }
59}
60impl TokenValue for surrealdb_types::Datetime {
61 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
62 let token = parser.peek();
63 match token.kind {
64 t!("d\"") | t!("d'") => {
65 parser.pop_peek();
66 let str = parser.unescape_string_span(token.span)?;
67 let file = Lexer::lex_datetime(str).map_err(|e| {
68 e.update_spans(|span| {
69 let range = span.to_range();
70 let start =
71 Lexer::escaped_string_offset(parser.span_str(token.span), range.start);
72 let end =
73 Lexer::escaped_string_offset(parser.span_str(token.span), range.end);
74 *span = Span::from_range(
75 (token.span.offset + start)..(token.span.offset + end),
76 );
77 })
78 })?;
79 Ok(file)
80 }
81 _ => unexpected!(parser, token, "a datetime"),
82 }
83 }
84}
85impl TokenValue for surrealdb_types::Uuid {
86 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
87 let token = parser.peek();
88 match token.kind {
89 t!("u\"") | t!("u'") => {
90 parser.pop_peek();
91 let str = parser.unescape_string_span(token.span)?;
92 let file = Lexer::lex_uuid(str).map_err(|e| {
93 e.update_spans(|span| {
94 let range = span.to_range();
95 let start =
96 Lexer::escaped_string_offset(parser.span_str(token.span), range.start);
97 let end =
98 Lexer::escaped_string_offset(parser.span_str(token.span), range.end);
99 *span = Span::from_range(
100 (token.span.offset + start)..(token.span.offset + end),
101 );
102 })
103 })?;
104 Ok(file)
105 }
106 _ => unexpected!(parser, token, "a uuid"),
107 }
108 }
109}
110impl TokenValue for surrealdb_types::File {
111 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
112 let token = parser.peek();
113 if !parser.settings.files_enabled {
114 unexpected!(
115 parser,
116 token,
117 "the experimental files feature to be enabled"
118 );
119 }
120 match token.kind {
121 t!("f\"") | t!("f'") => {
122 parser.pop_peek();
123 let str = parser.unescape_string_span(token.span)?;
124 let file = Lexer::lex_file(str).map_err(|e| {
125 e.update_spans(|span| {
126 let range = span.to_range();
127 let start =
128 Lexer::escaped_string_offset(parser.span_str(token.span), range.start);
129 let end =
130 Lexer::escaped_string_offset(parser.span_str(token.span), range.end);
131 *span = Span::from_range(
132 (token.span.offset + start)..(token.span.offset + end),
133 );
134 })
135 })?;
136 Ok(file)
137 }
138 _ => unexpected!(parser, token, "a file"),
139 }
140 }
141}
142impl TokenValue for surrealdb_types::Bytes {
143 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
144 let token = parser.peek();
145 match token.kind {
146 t!("b\"") | t!("b'") => {
147 parser.pop_peek();
148 let str = parser.unescape_string_span(token.span)?;
149 let bytes = Lexer::lex_bytes(str).map_err(|e| {
150 e.update_spans(|span| {
151 let range = span.to_range();
152 let start =
153 Lexer::escaped_string_offset(parser.span_str(token.span), range.start);
154 let end =
155 Lexer::escaped_string_offset(parser.span_str(token.span), range.end);
156 *span = Span::from_range(
157 (token.span.offset + start)..(token.span.offset + end),
158 );
159 })
160 })?;
161 Ok(bytes)
162 }
163 _ => unexpected!(parser, token, "a bytestring"),
164 }
165 }
166}
167impl TokenValue for surrealdb_types::Regex {
168 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
169 let peek = parser.peek();
170 match peek.kind {
171 t!("/") => {
172 parser.pop_peek();
173 if parser.has_peek() {
174 parser.backup_after(peek.span);
175 }
176 let token = parser.lex_compound(peek, compound::regex)?;
177 let s = parser.unescape_regex_span(token.span)?;
178 match regex::Regex::new(s) {
179 Ok(x) => Ok(surrealdb_types::Regex::from(x)),
180 Err(e) => {
181 bail!("Invalid regex syntax {e}", @ token.span);
182 }
183 }
184 }
185 _ => unexpected!(parser, peek, "a regex"),
186 }
187 }
188}
189pub enum NumberToken {
190 Float(f64),
191 Integer(ParsedInt),
192 Decimal(Decimal),
193}
194impl TokenValue for NumberToken {
195 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
196 let token = parser.peek();
197 match token.kind {
198 t!("+") | t!("-") | TokenKind::Digits => {
199 parser.pop_peek();
200 let token = parser.lex_compound(token, compound::number)?;
201 match token.value {
202 compound::Numeric::Float(f) => Ok(NumberToken::Float(f)),
203 compound::Numeric::Integer(x) => Ok(NumberToken::Integer(x)),
204 compound::Numeric::Decimal(d) => Ok(NumberToken::Decimal(d)),
205 compound::Numeric::Duration(_) => {
206 bail!(
207 "Unexpected token `duration`, expected a number", @ token
208 .span
209 )
210 }
211 }
212 }
213 TokenKind::NaN => {
214 parser.pop_peek();
215 Ok(NumberToken::Float(f64::NAN))
216 }
217 TokenKind::Infinity => {
218 parser.pop_peek();
219 Ok(NumberToken::Float(f64::INFINITY))
220 }
221 _ => unexpected!(parser, token, "a number"),
222 }
223 }
224}
225impl TokenValue for surrealdb_types::Number {
226 fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
227 let token = parser.next_token_value::<NumberToken>()?;
228 match token {
229 NumberToken::Float(x) => Ok(Self::Float(x)),
230 NumberToken::Integer(i) => Ok(Self::Int(i.into_int(parser.recent_span())?)),
231 NumberToken::Decimal(x) => Ok(Self::Decimal(x)),
232 }
233 }
234}
235impl Parser<'_> {
236 pub fn next_token_value<V: TokenValue>(&mut self) -> ParseResult<V> {
238 V::from_token(self)
239 }
240 pub fn parse_string_lit(&mut self) -> ParseResult<String> {
241 let token = self.peek();
242 match token.kind {
243 t!("\"") | t!("'") => {
244 self.pop_peek();
245 let str = self.unescape_string_span(token.span)?;
246 Ok(str.to_owned())
247 }
248 _ => unexpected!(self, token, "a strand"),
249 }
250 }
251 pub fn parse_ident(&mut self) -> ParseResult<String> {
252 self.parse_ident_str().map(|x| x.to_owned())
253 }
254 pub fn parse_ident_str(&mut self) -> ParseResult<&str> {
255 let token = self.next();
256 match token.kind {
257 TokenKind::Identifier => self.unescape_ident_span(token.span),
258 x if Self::kind_is_keyword_like(x) => Ok(self.span_str(token.span)),
259 _ => {
260 unexpected!(self, token, "an identifier");
261 }
262 }
263 }
264 pub fn parse_flexible_ident(&mut self) -> ParseResult<String> {
265 let token = self.next();
266 match token.kind {
267 TokenKind::Digits => {
268 let span = if let Some(peek) = self.peek_whitespace() {
269 match peek.kind {
270 x if Self::kind_is_keyword_like(x) => {
271 self.pop_peek();
272 token.span.covers(peek.span)
273 }
274 TokenKind::Identifier | TokenKind::NaN | TokenKind::Infinity => {
275 self.pop_peek();
276 token.span.covers(peek.span)
277 }
278 _ => token.span,
279 }
280 } else {
281 token.span
282 };
283 Ok(self.span_str(span).to_owned())
284 }
285 TokenKind::Identifier | TokenKind::NaN | TokenKind::Infinity => {
286 let str = self.unescape_ident_span(token.span)?;
287 Ok(str.to_owned())
288 }
289 x if Self::kind_is_keyword_like(x) => Ok(self.span_str(token.span).to_owned()),
290 _ => {
291 unexpected!(self, token, "an identifier");
292 }
293 }
294 }
295}