1use std::{fmt, sync::Arc};
4
5use gramatika::{debug, Parse, ParseStreamer, Result, Span, Spanned, SpannedError, Token as _};
6
7use crate::{
8 common::{ArgumentList, TypeDecl},
9 token::{brace, keyword, operator, punct},
10 ParseStream, Token, TokenKind,
11};
12
13#[derive(Clone, DebugLisp)]
14pub enum Expr {
15 UnaryPre(UnaryPreExpr),
16 UnaryPost(UnaryPostExpr),
17 Binary(BinaryExpr),
18 Assignment(BinaryExpr),
19 FnCall(FnCallExpr),
20 TypeCtor(TypeCtorExpr),
21 Group(GroupExpr),
22 Bitcast(BitcastExpr),
23 Literal(Token),
24 Ident(IdentExpr),
25 Primary(PrimaryExpr),
26}
27
28#[derive(Clone, DebugLisp)]
29pub struct UnaryPreExpr {
30 pub op: Token,
31 pub expr: Arc<Expr>,
32}
33
34#[derive(Clone, DebugLisp)]
35pub struct UnaryPostExpr {
36 pub expr: Arc<Expr>,
37 pub op: Token,
38}
39
40#[derive(Clone, DebugLisp)]
41pub struct BinaryExpr {
42 pub lhs: Arc<Expr>,
43 pub op: Token,
44 pub rhs: Arc<Expr>,
45}
46
47#[derive(Clone, DebugLisp)]
48pub struct FnCallExpr {
49 pub ident: IdentExpr,
50 pub arguments: ArgumentList,
51}
52
53#[derive(Clone, DebugLisp)]
54pub struct TypeCtorExpr {
55 pub ty: TypeDecl,
56 pub arguments: ArgumentList,
57}
58
59#[derive(Clone, DebugLisp)]
60pub struct GroupExpr {
61 pub brace_open: Token,
62 pub expr: Arc<Expr>,
63 pub brace_close: Token,
64}
65
66#[derive(Clone, DebugLisp)]
67pub struct BitcastExpr {
68 pub keyword: Token,
69 pub ty: TypeDecl,
70 pub expr: GroupExpr,
71}
72
73#[derive(Clone, DebugLisp)]
74pub enum IdentExpr {
75 Namespaced(NamespacedIdent),
76 Leaf(Token),
77}
78
79#[derive(Clone, DebugLisp)]
80pub struct NamespacedIdent {
81 pub namespace: Token,
82 pub ident: Arc<IdentExpr>,
83}
84
85#[derive(Clone, DebugLisp)]
86pub enum IdentExprBuilder {
87 Namespaced(NamespacedIdentBuilder),
88 Leaf(Token),
89}
90
91#[derive(Clone, DebugLisp)]
92pub struct NamespacedIdentBuilder {
93 pub namespace: Token,
94 pub ident: Box<IdentExprBuilder>,
95}
96
97#[derive(Clone, DebugLisp)]
98pub struct PrimaryExpr {
99 pub expr: Arc<Expr>,
100 pub postfix: Option<PostfixExpr>,
101}
102
103struct PrimaryExprBuilder {
104 pub expr: Box<Expr>,
105 pub postfix: Option<PostfixExpr>,
106}
107
108#[derive(Clone, DebugLisp)]
109pub struct PostfixExpr {
110 pub accessor: Accessor,
111 pub expr: Arc<Expr>,
112 pub postfix: Option<Arc<PostfixExpr>>,
113}
114
115#[derive(Clone)]
116pub enum Accessor {
117 Dot(Token),
118 Index([Token; 2]),
119}
120
121impl gramatika::DebugLisp for Accessor {
122 fn fmt(&self, f: &mut fmt::Formatter<'_>, indent: usize) -> fmt::Result {
123 match self {
124 Accessor::Dot(token) => write!(f, "(Accessor::Dot {:?})", token),
125 Accessor::Index(tokens) => {
126 writeln!(f, "(Accessor::Index")?;
127 for token in tokens {
128 write!(f, "{}", debug::INDENT.repeat(indent + 1))?;
129 writeln!(f, "{:?},", token)?;
130 }
131 write!(f, "{})", debug::INDENT.repeat(indent))
132 }
133 }
134 }
135}
136
137trait RecursiveDescent {
140 type Token: gramatika::Token;
141
142 fn assignment(&mut self) -> Result<Expr>;
143 fn short_circuit_or(&mut self) -> Result<Expr>;
144 fn short_circuit_and(&mut self) -> Result<Expr>;
145 fn inclusive_or(&mut self) -> Result<Expr>;
146 fn exclusive_or(&mut self) -> Result<Expr>;
147 fn and(&mut self) -> Result<Expr>;
148 fn equality(&mut self) -> Result<Expr>;
149 fn relational(&mut self) -> Result<Expr>;
150 fn shift(&mut self) -> Result<Expr>;
151 fn additive(&mut self) -> Result<Expr>;
152 fn multiplicative(&mut self) -> Result<Expr>;
153 fn unary(&mut self) -> Result<Expr>;
154 fn binary(
155 &mut self,
156 operators: &[Self::Token],
157 operand_method: fn(&mut Self) -> Result<Expr>,
158 ) -> Result<Expr>;
159}
160
161impl Spanned for Expr {
164 fn span(&self) -> Span {
165 match self {
166 Expr::UnaryPre(inner) => inner.span(),
167 Expr::UnaryPost(inner) => inner.span(),
168 Expr::Binary(inner) => inner.span(),
169 Expr::Assignment(inner) => inner.span(),
170 Expr::FnCall(inner) => inner.span(),
171 Expr::TypeCtor(inner) => inner.span(),
172 Expr::Group(inner) => inner.span(),
173 Expr::Bitcast(inner) => inner.span(),
174 Expr::Literal(inner) => inner.span(),
175 Expr::Ident(inner) => inner.span(),
176 Expr::Primary(inner) => inner.span(),
177 }
178 }
179}
180
181impl Spanned for PrimaryExpr {
182 fn span(&self) -> Span {
183 match self.postfix {
184 Some(ref postfix) => self.expr.span().through(postfix.span()),
185 None => self.expr.span(),
186 }
187 }
188}
189
190impl Spanned for PostfixExpr {
191 fn span(&self) -> Span {
192 match self.postfix {
193 Some(ref postfix) => self.expr.span().through(postfix.span()),
194 None => self.expr.span(),
195 }
196 }
197}
198
199impl Spanned for IdentExpr {
200 fn span(&self) -> Span {
201 match self {
202 IdentExpr::Leaf(name) => name.span(),
203 IdentExpr::Namespaced(NamespacedIdent { namespace, ident }) => {
204 namespace.span().through(ident.span())
205 }
206 }
207 }
208}
209
210impl Spanned for FnCallExpr {
211 fn span(&self) -> Span {
212 self.ident.span().through(self.arguments.brace_close.span())
213 }
214}
215
216impl Spanned for BinaryExpr {
217 fn span(&self) -> Span {
218 self.lhs.span().through(self.rhs.span())
219 }
220}
221
222impl Spanned for UnaryPreExpr {
223 fn span(&self) -> Span {
224 self.op.span().through(self.expr.span())
225 }
226}
227
228impl Spanned for UnaryPostExpr {
229 fn span(&self) -> Span {
230 self.expr.span().through(self.op.span())
231 }
232}
233
234impl Spanned for TypeCtorExpr {
235 fn span(&self) -> Span {
236 self.ty.span().through(self.arguments.brace_close.span())
237 }
238}
239
240impl Spanned for GroupExpr {
241 fn span(&self) -> Span {
242 self.brace_open.span().through(self.brace_close.span())
243 }
244}
245
246impl Spanned for BitcastExpr {
247 fn span(&self) -> Span {
248 self.keyword.span().through(self.expr.brace_close.span())
249 }
250}
251
252impl Parse for Expr {
253 type Stream = ParseStream;
254
255 fn parse(input: &mut Self::Stream) -> Result<Self> {
256 input.assignment()
257 }
258}
259
260impl Parse for PrimaryExprBuilder {
261 type Stream = ParseStream;
262
263 fn parse(input: &mut Self::Stream) -> Result<Self> {
264 use TokenKind::*;
265
266 let expr = match input.peek() {
267 Some(token) => match token.as_matchable() {
268 (Type, _, _) => Ok(Expr::TypeCtor(input.parse::<TypeCtorExpr>()?)),
269 (Brace, "(", _) => Ok(Expr::Group(input.parse::<GroupExpr>()?)),
270 (Keyword, "bitcast", _) => Ok(Expr::Bitcast(input.parse::<BitcastExpr>()?)),
271 (IntLiteral, _, _) | (FloatLiteral, _, _) | (Keyword, "true" | "false", _) => {
272 let token = input.next().unwrap();
273 Ok(Expr::Literal(token))
274 }
275 (Ident, _, _) => {
276 let mut ident = input.parse::<IdentExprBuilder>()?;
277
278 if input.check(brace!["("]) {
279 let mut expr = &mut ident;
280 while let IdentExprBuilder::Namespaced(NamespacedIdentBuilder {
281 ident,
282 ..
283 }) = expr
284 {
285 expr = ident.as_mut();
286 }
287 let IdentExprBuilder::Leaf(name) = expr else {
288 unreachable!();
289 };
290 *name = input.upgrade_last(TokenKind::Ident, Token::function)?;
291 let arguments = input.parse::<ArgumentList>()?;
292
293 Ok(Expr::FnCall(FnCallExpr {
294 ident: ident.build(),
295 arguments,
296 }))
297 } else {
298 Ok(Expr::Ident(ident.build()))
299 }
300 }
301 (_, _, span) => Err(SpannedError {
302 message: "Expected expression".into(),
303 span: Some(span),
304 source: input.source(),
305 }),
306 },
307 None => Err(SpannedError {
308 message: "Unexpected end of input".into(),
309 source: input.source(),
310 span: input.prev().map(|token| token.span()),
311 }),
312 }?;
313
314 let postfix = match input.peek().map(|t| t.as_matchable()) {
315 Some((Punct, ".", _) | (Brace, "[", _)) => Some(input.parse::<PostfixExpr>()?),
316 _ => None,
317 };
318
319 Ok(PrimaryExprBuilder {
320 expr: Box::new(expr),
321 postfix,
322 })
323 }
324}
325
326impl PrimaryExprBuilder {
327 fn build(self) -> PrimaryExpr {
328 PrimaryExpr {
329 expr: self.expr.into(),
330 postfix: self.postfix,
331 }
332 }
333}
334
335impl Parse for FnCallExpr {
336 type Stream = ParseStream;
337
338 fn parse(input: &mut Self::Stream) -> Result<Self> {
339 let mut ident = input.parse::<IdentExprBuilder>()?;
340
341 let mut expr = &mut ident;
343 while let IdentExprBuilder::Namespaced(NamespacedIdentBuilder { ident, .. }) = expr {
344 expr = ident.as_mut();
345 }
346 let IdentExprBuilder::Leaf(name) = expr else {
347 unreachable!();
348 };
349 *name = input.upgrade_last(TokenKind::Ident, Token::function)?;
350
351 let arguments = input.parse::<ArgumentList>()?;
352
353 Ok(Self {
354 ident: ident.build(),
355 arguments,
356 })
357 }
358}
359
360impl Parse for TypeCtorExpr {
361 type Stream = ParseStream;
362
363 fn parse(input: &mut Self::Stream) -> Result<Self> {
364 let ty = input.parse::<TypeDecl>()?;
365 let arguments = input.parse::<ArgumentList>()?;
366
367 Ok(Self { ty, arguments })
368 }
369}
370
371impl Parse for GroupExpr {
372 type Stream = ParseStream;
373
374 fn parse(input: &mut Self::Stream) -> Result<Self> {
375 let brace_open = input.consume(brace!["("])?;
376 let expr = input.parse::<Expr>()?;
377 let brace_close = input.consume(brace![")"])?;
378
379 Ok(Self {
380 brace_open,
381 expr: Arc::new(expr),
382 brace_close,
383 })
384 }
385}
386
387impl Parse for BitcastExpr {
388 type Stream = ParseStream;
389
390 fn parse(input: &mut Self::Stream) -> Result<Self> {
391 let keyword = input.consume(keyword![bitcast])?;
392 input.consume(operator![<])?;
393 let ty = input.parse::<TypeDecl>()?;
394 input.consume(operator![>])?;
395 let expr = input.parse::<GroupExpr>()?;
396
397 Ok(Self { keyword, ty, expr })
398 }
399}
400
401impl Parse for IdentExprBuilder {
402 type Stream = ParseStream;
403
404 fn parse(input: &mut Self::Stream) -> Result<Self> {
405 let mut ident = input.consume_kind(TokenKind::Ident)?;
406
407 if input.check(punct![::]) {
408 ident = input.upgrade_last(TokenKind::Ident, Token::module)?;
409 input.consume(punct![::])?;
410
411 Ok(Self::Namespaced(NamespacedIdentBuilder {
412 namespace: ident,
413 ident: Box::new(input.parse()?),
414 }))
415 } else {
416 Ok(Self::Leaf(ident))
417 }
418 }
419}
420
421impl IdentExprBuilder {
422 pub fn build(&self) -> IdentExpr {
423 match self {
424 IdentExprBuilder::Leaf(name) => IdentExpr::Leaf(name.clone()),
425 IdentExprBuilder::Namespaced(NamespacedIdentBuilder { namespace, ident }) => {
426 IdentExpr::Namespaced(NamespacedIdent {
427 namespace: namespace.clone(),
428 ident: Arc::new(ident.build()),
429 })
430 }
431 }
432 }
433}
434
435impl From<&IdentExpr> for IdentExprBuilder {
436 fn from(value: &IdentExpr) -> Self {
437 match value {
438 IdentExpr::Leaf(name) => IdentExprBuilder::Leaf(name.clone()),
439 IdentExpr::Namespaced(NamespacedIdent { namespace, ident }) => {
440 IdentExprBuilder::Namespaced(NamespacedIdentBuilder {
441 namespace: namespace.clone(),
442 ident: Box::new(ident.as_ref().into()),
443 })
444 }
445 }
446 }
447}
448
449impl Parse for IdentExpr {
450 type Stream = ParseStream;
451
452 fn parse(input: &mut Self::Stream) -> Result<Self> {
453 Ok(input.parse::<IdentExprBuilder>()?.build())
454 }
455}
456
457impl Parse for PostfixExpr {
458 type Stream = ParseStream;
459
460 fn parse(input: &mut Self::Stream) -> Result<Self> {
461 use TokenKind::*;
462
463 if input.check(punct![.]) {
464 let dot = input.next().unwrap();
465 let accessor = Accessor::Dot(dot);
466
467 let mut expr = input.parse::<PrimaryExprBuilder>()?;
468 if let Expr::Ident(ident) = expr.expr.as_mut() {
469 if let IdentExpr::Leaf(name) = ident {
470 *name = input.upgrade(name.clone(), Token::field)?;
471 } else {
472 let mut builder = IdentExprBuilder::from(&*ident);
474 let mut ident_expr = &mut builder;
475 while let IdentExprBuilder::Namespaced(NamespacedIdentBuilder {
476 ident, ..
477 }) = ident_expr
478 {
479 ident_expr = ident.as_mut();
480 }
481 let IdentExprBuilder::Leaf(name) = ident_expr else {
482 unreachable!();
483 };
484 *name = input.upgrade(name.clone(), Token::field)?;
485 *ident = builder.build();
486 }
487 }
488
489 let postfix = match input.peek().map(|t| t.as_matchable()) {
490 Some((Punct, ".", _) | (Brace, "[", _)) => {
491 Some(Arc::new(input.parse::<PostfixExpr>()?))
492 }
493 _ => None,
494 };
495
496 Ok(Self {
497 accessor,
498 expr: Arc::new(Expr::Primary(expr.build())),
499 postfix,
500 })
501 } else {
502 let brace_open = input.consume(brace!["["])?;
503 let expr = input.parse::<Expr>()?;
504 let brace_close = input.consume(brace!["]"])?;
505
506 let postfix = match input.peek().map(|t| t.as_matchable()) {
507 Some((Punct, ".", _) | (Brace, "[", _)) => {
508 Some(Arc::new(input.parse::<PostfixExpr>()?))
509 }
510 _ => None,
511 };
512
513 Ok(Self {
514 accessor: Accessor::Index([brace_open, brace_close]),
515 expr: Arc::new(expr),
516 postfix,
517 })
518 }
519 }
520}
521
522impl RecursiveDescent for ParseStream {
525 type Token = Token;
526
527 fn assignment(&mut self) -> Result<Expr> {
528 let lhs = self.short_circuit_or()?;
529
530 if matches!(
532 self.peek().map(|t| t.as_matchable()),
533 Some((
534 TokenKind::Operator,
535 "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" | "<<=" | ">>=" | "=",
536 _
537 ))
538 ) {
539 let op = self.next().unwrap();
540 let value = self.assignment()?;
541
542 match &lhs {
543 Expr::Primary(PrimaryExpr { expr, .. })
544 if matches!(expr.as_ref(), Expr::Ident(_)) =>
545 {
546 Ok(Expr::Assignment(BinaryExpr {
547 lhs: Arc::new(lhs),
548 op,
549 rhs: Arc::new(value),
550 }))
551 }
552 other => Err(SpannedError {
553 message: "Invalid assignment target".into(),
554 source: self.source(),
555 span: Some(other.span()),
556 }),
557 }
558 } else {
559 Ok(lhs)
560 }
561 }
562
563 fn short_circuit_or(&mut self) -> Result<Expr> {
564 self.binary(&[operator![||]], Self::short_circuit_and)
565 }
566
567 fn short_circuit_and(&mut self) -> Result<Expr> {
568 self.binary(&[operator![&&]], Self::inclusive_or)
569 }
570
571 fn inclusive_or(&mut self) -> Result<Expr> {
572 self.binary(&[operator![|]], Self::exclusive_or)
573 }
574
575 fn exclusive_or(&mut self) -> Result<Expr> {
576 self.binary(&[operator![^]], Self::and)
577 }
578
579 fn and(&mut self) -> Result<Expr> {
580 self.binary(&[operator![&]], Self::equality)
581 }
582
583 fn equality(&mut self) -> Result<Expr> {
584 self.binary(&[operator![==], operator![!=]], Self::relational)
585 }
586
587 fn relational(&mut self) -> Result<Expr> {
588 self.binary(
589 &[operator![<=], operator![>=], operator![<], operator![>]],
590 Self::shift,
591 )
592 }
593
594 fn shift(&mut self) -> Result<Expr> {
595 self.binary(&[operator![<<], operator![>>]], Self::additive)
596 }
597
598 fn additive(&mut self) -> Result<Expr> {
599 self.binary(&[operator!["+"], operator!["-"]], Self::multiplicative)
600 }
601
602 fn multiplicative(&mut self) -> Result<Expr> {
603 self.binary(&[operator![*], operator![/], operator![%]], Self::unary)
604 }
605
606 fn unary(&mut self) -> Result<Expr> {
607 if matches!(
608 self.peek().map(|t| t.as_matchable()),
609 Some((TokenKind::Operator, "-" | "!" | "~" | "*" | "&", _))
610 ) {
611 let op = self.next().unwrap();
612 let expr = self.unary()?;
613
614 Ok(Expr::UnaryPre(UnaryPreExpr {
615 op,
616 expr: Arc::new(expr),
617 }))
618 } else {
619 let primary = Expr::Primary(self.parse::<PrimaryExprBuilder>()?.build());
620
621 if let Some((TokenKind::Operator, "++" | "--", _)) =
622 self.peek().map(|t| t.as_matchable())
623 {
624 let op = self.next().unwrap();
625
626 Ok(Expr::UnaryPost(UnaryPostExpr {
627 expr: Arc::new(primary),
628 op,
629 }))
630 } else {
631 Ok(primary)
632 }
633 }
634 }
635
636 fn binary(
637 &mut self,
638 operators: &[Self::Token],
639 operand_method: fn(&mut Self) -> Result<Expr>,
640 ) -> Result<Expr> {
641 let mut expr = operand_method(self)?;
642
643 while operators.iter().any(|op| self.check(op.clone())) {
644 let op = self.next().unwrap();
645 let rhs = operand_method(self)?;
646
647 expr = Expr::Binary(BinaryExpr {
648 lhs: Arc::new(expr),
649 op,
650 rhs: Arc::new(rhs),
651 });
652 }
653
654 Ok(expr)
655 }
656}