1use super::{
2 parse_delimited, parse_token, Ident, Lookahead, PackageName, Parse, ParseResult, Peek,
3};
4use crate::lexer::{Lexer, Token};
5use miette::SourceSpan;
6use serde::Serialize;
7
8#[derive(Debug, Clone, Serialize)]
10#[serde(rename_all = "camelCase")]
11pub struct Expr<'a> {
12 pub span: SourceSpan,
14 pub primary: PrimaryExpr<'a>,
16 pub postfix: Vec<PostfixExpr<'a>>,
18}
19
20impl<'a> Parse<'a> for Expr<'a> {
21 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
22 let primary = PrimaryExpr::parse(lexer)?;
23
24 let mut postfix = Vec::new();
27 while let Some((Ok(token), _)) = lexer.peek() {
28 match token {
29 Token::Dot => {
30 postfix.push(PostfixExpr::Access(Parse::parse(lexer)?));
31 }
32 Token::OpenBracket => {
33 postfix.push(PostfixExpr::NamedAccess(Parse::parse(lexer)?));
34 }
35 _ => break,
36 }
37 }
38
39 let start = primary.span();
40 let len = postfix.last().map_or(start.len(), |p| {
41 p.span().offset() + p.span().len() - start.offset()
42 });
43
44 Ok(Self {
45 span: SourceSpan::new(start.offset().into(), len),
46 primary,
47 postfix,
48 })
49 }
50}
51
52#[derive(Debug, Clone, Serialize)]
54#[serde(rename_all = "camelCase")]
55pub enum PrimaryExpr<'a> {
56 New(NewExpr<'a>),
58 Nested(NestedExpr<'a>),
60 Ident(Ident<'a>),
62}
63
64impl PrimaryExpr<'_> {
65 pub fn span(&self) -> SourceSpan {
67 match self {
68 PrimaryExpr::New(new) => new.span,
69 PrimaryExpr::Nested(nested) => nested.span,
70 PrimaryExpr::Ident(ident) => ident.span,
71 }
72 }
73}
74
75impl<'a> Parse<'a> for PrimaryExpr<'a> {
76 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
77 let mut lookahead = Lookahead::new(lexer);
78 if NewExpr::peek(&mut lookahead) {
79 Ok(Self::New(Parse::parse(lexer)?))
80 } else if NestedExpr::peek(&mut lookahead) {
81 Ok(Self::Nested(Parse::parse(lexer)?))
82 } else if Ident::peek(&mut lookahead) {
83 Ok(Self::Ident(Parse::parse(lexer)?))
84 } else {
85 Err(lookahead.error())
86 }
87 }
88}
89
90#[derive(Debug, Clone, Serialize)]
92#[serde(rename_all = "camelCase")]
93pub struct NewExpr<'a> {
94 pub span: SourceSpan,
96 pub package: PackageName<'a>,
98 pub arguments: Vec<InstantiationArgument<'a>>,
100}
101
102impl<'a> Parse<'a> for NewExpr<'a> {
103 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
104 let start = parse_token(lexer, Token::NewKeyword)?;
105 let package = PackageName::parse(lexer)?;
106 parse_token(lexer, Token::OpenBrace)?;
107 let arguments = parse_delimited(lexer, Token::CloseBrace, true)?;
108 let end = parse_token(lexer, Token::CloseBrace)?;
109 Ok(Self {
110 span: SourceSpan::new(
111 start.offset().into(),
112 (end.offset() + end.len()) - start.offset(),
113 ),
114 package,
115 arguments,
116 })
117 }
118}
119
120impl Peek for NewExpr<'_> {
121 fn peek(lookahead: &mut Lookahead) -> bool {
122 lookahead.peek(Token::NewKeyword)
123 }
124}
125
126#[derive(Debug, Clone, Serialize)]
128#[serde(rename_all = "camelCase")]
129pub enum InstantiationArgument<'a> {
130 Inferred(Ident<'a>),
132 Spread(Ident<'a>),
134 Named(NamedInstantiationArgument<'a>),
136 Fill(SourceSpan),
138}
139
140impl<'a> Parse<'a> for InstantiationArgument<'a> {
141 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
142 let mut lookahead = Lookahead::new(lexer);
143 if lookahead.peek(Token::Ellipsis) {
144 let span = parse_token(lexer, Token::Ellipsis)?;
146 match lexer.peek() {
147 Some((Ok(Token::Comma), _)) | Some((Ok(Token::CloseBrace), _)) => {
148 Ok(Self::Fill(span))
150 }
151 _ => {
152 Ok(Self::Spread(Parse::parse(lexer)?))
154 }
155 }
156 } else if NamedInstantiationArgument::peek(&mut lookahead) {
157 if let Some((Ok(Token::Colon), _)) = lexer.peek2() {
160 Ok(Self::Named(Parse::parse(lexer)?))
161 } else {
162 Ok(Self::Inferred(Parse::parse(lexer)?))
163 }
164 } else {
165 Err(lookahead.error())
166 }
167 }
168}
169
170impl Peek for InstantiationArgument<'_> {
171 fn peek(lookahead: &mut Lookahead) -> bool {
172 lookahead.peek(Token::Ellipsis) | NamedInstantiationArgument::peek(lookahead)
173 }
174}
175
176#[derive(Debug, Clone, Serialize)]
178#[serde(rename_all = "camelCase")]
179pub struct NamedInstantiationArgument<'a> {
180 pub name: InstantiationArgumentName<'a>,
182 pub expr: Expr<'a>,
184}
185
186impl<'a> Parse<'a> for NamedInstantiationArgument<'a> {
187 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
188 let name = Parse::parse(lexer)?;
189 parse_token(lexer, Token::Colon)?;
190 let expr = Parse::parse(lexer)?;
191 Ok(Self { name, expr })
192 }
193}
194
195impl Peek for NamedInstantiationArgument<'_> {
196 fn peek(lookahead: &mut Lookahead) -> bool {
197 InstantiationArgumentName::peek(lookahead)
198 }
199}
200
201#[derive(Debug, Clone, Serialize)]
203#[serde(rename_all = "camelCase")]
204pub enum InstantiationArgumentName<'a> {
205 Ident(Ident<'a>),
207 String(super::String<'a>),
209}
210
211impl InstantiationArgumentName<'_> {
212 pub fn as_str(&self) -> &str {
214 match self {
215 Self::Ident(ident) => ident.string,
216 Self::String(string) => string.value,
217 }
218 }
219}
220
221impl<'a> Parse<'a> for InstantiationArgumentName<'a> {
222 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
223 let mut lookahead = Lookahead::new(lexer);
224 if Ident::peek(&mut lookahead) {
225 Ok(Self::Ident(Parse::parse(lexer)?))
226 } else if super::String::peek(&mut lookahead) {
227 Ok(Self::String(Parse::parse(lexer)?))
228 } else {
229 Err(lookahead.error())
230 }
231 }
232}
233
234impl Peek for InstantiationArgumentName<'_> {
235 fn peek(lookahead: &mut Lookahead) -> bool {
236 Ident::peek(lookahead) || super::String::peek(lookahead)
237 }
238}
239
240impl InstantiationArgumentName<'_> {
241 pub fn span(&self) -> SourceSpan {
243 match self {
244 Self::Ident(ident) => ident.span,
245 Self::String(string) => string.span,
246 }
247 }
248}
249
250#[derive(Debug, Clone, Serialize)]
252#[serde(rename_all = "camelCase")]
253pub struct NestedExpr<'a> {
254 pub span: SourceSpan,
256 pub inner: Box<Expr<'a>>,
258}
259
260impl<'a> Parse<'a> for NestedExpr<'a> {
261 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
262 let start = parse_token(lexer, Token::OpenParen)?;
263 let inner = Box::new(Parse::parse(lexer)?);
264 let end = parse_token(lexer, Token::CloseParen)?;
265 Ok(Self {
266 span: SourceSpan::new(
267 start.offset().into(),
268 (end.offset() + end.len()) - start.offset(),
269 ),
270 inner,
271 })
272 }
273}
274
275impl Peek for NestedExpr<'_> {
276 fn peek(lookahead: &mut Lookahead) -> bool {
277 lookahead.peek(Token::OpenParen)
278 }
279}
280
281#[derive(Debug, Clone, Serialize)]
283#[serde(rename_all = "camelCase")]
284pub enum PostfixExpr<'a> {
285 Access(AccessExpr<'a>),
287 NamedAccess(NamedAccessExpr<'a>),
289}
290
291impl PostfixExpr<'_> {
292 pub fn span(&self) -> SourceSpan {
294 match self {
295 PostfixExpr::Access(access) => access.span,
296 PostfixExpr::NamedAccess(access) => access.span,
297 }
298 }
299}
300
301#[derive(Debug, Clone, Serialize)]
303#[serde(rename_all = "camelCase")]
304pub struct AccessExpr<'a> {
305 pub span: SourceSpan,
307 pub id: Ident<'a>,
309}
310
311impl<'a> Parse<'a> for AccessExpr<'a> {
312 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
313 let start = parse_token(lexer, Token::Dot)?;
314 let id: Ident = Parse::parse(lexer)?;
315 Ok(Self {
316 span: SourceSpan::new(
317 start.offset().into(),
318 id.span.offset() - start.offset() + id.span.len(),
319 ),
320 id,
321 })
322 }
323}
324
325impl Peek for AccessExpr<'_> {
326 fn peek(lookahead: &mut Lookahead) -> bool {
327 lookahead.peek(Token::Dot)
328 }
329}
330
331#[derive(Debug, Clone, Serialize)]
333#[serde(rename_all = "camelCase")]
334pub struct NamedAccessExpr<'a> {
335 pub span: SourceSpan,
337 pub string: super::String<'a>,
339}
340
341impl<'a> Parse<'a> for NamedAccessExpr<'a> {
342 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
343 let opening = parse_token(lexer, Token::OpenBracket)?;
344 let string = Parse::parse(lexer)?;
345 let closing = parse_token(lexer, Token::CloseBracket)?;
346 Ok(Self {
347 span: SourceSpan::new(
348 opening.offset().into(),
349 (closing.offset() + closing.len()) - opening.offset(),
350 ),
351 string,
352 })
353 }
354}
355
356impl Peek for NamedAccessExpr<'_> {
357 fn peek(lookahead: &mut Lookahead) -> bool {
358 lookahead.peek(Token::OpenBracket)
359 }
360}