1use crate::ast::*;
6use crate::error::{Error, ErrorKind};
7use crate::lexer::Token;
8use logos::{Lexer, Logos};
9
10struct Parser<'source> {
14 lexer: Lexer<'source, Token>,
15 tdark: bool,
16}
17
18impl<'source> Parser<'source> {
19 fn new(source: &'source str) -> Self {
21 Self {
22 lexer: Token::lexer(source),
23 tdark: false,
24 }
25 }
26
27 fn parse(&mut self) -> Result<Block, Error> {
31 let mut ast = vec![];
32 while let Some(token) = self.lexer.next() {
33 match token {
34 Ok(Token::TDark) => ast.extend(self.tdark_flow()?),
36 Ok(token) => ast.push(self.parse_stmt(token)?),
37
38 Err(()) => return Err(Error::new(ErrorKind::InvalidToken, self.lexer.span())),
40 }
41 }
42 Ok(ast)
43 }
44
45 fn checked_next(&mut self) -> Result<Token, Error> {
49 match self.lexer.next() {
50 Some(Ok(t)) => Ok(t),
51 Some(Err(())) => Err(Error::new(ErrorKind::InvalidToken, self.lexer.span())),
52 None => Err(Error::unexpected_eoi(self.lexer.span().start)),
53 }
54 }
55
56 fn parse_stmt(&mut self, token: Token) -> Result<Spanned<Stmt>, Error> {
61 let start = self.lexer.span().start;
62
63 match token {
64 Token::Unless => self.unless_flow(),
65 Token::Functio => self.functio_flow(),
66 Token::Bff => self.bff_flow(),
67 Token::Melo => self.melo_flow(),
68 Token::Loop => self.get_block().map(|body| Stmt::Loop { body }),
69 Token::Enough => self.semicolon_terminated(Stmt::Enough),
70 Token::AndAgain => self.semicolon_terminated(Stmt::AndAgain),
71 Token::Finally => self.get_block().map(Stmt::Finally),
72 Token::Rlyeh => self.semicolon_terminated(Stmt::Rlyeh),
73 Token::Rickroll => self.semicolon_terminated(Stmt::Rickroll),
74
75 Token::Identifier(_)
76 | Token::String(_)
77 | Token::Integer(_)
78 | Token::Char(_)
79 | Token::Aint
80 | Token::LeftBracket
81 | Token::LeftParen => self.value_flow(token),
82
83 t => Err(Error {
84 kind: ErrorKind::UnexpectedToken(t),
85 span: start..self.lexer.span().end,
86 }),
87 }
88 .map(|stmt| Spanned::new(stmt, start..self.lexer.span().end))
89 }
90
91 fn semicolon_terminated(&mut self, stmt_kind: Stmt) -> Result<Stmt, Error> {
95 self.require(Token::Semicolon)?;
96 Ok(stmt_kind)
97 }
98
99 fn require(&mut self, required: Token) -> Result<(), Error> {
101 match self.checked_next()? {
102 t if t == required => Ok(()),
103 t => Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
104 }
105 }
106
107 fn get_ident(&mut self) -> Result<Spanned<String>, Error> {
109 match self.checked_next()? {
110 Token::Identifier(ident) => {
111 Ok(Spanned::new(self.tdark_subst(ident), self.lexer.span()))
112 }
113 t => Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
114 }
115 }
116
117 fn parse_expr(
123 &mut self,
124 token: Token,
125 buf: &mut Option<Spanned<Expr>>,
126 ) -> Result<Spanned<Expr>, Error> {
127 let start = match buf {
128 Some(e) => e.span.start,
129 None => self.lexer.span().start,
130 };
131
132 match token {
133 Token::Identifier(i) => Ok(Expr::Variable(self.tdark_subst(i))),
135 Token::Integer(i) => Ok(Expr::Literal(Literal::Int(i))),
136 Token::String(s) => Ok(Expr::Literal(Literal::Str(self.tdark_subst(s)))),
137 Token::Char(c) => Ok(Expr::Literal(Literal::Char(c))),
138 Token::LeftBracket => match buf.take() {
139 Some(buf) => self.index_flow(buf),
140 None => self.cart_flow(),
141 },
142
143 Token::Aint if buf.is_none() => {
145 let next = self.checked_next()?;
146 Ok(Expr::Aint(Box::new(self.parse_expr(next, buf)?)))
147 }
148
149 Token::Plus
150 | Token::Minus
151 | Token::Star
152 | Token::FwdSlash
153 | Token::Equals
154 | Token::LessThan
155 | Token::GreaterThan
156 | Token::Aint => self.binop_flow(
157 BinOpKind::from_token(token).map_err(|e| Error::new(e, self.lexer.span()))?,
158 buf,
159 ),
160
161 Token::LeftParen => return self.expr_flow(Token::RightParen),
162 t => Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
163 }
164 .map(|expr| Spanned::new(expr, start..self.lexer.span().end))
165 }
166
167 fn cart_flow(&mut self) -> Result<Expr, Error> {
169 let mut cart = vec![];
170 let mut buf = None;
171
172 match self.checked_next()? {
173 Token::RightBracket => (),
174 t => {
175 buf = Some(self.parse_expr(t, &mut buf)?);
176 'cart: loop {
177 let value = loop {
178 match self.checked_next()? {
179 Token::Arrow => break buf.take(),
180 t => buf = Some(self.parse_expr(t, &mut buf)?),
181 }
182 }
183 .ok_or_else(|| {
184 Error::new(ErrorKind::UnexpectedToken(Token::Arrow), self.lexer.span())
185 })?;
186
187 let key = loop {
188 match self.checked_next()? {
189 Token::RightBracket => {
190 cart.push((
191 value,
192 buf.take().ok_or_else(|| {
193 Error::unexpected_eoi(self.lexer.span().start)
194 })?,
195 ));
196
197 break 'cart;
198 }
199 Token::Comma => break buf.take(),
200 t => buf = Some(self.parse_expr(t, &mut buf)?),
201 }
202 }
203 .ok_or_else(|| Error::unexpected_eoi(self.lexer.span().start))?;
204
205 cart.push((value, key));
206 }
207 }
208 }
209
210 Ok(Expr::Cart(cart))
211 }
212
213 fn index_flow(&mut self, expr: Spanned<Expr>) -> Result<Expr, Error> {
217 let mut buf = None;
218 Ok(loop {
219 match self.checked_next()? {
220 Token::RightBracket => match buf {
221 Some(index) => {
222 break Expr::Index {
223 expr: Box::new(expr),
224 index: Box::new(index),
225 }
226 }
227 None => break Expr::Len(Box::new(expr)),
228 },
229 Token::GreaterThan if buf.is_none() => {
230 self.require(Token::RightBracket)?;
231 break Expr::Keys(Box::new(expr));
232 }
233 token => buf = Some(self.parse_expr(token, &mut buf)?),
234 }
235 })
236 }
237
238 fn binop_flow(
244 &mut self,
245 kind: BinOpKind,
246 lhs: &mut Option<Spanned<Expr>>,
247 ) -> Result<Expr, Error> {
248 Ok(Expr::BinOp {
249 lhs: Box::new(
250 lhs.take()
251 .ok_or_else(|| Error::new(ErrorKind::MissingLhs, self.lexer.span()))?,
252 ),
253 rhs: {
254 let next = self.checked_next()?;
255 Box::new(self.parse_expr(next, &mut None)?)
256 },
257 kind,
258 })
259 }
260
261 fn expr_flow(&mut self, terminate: Token) -> Result<Spanned<Expr>, Error> {
263 let mut buf = None;
264 Ok(loop {
265 match self.checked_next()? {
266 t if t == terminate => {
267 break buf.take().ok_or_else(|| {
268 Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())
269 })?
270 }
271 t => buf = Some(self.parse_expr(t, &mut buf)?),
272 }
273 })
274 }
275
276 fn get_block(&mut self) -> Result<Block, Error> {
278 self.require(Token::LeftCurly)?;
279 let mut block = vec![];
280
281 loop {
282 match self.checked_next()? {
283 Token::RightCurly => break,
284 Token::TDark => block.extend(self.tdark_flow()?),
285 t => block.push(self.parse_stmt(t)?),
286 }
287 }
288 Ok(block)
289 }
290
291 fn tdark_flow(&mut self) -> Result<Block, Error> {
293 self.tdark = true;
294 let block = self.get_block();
295 self.tdark = false;
296 block
297 }
298
299 fn value_flow(&mut self, init: Token) -> Result<Stmt, Error> {
303 let mut buf = Some(self.parse_expr(init, &mut None)?);
304 Ok(loop {
305 match self.checked_next()? {
306 Token::Print => {
308 break Stmt::Print {
309 expr: buf.take().ok_or_else(|| {
310 Error::new(ErrorKind::UnexpectedToken(Token::Print), self.lexer.span())
311 })?,
312 newline: match self.checked_next()? {
313 Token::Semicolon => true,
314 Token::Minus => {
315 self.require(Token::Semicolon)?;
316 false
317 }
318 token => {
319 return Err(Error::new(
320 ErrorKind::UnexpectedToken(token),
321 self.lexer.span(),
322 ));
323 }
324 },
325 };
326 }
327
328 Token::LeftParen => {
330 break self.functio_call_flow(buf.take().ok_or_else(|| {
331 Error::new(
332 ErrorKind::UnexpectedToken(Token::LeftParen),
333 self.lexer.span(),
334 )
335 })?)?;
336 }
337
338 Token::Dim => {
340 return match buf.take() {
341 Some(Spanned {
342 item: Expr::Variable(ident),
343 span,
344 }) => Ok(Stmt::Dim {
345 ident: Spanned::new(ident, span),
346 init: {
347 let mut init = None;
348 loop {
349 match self.checked_next()? {
350 Token::Semicolon => break init,
351 token => init = Some(self.parse_expr(token, &mut init)?),
352 }
353 }
354 },
355 }),
356 _ => Err(Error::new(
357 ErrorKind::UnexpectedToken(Token::Dim),
358 self.lexer.span(),
359 )),
360 }
361 }
362
363 Token::Assign => {
365 return match buf.take() {
366 Some(expr) => self.assignment_flow(expr),
367 None => Err(Error::new(
368 ErrorKind::UnexpectedToken(Token::Assign),
369 self.lexer.span(),
370 )),
371 }
372 }
373
374 Token::Read => {
376 if let Some(Ok(assignable)) = buf.take().map(Assignable::from_expr) {
377 self.require(Token::Semicolon)?;
378 break Stmt::Read(assignable);
379 } else {
380 return Err(Error::new(
381 ErrorKind::UnexpectedToken(Token::Read),
382 self.lexer.span(),
383 ));
384 }
385 }
386
387 t => buf = Some(self.parse_expr(t, &mut buf)?),
388 }
389 })
390 }
391
392 fn unless_flow(&mut self) -> Result<Stmt, Error> {
396 self.require(Token::LeftParen)?;
397 Ok(Stmt::Unless {
398 cond: self.expr_flow(Token::RightParen)?,
399 body: self.get_block()?,
400 })
401 }
402
403 fn functio_flow(&mut self) -> Result<Stmt, Error> {
407 let ident = self.get_ident()?;
408 self.require(Token::LeftParen)?;
409
410 let mut params = vec![];
411 loop {
412 match self.checked_next()? {
413 Token::RightParen => break,
414 Token::Identifier(i) => {
415 params.push(Spanned::new(i, self.lexer.span()));
416
417 match self.checked_next()? {
419 Token::Comma => continue,
420 Token::RightParen => break,
421 t => {
422 return Err(Error::new(
423 ErrorKind::UnexpectedToken(t),
424 self.lexer.span(),
425 ))
426 }
427 }
428 }
429 t => return Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
430 }
431 }
432
433 let body = self.get_block()?;
434
435 Ok(Stmt::Functio {
436 ident,
437 params,
438 body,
439 })
440 }
441
442 fn bff_flow(&mut self) -> Result<Stmt, Error> {
446 let ident = self.get_ident()?;
447
448 let tape_len = match self.checked_next()? {
449 Token::LeftParen => {
450 let len = Some(self.expr_flow(Token::RightParen)?);
451 self.require(Token::LeftCurly)?;
452 len
453 }
454 Token::LeftCurly => None,
455 token => {
456 return Err(Error::new(
457 ErrorKind::UnexpectedToken(token),
458 self.lexer.span(),
459 ))
460 }
461 };
462
463 let mut code: Vec<u8> = vec![];
464 loop {
465 match self.lexer.next() {
466 Some(Ok(Token::RightCurly)) => break,
467 Some(_) => code.push(self.lexer.slice().as_bytes()[0]),
468 None => return Err(Error::unexpected_eoi(self.lexer.span().start)),
469 }
470 }
471
472 Ok(Stmt::BfFunctio {
473 ident,
474 tape_len,
475 code,
476 })
477 }
478
479 fn functio_call_flow(&mut self, expr: Spanned<Expr>) -> Result<Stmt, Error> {
481 let mut args = vec![];
482 let mut buf = None;
483 loop {
484 match self.checked_next()? {
485 Token::RightParen => {
487 if let Some(expr) = buf.take() {
488 args.push(expr)
489 }
490 break;
491 }
492
493 Token::Comma => match buf.take() {
495 Some(expr) => args.push(expr),
496 None => {
498 return Err(Error::new(
499 ErrorKind::UnexpectedToken(Token::Comma),
500 self.lexer.span(),
501 ))
502 }
503 },
504 t => buf = Some(self.parse_expr(t, &mut buf)?),
505 }
506 }
507
508 self.require(Token::Semicolon)?;
509 Ok(Stmt::Call { expr, args })
510 }
511
512 fn assignment_flow(&mut self, value: Spanned<Expr>) -> Result<Stmt, Error> {
514 let ident = self.get_ident()?;
515 let kind = match self.checked_next()? {
516 Token::Semicolon => AssignableKind::Variable,
517 Token::LeftBracket => {
518 let mut indices = vec![];
519 loop {
520 indices.push(self.expr_flow(Token::RightBracket)?);
521 match self.checked_next()? {
522 Token::Semicolon => break AssignableKind::Index { indices },
523 Token::LeftBracket => (),
524 t => {
525 return Err(Error::new(
526 ErrorKind::UnexpectedToken(t),
527 self.lexer.span(),
528 ))
529 }
530 }
531 }
532 }
533 t => return Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
534 };
535
536 Ok(Stmt::Assign {
537 assignable: Assignable { ident, kind },
538 value,
539 })
540 }
541
542 fn melo_flow(&mut self) -> Result<Stmt, Error> {
544 let ident = self.get_ident()?;
545 self.semicolon_terminated(Stmt::Melo(ident))
546 }
547
548 fn tdark_subst(&self, mut string: String) -> String {
550 if self.tdark {
551 if let Some(pos) = string.to_lowercase().find("lang") {
552 let range = pos..pos + 4;
553 let mut count_upper = 0_u8;
554 string.replace_range(
555 range.clone(),
556 &(string[range]
557 .chars()
558 .zip("scri".chars())
559 .map(|(lc, sc)| {
560 if lc.is_uppercase() {
561 count_upper += 1;
562 sc.to_ascii_uppercase()
563 } else {
564 sc.to_ascii_lowercase()
565 }
566 })
567 .collect::<String>()
568 + match count_upper {
569 0 | 1 => "pt",
570 2 if rand::random() => "Pt",
571 2 => "pT",
572 _ => "PT",
573 }),
574 )
575 }
576 }
577
578 string
579 }
580}
581
582pub fn parse(source: &str) -> Result<Block, Error> {
584 Parser::new(source).parse()
585}
586
587#[cfg(test)]
588mod tests {
589 use super::*;
590
591 #[test]
592 fn simple_math() {
593 let code = "1 * (num + 3) / 666 print;";
594 let expected = &[Spanned {
595 item: Stmt::Print {
596 expr: Spanned {
597 item: Expr::BinOp {
598 lhs: Box::new(Spanned {
599 item: Expr::BinOp {
600 lhs: Box::new(Spanned {
601 item: Expr::Literal(Literal::Int(1)),
602 span: 0..1,
603 }),
604 rhs: Box::new(Spanned {
605 item: Expr::BinOp {
606 lhs: Box::new(Spanned {
607 item: Expr::Variable("num".to_owned()),
608 span: 5..6,
609 }),
610 rhs: Box::new(Spanned {
611 item: Expr::Literal(Literal::Int(3)),
612 span: 9..10,
613 }),
614 kind: BinOpKind::Add,
615 },
616 span: 5..10,
617 }),
618 kind: BinOpKind::Multiply,
619 },
620 span: 0..11,
621 }),
622 rhs: Box::new(Spanned {
623 item: Expr::Literal(Literal::Int(666)),
624 span: 14..17,
625 }),
626 kind: BinOpKind::Divide,
627 },
628 span: 0..17,
629 },
630 newline: true,
631 },
632 span: 0..24,
633 }];
634
635 let ast = Parser::new(code).parse().unwrap();
636 assert_eq!(ast, expected);
637 }
638
639 #[test]
640 fn variable_declaration() {
641 let code = "var dim 42;";
642 let expected = &[Spanned {
643 item: Stmt::Dim {
644 ident: Spanned {
645 item: "var".to_owned(),
646 span: 0..3,
647 },
648 init: Some(Spanned {
649 item: Expr::Literal(Literal::Int(42)),
650 span: 4..6,
651 }),
652 },
653 span: 0..11,
654 }];
655
656 let ast = Parser::new(code).parse().unwrap();
657 assert_eq!(ast, expected);
658 }
659
660 #[test]
661 fn unless_flow() {
662 let code = "unless (never + never) { /*Buy Able products!*/ print; }";
663 let expected = &[Spanned {
664 item: Stmt::Unless {
665 cond: Spanned {
666 item: Expr::BinOp {
667 lhs: Box::new(Spanned {
668 item: Expr::Variable("never".to_owned()),
669 span: 8..13,
670 }),
671 rhs: Box::new(Spanned {
672 item: Expr::Variable("never".to_owned()),
673 span: 16..21,
674 }),
675 kind: BinOpKind::Add,
676 },
677 span: 8..21,
678 },
679 body: vec![Spanned {
680 item: Stmt::Print {
681 expr: Spanned {
682 item: Expr::Literal(Literal::Str("Buy Able products!".to_owned())),
683 span: 25..47,
684 },
685 newline: true,
686 },
687 span: 25..54,
688 }],
689 },
690 span: 0..56,
691 }];
692
693 let ast = Parser::new(code).parse().unwrap();
694 assert_eq!(ast, expected);
695 }
696
697 #[test]
698 fn tdark() {
699 let code = "T-Dark { lang dim /*lang*/ + lang; }";
700 let expected = &[Spanned {
701 item: Stmt::Dim {
702 ident: Spanned {
703 item: "script".to_owned(),
704 span: 9..15,
705 },
706 init: Some(Spanned {
707 item: Expr::BinOp {
708 lhs: Box::new(Spanned {
709 item: Expr::Literal(Literal::Str("script".to_owned())),
710 span: 20..26,
711 }),
712 rhs: Box::new(Spanned {
713 item: Expr::Variable("script".to_owned()),
714 span: 29..33,
715 }),
716 kind: BinOpKind::Add,
717 },
718 span: 20..33,
719 }),
720 },
721 span: 9..34,
722 }];
723
724 let ast = Parser::new(code).parse().unwrap();
725 assert_eq!(ast, expected);
726 }
727
728 #[test]
729 fn cart_construction() {
730 let code = "[/*able*/ <= 1, /*script*/ <= 3 - 1] print;";
731 let expected = &[Spanned {
732 item: Stmt::Print {
733 expr: Spanned {
734 item: Expr::Cart(vec![
735 (
736 Spanned {
737 item: Expr::Literal(Literal::Str("able".to_owned())),
738 span: 1..7,
739 },
740 Spanned {
741 item: Expr::Literal(Literal::Int(1)),
742 span: 11..12,
743 },
744 ),
745 (
746 Spanned {
747 item: Expr::Literal(Literal::Str("script".to_owned())),
748 span: 14..22,
749 },
750 Spanned {
751 item: Expr::BinOp {
752 kind: BinOpKind::Subtract,
753 lhs: Box::new(Spanned {
754 item: Expr::Literal(Literal::Int(3)),
755 span: 26..27,
756 }),
757 rhs: Box::new(Spanned {
758 item: Expr::Literal(Literal::Int(1)),
759 span: 30..31,
760 }),
761 },
762 span: 26..31,
763 },
764 ),
765 ]),
766 span: 0..32,
767 },
768 newline: true,
769 },
770 span: 0..39,
771 }];
772
773 let ast = Parser::new(code).parse().unwrap();
774 assert_eq!(ast, expected);
775 }
776
777 #[test]
778 fn cart_index() {
779 let code = "[/*able*/ <= /*ablecorp*/][/*ablecorp*/] print;";
780 let expected = &[Spanned {
781 item: Stmt::Print {
782 expr: Spanned {
783 item: Expr::Index {
784 expr: Box::new(Spanned {
785 item: Expr::Cart(vec![(
786 Spanned {
787 item: Expr::Literal(Literal::Str("able".to_owned())),
788 span: 1..7,
789 },
790 Spanned {
791 item: Expr::Literal(Literal::Str("ablecorp".to_owned())),
792 span: 11..21,
793 },
794 )]),
795 span: 0..22,
796 }),
797 index: Box::new(Spanned {
798 item: Expr::Literal(Literal::Str("ablecorp".to_owned())),
799 span: 23..33,
800 }),
801 },
802 span: 0..34,
803 },
804 newline: true,
805 },
806 span: 0..41,
807 }];
808
809 let ast = Parser::new(code).parse().unwrap();
810 assert_eq!(ast, expected);
811 }
812}