Skip to main content

surql_parser/upstream/syn/parser/
function.rs

1use super::{ParseResult, Parser};
2use crate::upstream::sql::{Expr, Function, FunctionCall, Model};
3use crate::upstream::syn::error::{bail, syntax_error};
4use crate::upstream::syn::parser::mac::{expected, expected_whitespace, unexpected};
5use crate::upstream::syn::token::{TokenKind, t};
6use reblessive::Stk;
7impl Parser<'_> {
8	pub async fn parse_function_name(&mut self) -> ParseResult<Function> {
9		let peek = self.peek();
10		let fnc = match peek.kind {
11			t!("fn") => {
12				self.pop_peek();
13				expected!(self, t!("::"));
14				let mut name = self.parse_ident()?;
15				while self.eat(t!("::")) {
16					name.push_str("::");
17					name.push_str(self.parse_ident_str()?);
18				}
19				Function::Custom(name)
20			}
21			t!("mod") => {
22				self.pop_peek();
23				if !self.settings.surrealism_enabled {
24					bail!(
25						"Experimental capability `surrealism` is not enabled", @ self
26						.last_span() => "Use of `mod::` is still experimental"
27					)
28				}
29				expected!(self, t!("::"));
30				let name = self.parse_ident()?;
31				let sub = if self.eat(t!("::")) {
32					Some(self.parse_ident()?)
33				} else {
34					None
35				};
36				Function::Module(name, sub)
37			}
38			t!("silo") => {
39				self.pop_peek();
40				if !self.settings.surrealism_enabled {
41					bail!(
42						"Experimental capability `surrealism` is not enabled", @ self
43						.last_span() => "Use of `silo::` is still experimental"
44					)
45				}
46				expected!(self, t!("::"));
47				let org = self.parse_ident()?;
48				expected!(self, t!("::"));
49				let pkg = self.parse_ident()?;
50				expected!(self, t!("<"));
51				let major = self.parse_version_digits()?;
52				expected!(self, t!("."));
53				let minor = self.parse_version_digits()?;
54				expected!(self, t!("."));
55				let patch = self.parse_version_digits()?;
56				expected!(self, t!(">"));
57				let sub = if self.eat(t!("::")) {
58					Some(self.parse_ident()?)
59				} else {
60					None
61				};
62				Function::Silo {
63					org,
64					pkg,
65					major,
66					minor,
67					patch,
68					sub,
69				}
70			}
71			t!("ml") => {
72				self.pop_peek();
73				expected!(self, t!("::"));
74				let mut name = self.parse_ident()?;
75				while self.eat(t!("::")) {
76					name.push_str("::");
77					name.push_str(self.parse_ident_str()?);
78				}
79				let (major, minor, patch) = self.parse_model_version()?;
80				let version = format!("{}.{}.{}", major, minor, patch);
81				Function::Model(Model { name, version })
82			}
83			TokenKind::Identifier => {
84				let mut name = self.parse_ident()?;
85				while self.eat(t!("::")) {
86					name.push_str("::");
87					name.push_str(self.parse_ident_str()?)
88				}
89				Function::Normal(name)
90			}
91			x if Self::kind_is_keyword_like(x) => {
92				self.pop_peek();
93				let mut name = self.lexer.span_str(peek.span).to_string();
94				while self.eat(t!("::")) {
95					name.push_str("::");
96					name.push_str(self.parse_ident_str()?)
97				}
98				Function::Normal(name)
99			}
100			_ => unexpected!(self, self.peek(), "a function name"),
101		};
102		Ok(fnc)
103	}
104	/// Parse a custom function function call
105	///
106	/// Expects `fn` to already be called.
107	pub(super) async fn parse_custom_function(
108		&mut self,
109		stk: &mut Stk,
110	) -> ParseResult<FunctionCall> {
111		expected!(self, t!("::"));
112		let mut name = self.parse_ident()?;
113		while self.eat(t!("::")) {
114			name.push_str("::");
115			name.push_str(self.parse_ident_str()?)
116		}
117		expected!(self, t!("(")).span;
118		let args = self.parse_function_args(stk).await?;
119		let name = Function::Custom(name);
120		Ok(FunctionCall {
121			receiver: name,
122			arguments: args,
123		})
124	}
125	/// Parse a module function function call
126	///
127	/// Expects `mod` to already be called.
128	pub(super) async fn parse_module_function(
129		&mut self,
130		stk: &mut Stk,
131	) -> ParseResult<FunctionCall> {
132		if !self.settings.surrealism_enabled {
133			bail!(
134				"Experimental capability `surrealism` is not enabled", @ self.last_span()
135				=> "Use of `mod::` is still experimental"
136			)
137		}
138		expected!(self, t!("::"));
139		let name = self.parse_ident()?;
140		let sub = if self.eat(t!("::")) {
141			Some(self.parse_ident()?)
142		} else {
143			None
144		};
145		expected!(self, t!("(")).span;
146		let args = self.parse_function_args(stk).await?;
147		let name = Function::Module(name, sub);
148		Ok(FunctionCall {
149			receiver: name,
150			arguments: args,
151		})
152	}
153	/// Parse a silo function function call
154	///
155	/// Expects `silo` to already be called.
156	pub(super) async fn parse_silo_function(&mut self, stk: &mut Stk) -> ParseResult<FunctionCall> {
157		if !self.settings.surrealism_enabled {
158			bail!(
159				"Experimental capability `surrealism` is not enabled", @ self.last_span()
160				=> "Use of `silo::` is still experimental"
161			)
162		}
163		expected!(self, t!("::"));
164		let org = self.parse_ident()?;
165		expected!(self, t!("::"));
166		let pkg = self.parse_ident()?;
167		expected!(self, t!("<"));
168		let major = self.parse_version_digits()?;
169		expected!(self, t!("."));
170		let minor = self.parse_version_digits()?;
171		expected!(self, t!("."));
172		let patch = self.parse_version_digits()?;
173		expected!(self, t!(">"));
174		let sub = if self.eat(t!("::")) {
175			Some(self.parse_ident()?)
176		} else {
177			None
178		};
179		expected!(self, t!("(")).span;
180		let args = self.parse_function_args(stk).await?;
181		let name = Function::Silo {
182			org,
183			pkg,
184			major,
185			minor,
186			patch,
187			sub,
188		};
189		Ok(FunctionCall {
190			receiver: name,
191			arguments: args,
192		})
193	}
194	pub(super) async fn parse_function_args(&mut self, stk: &mut Stk) -> ParseResult<Vec<Expr>> {
195		let start = self.last_span();
196		let mut args = Vec::new();
197		loop {
198			if self.eat(t!(")")) {
199				break;
200			}
201			let arg = stk.run(|ctx| self.parse_expr_inherit(ctx)).await?;
202			args.push(arg);
203			if !self.eat(t!(",")) {
204				self.expect_closing_delimiter(t!(")"), start)?;
205				break;
206			}
207		}
208		Ok(args)
209	}
210	pub fn parse_version_digits(&mut self) -> ParseResult<u32> {
211		let token = self.next();
212		match token.kind {
213			TokenKind::Digits => self
214				.span_str(token.span)
215				.parse::<u32>()
216				.map_err(|e| syntax_error!("Failed to parse model version: {e}", @ token.span)),
217			_ => unexpected!(self, token, "an integer"),
218		}
219	}
220	pub(super) fn parse_model_version(&mut self) -> ParseResult<(u32, u32, u32)> {
221		let start = expected!(self, t!("<")).span;
222		let major: u32 = self.parse_version_digits()?;
223		expected_whitespace!(self, t!("."));
224		let minor: u32 = self.parse_version_digits()?;
225		expected_whitespace!(self, t!("."));
226		let patch: u32 = self.parse_version_digits()?;
227		self.expect_closing_delimiter(t!(">"), start)?;
228		Ok((major, minor, patch))
229	}
230	/// Parse a model invocation
231	///
232	/// Expects `ml` to already be called.
233	pub(super) async fn parse_model(&mut self, stk: &mut Stk) -> ParseResult<FunctionCall> {
234		expected!(self, t!("::"));
235		let mut name = self.parse_ident()?;
236		while self.eat(t!("::")) {
237			name.push_str("::");
238			name.push_str(self.parse_ident_str()?)
239		}
240		let (major, minor, patch) = self.parse_model_version()?;
241		let start = expected!(self, t!("(")).span;
242		let mut args = Vec::new();
243		loop {
244			if self.eat(t!(")")) {
245				break;
246			}
247			let arg = stk.run(|ctx| self.parse_expr_inherit(ctx)).await?;
248			args.push(arg);
249			if !self.eat(t!(",")) {
250				self.expect_closing_delimiter(t!(")"), start)?;
251				break;
252			}
253		}
254		let func = Function::Model(Model {
255			name,
256			version: format!("{}.{}.{}", major, minor, patch),
257		});
258		Ok(FunctionCall {
259			receiver: func,
260			arguments: args,
261		})
262	}
263}