1use super::{PResult, PResultExt, Parse, ParseError, Parser, no_eof, pat::Prec as PPrec};
2use cl_ast::{types::Literal, *};
3use cl_token::{TKind, Token};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
7pub enum Prec {
8 Min,
9 Do,
11 Assign,
13 Tuple,
15 Body,
17 Make,
19 Logical,
21 LogOr,
23 LogAnd,
25 Compare,
27 Range,
29 Binary,
31 Shift,
33 Factor,
35 Term,
37 Unary,
39 Project,
41 Extend,
43 Max,
44}
45
46impl Prec {
47 pub const MIN: usize = Prec::Min.value();
48
49 pub const fn value(self) -> usize {
50 self as usize * 2
51 }
52
53 pub const fn prev(self) -> usize {
54 match self {
55 Self::Assign => self.value() + 1,
56 _ => self.value(),
57 }
58 }
59
60 pub const fn next(self) -> usize {
61 match self {
62 Self::Assign => self.value(),
63 _ => self.value() + 1,
64 }
65 }
66}
67
68#[derive(Clone, Copy, Debug, PartialEq, Eq)]
70pub enum Ps {
71 Id, Mid, Lit, Use, Def, DocInner, DocOuter, For, Lambda0, Lambda, DoubleRef, Make, Match, ImplicitDo, Ellipsis, End, Op(Op), }
89
90fn from_prefix(token: &Token) -> PResult<(Ps, Prec)> {
93 Ok(match token.kind {
94 TKind::OutDoc => (Ps::DocOuter, Prec::Max),
95 TKind::InDoc => (Ps::DocInner, Prec::Max),
96 TKind::Do => (Ps::Op(Op::Do), Prec::Do),
97 TKind::Semi => (Ps::End, Prec::Body),
98
99 TKind::Identifier | TKind::ColonColon => (Ps::Id, Prec::Max),
100 TKind::Dollar => (Ps::Mid, Prec::Max),
101 TKind::True | TKind::False | TKind::Character | TKind::Integer | TKind::String => {
102 (Ps::Lit, Prec::Max)
103 }
104 TKind::Use => (Ps::Use, Prec::Max),
105
106 TKind::Pub => (Ps::Op(Op::Pub), Prec::Max),
107 TKind::Const => (Ps::Op(Op::Const), Prec::Max),
108 TKind::Static => (Ps::Op(Op::Static), Prec::Max),
109 TKind::For => (Ps::For, Prec::Max),
110 TKind::Match => (Ps::Match, Prec::Max),
111 TKind::Macro => (Ps::Op(Op::Macro), Prec::Assign),
112
113 TKind::Fn
114 | TKind::Mod
115 | TKind::Impl
116 | TKind::Let
117 | TKind::Type
118 | TKind::Struct
119 | TKind::Enum => (Ps::Def, Prec::Max),
120
121 TKind::Loop => (Ps::Op(Op::Loop), Prec::Body),
122 TKind::If => (Ps::Op(Op::If), Prec::Body),
123 TKind::While => (Ps::Op(Op::While), Prec::Body),
124 TKind::Break => (Ps::Op(Op::Break), Prec::Body),
125 TKind::Return => (Ps::Op(Op::Return), Prec::Body),
126 TKind::Continue => (Ps::Op(Op::Continue), Prec::Max),
127
128 TKind::LCurly => (Ps::Op(Op::Block), Prec::Min),
129 TKind::RCurly => (Ps::End, Prec::Do),
130 TKind::LBrack => (Ps::Op(Op::Array), Prec::Tuple),
131 TKind::RBrack => (Ps::End, Prec::Tuple),
132 TKind::LParen => (Ps::Op(Op::Group), Prec::Min),
133 TKind::RParen => (Ps::End, Prec::Tuple),
134 TKind::Amp => (Ps::Op(Op::Refer), Prec::Unary),
135 TKind::AmpAmp => (Ps::DoubleRef, Prec::Unary),
136 TKind::Bang => (Ps::Op(Op::Not), Prec::Unary),
137 TKind::BangBang => (Ps::Op(Op::Identity), Prec::Unary),
138 TKind::Bar => (Ps::Lambda, Prec::Body),
139 TKind::BarBar => (Ps::Lambda0, Prec::Body),
140 TKind::DotDot => (Ps::Op(Op::RangeEx), Prec::Range),
141 TKind::DotDotDot => (Ps::Ellipsis, Prec::Max),
142 TKind::DotDotEq => (Ps::Op(Op::RangeIn), Prec::Range),
143 TKind::Minus => (Ps::Op(Op::Neg), Prec::Unary),
144 TKind::Plus => (Ps::Op(Op::Identity), Prec::Unary),
145 TKind::Star => (Ps::Op(Op::Deref), Prec::Unary),
146 TKind::Hash => (Ps::Op(Op::MetaOuter), Prec::Max),
147 TKind::HashBang => (Ps::Op(Op::MetaInner), Prec::Max),
148
149 kind => Err(ParseError::NotPrefix(kind, token.span))?,
150 })
151}
152
153const fn from_infix(token: &Token) -> PResult<(Ps, Prec)> {
156 Ok(match token.kind {
157 TKind::Semi => (Ps::Op(Op::Do), Prec::Do), TKind::In => (Ps::Op(Op::Do), Prec::Do),
159
160 TKind::Eq => (Ps::Op(Op::Set), Prec::Assign),
161 TKind::StarEq => (Ps::Op(Op::MulSet), Prec::Assign),
162 TKind::SlashEq => (Ps::Op(Op::DivSet), Prec::Assign),
163 TKind::RemEq => (Ps::Op(Op::RemSet), Prec::Assign),
164 TKind::PlusEq => (Ps::Op(Op::AddSet), Prec::Assign),
165 TKind::MinusEq => (Ps::Op(Op::SubSet), Prec::Assign),
166 TKind::LtLtEq => (Ps::Op(Op::ShlSet), Prec::Assign),
167 TKind::GtGtEq => (Ps::Op(Op::ShrSet), Prec::Assign),
168 TKind::AmpEq => (Ps::Op(Op::AndSet), Prec::Assign),
169 TKind::XorEq => (Ps::Op(Op::XorSet), Prec::Assign),
170 TKind::BarEq => (Ps::Op(Op::OrSet), Prec::Assign),
171 TKind::Comma => (Ps::Op(Op::Tuple), Prec::Tuple),
172 TKind::LCurly => (Ps::Make, Prec::Make),
173 TKind::XorXor => (Ps::Op(Op::LogXor), Prec::Logical),
174 TKind::BarBar => (Ps::Op(Op::LogOr), Prec::LogOr),
175 TKind::AmpAmp => (Ps::Op(Op::LogAnd), Prec::LogAnd),
176 TKind::Lt => (Ps::Op(Op::Lt), Prec::Compare),
177 TKind::LtEq => (Ps::Op(Op::Leq), Prec::Compare),
178 TKind::EqEq => (Ps::Op(Op::Eq), Prec::Compare),
179 TKind::BangEq => (Ps::Op(Op::Neq), Prec::Compare),
180 TKind::GtEq => (Ps::Op(Op::Geq), Prec::Compare),
181 TKind::Gt => (Ps::Op(Op::Gt), Prec::Compare),
182 TKind::DotDot => (Ps::Op(Op::RangeEx), Prec::Range),
183 TKind::DotDotEq => (Ps::Op(Op::RangeIn), Prec::Range),
184 TKind::Amp => (Ps::Op(Op::And), Prec::Binary),
185 TKind::Xor => (Ps::Op(Op::Xor), Prec::Binary),
186 TKind::Bar => (Ps::Op(Op::Or), Prec::Binary),
187 TKind::LtLt => (Ps::Op(Op::Shl), Prec::Shift),
188 TKind::GtGt => (Ps::Op(Op::Shr), Prec::Shift),
189 TKind::Plus => (Ps::Op(Op::Add), Prec::Factor),
190 TKind::Minus => (Ps::Op(Op::Sub), Prec::Factor),
191 TKind::Star => (Ps::Op(Op::Mul), Prec::Term),
192 TKind::Slash => (Ps::Op(Op::Div), Prec::Term),
193 TKind::Rem => (Ps::Op(Op::Rem), Prec::Term),
194
195 TKind::Question => (Ps::Op(Op::Try), Prec::Unary),
196 TKind::Dot => (Ps::Op(Op::Dot), Prec::Project),
197 TKind::LBrack => (Ps::Op(Op::Index), Prec::Project),
198 TKind::LParen => (Ps::Op(Op::Call), Prec::Extend),
199
200 TKind::RParen | TKind::RBrack | TKind::RCurly => (Ps::End, Prec::Max),
201 TKind::As => (Ps::Op(Op::As), Prec::Project),
202 _ => (Ps::ImplicitDo, Prec::Do),
203 })
204}
205
206impl<'t> Parse<'t> for Expr {
207 type Prec = usize;
208
209 fn parse(p: &mut Parser<'t>, level: usize) -> PResult<Self> {
213 const MIN: usize = Prec::MIN;
214
215 let tok @ &Token { kind, span, .. } = p.peek()?;
217 let (op, prec) = from_prefix(tok)?;
218 no_eof(move || {
219 let mut head = match op {
220 Ps::End if (prec.value()..=prec.next()).contains(&level) => Expr::Omitted,
225 Ps::End => Err(ParseError::NotPrefix(kind, span))?,
226
227 Ps::Id => Expr::Id(p.parse(())?),
228 Ps::Mid => Expr::MetId(p.consume().next()?.lexeme.to_string().as_str().into()),
229 Ps::Lit => Expr::Lit(p.parse(())?),
230 Ps::Use => Expr::Use(p.consume().parse(())?),
231 Ps::Def => Expr::Bind(p.parse(())?),
232 Ps::For => parse_for(p, ())?,
233 Ps::Match => Expr::Match(p.parse(())?),
234 Ps::Lambda | Ps::Lambda0 => {
235 p.consume();
236
237 let args = if kind == TKind::Bar {
238 p.opt(PPrec::Tuple, TKind::Bar)?
239 .map(Pat::to_tuple)
240 .unwrap_or(Pat::Op(PatOp::Tuple, vec![]))
241 } else {
242 Pat::Op(PatOp::Tuple, vec![])
243 };
244
245 let rety = p.opt_if(PPrec::Max, TKind::Arrow)?.unwrap_or(Pat::Ignore);
246
247 Expr::Bind(Box::new(Bind(
248 BindOp::Fn,
249 vec![],
250 Pat::Op(PatOp::Fn, vec![args, rety]),
251 vec![p.parse(Prec::Body.next())?],
252 )))
253 }
254 Ps::DocOuter | Ps::DocInner => {
255 let comment = Literal::Str(p.take_lexeme()?.string().unwrap());
256 let comment = Expr::Lit(comment).at(span);
257 let next = p.parse(prec.next())?;
258 Expr::Op(
259 match op {
260 Ps::DocOuter => Op::MetaOuter,
261 _ => Op::MetaInner,
262 },
263 vec![comment, next],
264 )
265 }
266 Ps::Ellipsis => p.consume().then(Expr::Omitted),
267 Ps::Op(op @ (Op::MetaOuter | Op::MetaInner)) => Expr::Op(
268 op,
269 vec![
270 p.consume()
271 .expect(TKind::LBrack)?
272 .opt(MIN, TKind::RBrack)?
273 .unwrap_or_else(|| Expr::Op(Op::Tuple, vec![]).at(span)),
274 p.parse(prec.next())?,
275 ],
276 ),
277 Ps::Op(Op::Block) => Expr::Op(
278 Op::Block,
279 p.consume().opt(MIN, kind.flip())?.into_iter().collect(),
280 ),
281 Ps::Op(Op::Array) => parse_array(p)?,
282 Ps::Op(Op::Group) => match p.consume().opt(MIN, kind.flip())? {
283 Some(value) => Expr::Op(Op::Group, vec![value]),
284 None => Expr::Op(Op::Tuple, vec![]),
285 },
286 Ps::Op(Op::Continue) => p.consume().then(Expr::Op(Op::Continue, vec![])),
287 Ps::Op(op @ (Op::If | Op::While)) => {
288 p.consume();
289 let exprs = vec![
290 p.parse(Prec::Logical.value())?,
292 p.parse(prec.next())?,
293 match p.peek() {
294 Ok(Token { kind: TKind::Else, .. }) => {
295 p.consume().parse(prec.next())?
296 }
297 _ => Expr::Op(Op::Tuple, vec![]).at(span.merge(p.span())),
298 },
299 ];
300 Expr::Op(op, exprs)
301 }
302 Ps::DoubleRef => p.consume().parse(prec.next()).map(|At(expr, span)| {
303 Expr::Op(
304 Op::Refer,
305 vec![At(Expr::Op(Op::Refer, vec![At(expr, span)]), span)],
306 )
307 })?,
308
309 Ps::Op(op) => Expr::Op(op, vec![p.consume().parse(prec.next())?]),
310 _ => unimplemented!("prefix {op:?}"),
311 };
312
313 while let Ok(Some(tok @ &Token { kind, .. })) = p.peek().allow_eof()
315 && let Ok((op, prec)) = from_infix(tok)
316 && level <= prec.prev()
317 && op != Ps::End
318 {
319 let span = span.merge(p.span());
320
321 head = match op {
322 Ps::Make => match &head {
324 Expr::Id(_) | Expr::MetId(_) => Expr::Make(Box::new(Make(
325 head.at(span),
326 p.consume().list(vec![], (), TKind::Comma, TKind::RCurly)?,
327 ))),
328 _ => break,
329 },
330 Ps::ImplicitDo if p.elide_do => head.and_do(span, p.parse(prec.next())?),
332 Ps::ImplicitDo => break,
333 Ps::Op(Op::Do) => head.and_do(
335 span,
336 match p.consume().peek().allow_eof()? {
337 Some(_) => p.parse(prec.next())?,
338 None => At(Expr::Omitted, span),
339 },
340 ),
341 Ps::Op(Op::Index) => Expr::Op(
342 Op::Index,
343 p.consume()
344 .list(vec![head.at(span)], 0, TKind::Comma, TKind::RBrack)?,
345 ),
346 Ps::Op(Op::Call) => {
347 let head = head.at(span);
348 let args = match p.consume().opt::<At<Expr>>(0, TKind::RParen)? {
349 None => Expr::Op(Op::Tuple, vec![]).at(span),
350 Some(At(expr, span)) => expr.to_tuple(span).at(span),
351 };
352 Expr::Op(Op::Call, vec![head, args])
353 }
354 Ps::Op(op @ Op::Tuple) => Expr::Op(
355 op,
356 p.consume()
357 .list_bare(vec![head.at(span)], prec.next(), kind)?,
358 ),
359 Ps::Op(op @ Op::Try) => {
360 p.consume();
361 Expr::Op(op, vec![head.at(span)])
362 }
363 Ps::Op(op) => {
364 Expr::Op(op, vec![head.at(span), p.consume().parse(prec.next())?])
365 }
366 _ => Err(ParseError::NotInfix(kind, span))?,
367 }
368 }
369
370 Ok(head)
371 })
372 }
373}
374
375fn parse_array(p: &mut Parser<'_>) -> PResult<Expr> {
377 if p.consume().peek()?.kind == TKind::RBrack {
378 p.consume();
379 return Ok(Expr::Op(Op::Array, vec![]));
380 }
381
382 let prec = Prec::Tuple;
383 let item = p.parse(prec.value())?;
384 let repeat = p.opt_if(prec.next(), TKind::Semi)?;
385 p.expect(TKind::RBrack)?;
386
387 Ok(match (repeat, item) {
388 (Some(repeat), item) => Expr::Op(Op::ArRep, vec![item, repeat]),
389 (None, At(Expr::Op(Op::Tuple, items), _)) => Expr::Op(Op::Array, items),
390 (None, item) => Expr::Op(Op::Array, vec![item]),
391 })
392}
393
394impl<'t> Parse<'t> for Match {
402 type Prec = ();
403
404 fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self>
405 where Self: Sized {
406 Ok(Self(
407 p.consume().parse(Prec::Logical.value())?,
408 p.expect(TKind::LCurly)?
409 .list(vec![], (), TKind::Comma, TKind::RCurly)?,
410 ))
411 }
412}
413
414impl<'t> Parse<'t> for MatchArm {
415 type Prec = ();
416
417 fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self>
418 where Self: Sized {
419 let pat = p.parse(PPrec::Alt)?;
427 p.expect(TKind::FatArrow)?;
428 let body = p.parse(Prec::Body.value())?;
429
430 Ok(Self(pat, body))
431 }
432}
433
434fn parse_for(p: &mut Parser<'_>, _level: ()) -> PResult<Expr> {
436 let pat = p.consume().parse(PPrec::Tuple)?;
438 let iter: At<Expr> = p.expect(TKind::In)?.parse(Prec::Logical.next())?;
440 let pass: At<Expr> = p.parse(Prec::Body.next())?;
442 let pspan = pass.1;
443 let fail = match p.next_if(TKind::Else).allow_eof()? {
445 Some(Ok(_)) => p.parse(Prec::Body.next())?,
446 _ => Expr::Op(Op::Tuple, vec![]).at(pspan),
447 };
448 Ok(Expr::Bind(Box::new(Bind(
461 BindOp::For,
462 vec![],
463 pat,
464 vec![iter, pass, fail],
465 ))))
466}
467
468#[rustfmt::skip]
471#[allow(clippy::type_complexity)]
472fn from_bind(p: &mut Parser<'_>) -> PResult<(BindOp, PPrec, Option<TKind>, Option<Prec>, Option<Prec>)> {
473 let bk = match p.peek()?.kind {
474 TKind::Let => (BindOp::Let, PPrec::Tuple, Some(TKind::Eq), Some(Prec::Tuple), Some(Prec::Body)),
476 TKind::Type => (BindOp::Type, PPrec::Alt, Some(TKind::Eq), Some(Prec::Tuple), None),
477 TKind::Struct => (BindOp::Struct, PPrec::Tuple, None, None, None),
478 TKind::Enum => (BindOp::Enum, PPrec::Tuple, None, None, None),
479 TKind::Fn => (BindOp::Fn, PPrec::Fn, None, Some(Prec::Body), None),
480 TKind::Mod => (BindOp::Mod, PPrec::Max, None, Some(Prec::Body), None),
481 TKind::Impl => (BindOp::Impl, PPrec::Fn, None, Some(Prec::Body), None),
482 other => return Err(ParseError::NotBind(other, p.span()))
483 };
484
485 p.consume();
486 Ok(bk)
487}
488
489impl<'t> Parse<'t> for Bind {
490 type Prec = ();
491
492 fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
493 let (level, patp, arrow, bodyp, failp) = from_bind(p)?;
495
496 let generics = match p.next_if(TKind::Lt)? {
498 Ok(_) => p.list(vec![], (), TKind::Comma, TKind::Gt)?,
499 Err(_) => vec![],
500 };
501
502 let pat = p.parse(patp)?;
504
505 let Some(bodyp) = bodyp else {
506 return Ok(Self(level, generics, pat, vec![]));
507 };
508
509 if let Some(arrow) = arrow {
511 if p.next_if(arrow).allow_eof()?.is_none_or(|v| v.is_err()) {
512 return Ok(Self(level, generics, pat, vec![]));
513 }
514 } else {
515 p.next_if(TKind::Eq).allow_eof()?;
517 }
518
519 let body = p.parse(bodyp.value())?;
521
522 let Some(failp) = failp else {
523 return Ok(Self(level, generics, pat, vec![body]));
524 };
525
526 if p.next_if(TKind::Else)
528 .allow_eof()?
529 .is_none_or(|v| v.is_err())
530 {
531 return Ok(Self(level, generics, pat, vec![body]));
532 }
533
534 let fail = p.parse(failp.value())?;
535
536 Ok(Self(level, generics, pat, vec![body, fail]))
537 }
538}
539
540impl<'t> Parse<'t> for MakeArm {
541 type Prec = ();
542
543 fn parse(p: &mut Parser<'t>, _level: ()) -> PResult<Self> {
544 let name = p
545 .next_if(TKind::Identifier)?
546 .map_err(|tk| ParseError::Expected(TKind::Identifier, tk, p.span()))?;
547 Ok(MakeArm(
548 name.lexeme
549 .str()
550 .expect("Identifier should have String")
551 .into(),
552 p.opt_if(Prec::Body.value(), TKind::Colon)?,
553 ))
554 }
555}