1use crate::{
2 error::{ParseError, ParseErrorKind, ParseErrors, ParseErrorsFor},
3 expression::{Expression, ExpressionKind},
4 operator::Fixity,
5 token::{Token, Tokenizer},
6 Span,
7};
8
9const EXPECT_TERM: &str = "literal, variable, unary operator, or delimiter";
10const EXPECT_OPERATOR: &str = "binary operator, delimiter, postfix operator, or end of input";
11
12pub fn parse<T, P>(
13 mut tokenizer: T,
14 parser: P,
15) -> Result<ExpressionQueueFor<P, T>, ParseErrorsFor<P, T>>
16where
17 P: Parser<T::Token>,
18 T: Tokenizer,
19{
20 let mut state = ParseState::new(parser);
21 while let Some(token) = tokenizer.next_token() {
22 state.parse_result(token);
23 }
24 state.finish()
25}
26
27pub fn parse_one_term<T, P>(
32 mut tokenizer: T,
33 parser: P,
34) -> Result<ExpressionQueueFor<P, T>, ParseErrorsFor<P, T>>
35where
36 P: Parser<T::Token>,
37 T: Tokenizer,
38{
39 let mut state = ParseState::new(parser);
40 while let Some(token) = tokenizer.next_token() {
41 state.parse_result(token);
42 if state.has_parsed_expression() {
43 break;
44 }
45 }
46 state.finish()
47}
48
49pub type ExpressionQueueFor<P, T> = Vec<
50 Expression<
51 <T as Tokenizer>::Position,
52 <P as Parser<<T as Tokenizer>::Token>>::BinaryOperator,
53 <P as Parser<<T as Tokenizer>::Token>>::UnaryOperator,
54 <P as Parser<<T as Tokenizer>::Token>>::Term,
55 >,
56>;
57
58pub type ExpressionQueue<T, Idx, P> = Vec<
59 Expression<
60 Idx,
61 <P as Parser<T>>::BinaryOperator,
62 <P as Parser<T>>::UnaryOperator,
63 <P as Parser<T>>::Term,
64 >,
65>;
66
67pub struct ParseState<T, TokErr, Idx, P: Parser<T>> {
68 parser: P,
69 end_of_input: Idx,
70 state: State,
71 stack: Stack<T, Idx, P>,
72 queue: ExpressionQueue<T, Idx, P>,
73 errors: Vec<ParseError<P::Error, TokErr, Idx>>,
74}
75
76impl<T, TokErr, Idx: Default + Clone, P: Parser<T>> ParseState<T, TokErr, Idx, P> {
77 pub fn new(parser: P) -> Self {
78 Self {
79 parser,
80 end_of_input: Default::default(),
81 state: State::PostOperator,
82 stack: Stack::new(),
83 queue: Vec::new(),
84 errors: Vec::new(),
85 }
86 }
87
88 pub fn parse_result(&mut self, result: Result<Token<T, Idx>, TokErr>) {
89 match result {
90 Err(e) => self.errors.push(ParseError {
91 span: Span {
92 start: self.end_of_input.clone(),
93 end: self.end_of_input.clone(),
94 },
95 kind: ParseErrorKind::Tokenizer(e),
96 }),
97 Ok(token) => {
98 self.parse_token(token);
99 }
100 }
101 }
102
103 pub fn parse_token(&mut self, token: Token<T, Idx>) {
104 self.end_of_input = token.span.end.clone();
105 match self.parser.parse_token(token.kind) {
106 Ok(element) => match self.state {
107 State::PostOperator => {
108 if self.parse_term(token.span.clone(), element.prefix) {
109 self.parse_operator(token.span, element.postfix);
110 }
111 }
112 State::PostTerm => {
113 if self.parse_operator(token.span.clone(), element.postfix) {
114 self.parse_term(token.span, element.prefix);
115 }
116 }
117 },
118 Err(error) => {
119 self.errors.push(ParseError {
120 span: token.span,
121 kind: ParseErrorKind::Parser(error),
122 });
123 match self.state {
126 State::PostOperator => self.state = State::PostTerm,
127 State::PostTerm => self.state = State::PostOperator,
128 }
129 }
130 }
131 }
132
133 pub fn has_parsed_expression(&mut self) -> bool {
135 !self.stack.has_delimiter()
137 && (
138 self.state == State::PostTerm
140 || self
141 .stack
142 .peek_top()
143 .is_some_and(|top| top.operator.can_have_no_rhs())
144 )
145 }
146
147 pub fn has_error(&mut self) -> bool {
149 !self.errors.is_empty()
150 }
151
152 #[allow(clippy::type_complexity)]
153 pub fn finish(
154 mut self,
155 ) -> Result<ExpressionQueue<T, Idx, P>, ParseErrors<P::Error, TokErr, Idx>> {
156 if self.state != State::PostTerm {
157 if let Some(el) = self.stack.pop() {
158 if let Some(kind) = el.operator.expression_kind_no_rhs() {
159 self.queue.push(Expression {
160 kind,
161 span: el.span.clone(),
162 });
163 } else {
164 self.errors.push(ParseError {
165 kind: ParseErrorKind::EndOfInput {
166 expected: EXPECT_TERM,
167 },
168 span: Span {
169 start: self.end_of_input.clone(),
170 end: self.end_of_input,
171 },
172 })
173 }
174 if el.order.is_delimiter() {
175 self.errors.push(ParseError {
176 kind: ParseErrorKind::UnmatchedLeftDelimiter,
177 span: el.span,
178 })
179 }
180 }
181 }
182 while let Some(el) = self.stack.pop() {
183 if let Some(kind) = el.operator.expression_kind_rhs() {
184 self.queue.push(Expression {
185 kind,
186 span: el.span.clone(),
187 });
188 }
189 if el.order.is_delimiter() {
190 self.errors.push(ParseError {
191 kind: ParseErrorKind::UnmatchedLeftDelimiter,
192 span: el.span,
193 })
194 }
195 }
196 if self.errors.is_empty() {
197 Ok(self.queue)
198 } else {
199 Err(self.errors.into())
200 }
201 }
202
203 fn parse_term(&mut self, span: Span<Idx>, prefix: ParserPrefix<P, T>) -> bool {
204 match prefix {
205 Prefix::LeftDelimiter {
206 delimiter,
207 operator,
208 empty,
209 } => {
210 self.stack.push(StackElement {
211 span,
212 order: StackOrder::Delimiter(delimiter),
213 operator: StackOperator::unary_delimiter(operator, empty),
214 });
215 self.state = State::PostOperator;
216 false
217 }
218 Prefix::RightDelimiter { delimiter } => {
219 self.process_right_delimiter(span, delimiter);
220 false
221 }
222 Prefix::UnaryOperator {
223 precedence,
224 operator,
225 no_rhs,
226 } => {
227 self.stack.push(StackElement {
228 span,
229 order: StackOrder::Precedence(precedence),
230 operator: StackOperator::Unary {
231 unary: operator,
232 term: no_rhs,
233 },
234 });
235 self.state = State::PostOperator;
236 false
237 }
238 Prefix::Term { term } => {
239 self.state = State::PostTerm;
240 self.queue.push(Expression {
241 span,
242 kind: ExpressionKind::Term(term),
243 });
244 false
245 }
246 Prefix::None => {
247 self.state = State::PostTerm;
248 if let Some(el) = self.stack.pop() {
249 if let Some(kind) = el.operator.expression_kind_no_rhs() {
250 self.queue.push(Expression {
251 kind,
252 span: el.span,
253 });
254 } else {
255 self.errors.push(ParseError {
256 kind: ParseErrorKind::UnexpectedToken {
257 expected: EXPECT_TERM,
258 },
259 span: span.clone(),
260 });
261 };
262 }
263 true
264 }
265 }
266 }
267
268 fn parse_operator(&mut self, span: Span<Idx>, postfix: ParserPostfix<P, T>) -> bool {
269 match postfix {
270 Postfix::RightDelimiter { delimiter } => {
271 self.process_right_delimiter(span, delimiter);
272 false
273 }
274 Postfix::BinaryOperator {
275 fixity,
276 operator,
277 no_rhs,
278 } => {
279 self.state = State::PostOperator;
280 self.process_binary_operator(span, fixity, operator, no_rhs);
281 false
282 }
283 Postfix::ImplicitOperator { fixity, operator } => {
284 self.process_binary_operator(span.clone(), fixity, operator, None);
285 true
286 }
287 Postfix::PostfixOperator {
288 precedence,
289 operator,
290 } => {
291 self.process_postfix_operator(span, precedence, operator);
292 false
293 }
294 Postfix::LeftDelimiter {
295 delimiter,
296 operator,
297 empty,
298 } => {
299 self.state = State::PostOperator;
300 self.stack.push(StackElement {
307 span,
308 order: StackOrder::Delimiter(delimiter),
309 operator: StackOperator::Binary {
310 binary: operator,
311 unary: empty,
312 },
313 });
314 false
315 }
316 Postfix::None => {
317 self.state = State::PostOperator;
318 self.errors.push(ParseError {
319 kind: ParseErrorKind::UnexpectedToken {
320 expected: EXPECT_OPERATOR,
321 },
322 span,
323 });
324 true
325 }
326 }
327 }
328
329 fn process_right_delimiter(&mut self, span: Span<Idx>, right: P::Delimiter) {
330 if self.state != State::PostTerm {
335 if let Some(el) = self.stack.pop() {
336 if let Some(kind) = el.operator.expression_kind_no_rhs() {
337 self.queue.push(Expression {
338 kind,
339 span: el.span.clone(),
340 });
341 } else {
342 self.errors.push(ParseError {
343 kind: ParseErrorKind::UnexpectedToken {
344 expected: EXPECT_TERM,
345 },
346 span: span.clone(),
347 });
348 };
349 if let StackOrder::Delimiter(left) = el.order {
350 self.state = State::PostTerm;
351 self.check_delimiter_match(left, el.span, right, span);
352 return;
353 }
354 }
355 };
356 self.state = State::PostTerm;
357 while let Some(el) = self.stack.pop() {
358 if let Some(kind) = el.operator.expression_kind_rhs() {
359 self.queue.push(Expression {
360 kind,
361 span: el.span.clone(),
362 });
363 }
364 if let StackOrder::Delimiter(left) = el.order {
365 self.check_delimiter_match(left, el.span, right, span);
366 return;
367 }
368 }
369 self.errors.push(ParseError {
370 kind: ParseErrorKind::UnmatchedRightDelimiter,
371 span,
372 })
373 }
374
375 fn check_delimiter_match(
376 &mut self,
377 left: P::Delimiter,
378 left_span: Span<Idx>,
379 right: P::Delimiter,
380 right_span: Span<Idx>,
381 ) {
382 if !left.matches(&right) {
383 self.errors.push(ParseError {
384 kind: ParseErrorKind::MismatchedDelimiter { opening: left_span },
385 span: right_span,
386 });
387 }
388 }
389
390 fn process_binary_operator(
391 &mut self,
392 span: Span<Idx>,
393 fixity: Fixity<P::Precedence>,
394 binary: P::BinaryOperator,
395 unary: Option<P::UnaryOperator>,
396 ) {
397 self.pop_while_lower_precedence(&fixity);
398 self.stack.push(StackElement {
399 span,
400 order: StackOrder::Precedence(fixity.into_precedence()),
401 operator: StackOperator::Binary { binary, unary },
402 });
403 }
404
405 fn process_postfix_operator(
406 &mut self,
407 span: Span<Idx>,
408 precedence: P::Precedence,
409 operator: P::UnaryOperator,
410 ) {
411 self.state = State::PostTerm;
412 let fixity = Fixity::Right(precedence);
413 self.pop_while_lower_precedence(&fixity);
414 self.queue.push(Expression {
415 span,
416 kind: ExpressionKind::UnaryOperator(operator),
417 });
418 }
419
420 fn pop_while_lower_precedence(&mut self, fixity: &Fixity<P::Precedence>) {
421 while let Some(el) = self.stack.pop_if_lower_precedence(fixity) {
422 if let Some(kind) = el.operator.expression_kind_rhs() {
423 self.queue.push(Expression {
424 kind,
425 span: el.span,
426 });
427 }
428 }
429 }
430}
431
432impl<T, TokErr, Idx: Default + Clone, P: Parser<T>> Extend<Token<T, Idx>>
433 for ParseState<T, TokErr, Idx, P>
434{
435 fn extend<I>(&mut self, iter: I)
436 where
437 I: IntoIterator<Item = Token<T, Idx>>,
438 {
439 iter.into_iter().for_each(|tok| self.parse_token(tok))
440 }
441}
442
443impl<T, TokErr, Idx: Default + Clone, P: Parser<T>> Extend<Result<Token<T, Idx>, TokErr>>
444 for ParseState<T, TokErr, Idx, P>
445{
446 fn extend<I>(&mut self, iter: I)
447 where
448 I: IntoIterator<Item = Result<Token<T, Idx>, TokErr>>,
449 {
450 iter.into_iter().for_each(|res| self.parse_result(res))
451 }
452}
453
454pub trait Parser<T> {
455 type Precedence: Ord;
456 type Delimiter: Delimiter;
457 type BinaryOperator;
458 type UnaryOperator;
459 type Term;
460 type Error;
461
462 fn parse_token(&self, kind: T) -> Result<ParserElement<Self, T>, Self::Error>;
463}
464
465impl<P, T> Parser<T> for &'_ P
466where
467 P: Parser<T> + ?Sized,
468{
469 type Precedence = P::Precedence;
470 type Delimiter = P::Delimiter;
471 type BinaryOperator = P::BinaryOperator;
472 type UnaryOperator = P::UnaryOperator;
473 type Term = P::Term;
474 type Error = P::Error;
475
476 fn parse_token(&self, kind: T) -> Result<ParserElement<Self, T>, Self::Error> {
477 P::parse_token(self, kind)
478 }
479}
480
481pub trait Delimiter {
482 fn matches(&self, other: &Self) -> bool;
483}
484
485pub struct Element<P, D, B, U, T> {
486 pub prefix: Prefix<P, D, U, T>,
487 pub postfix: Postfix<P, D, B, U>,
488}
489
490pub type ParserElement<P, T> = Element<
491 <P as Parser<T>>::Precedence,
492 <P as Parser<T>>::Delimiter,
493 <P as Parser<T>>::BinaryOperator,
494 <P as Parser<T>>::UnaryOperator,
495 <P as Parser<T>>::Term,
496>;
497
498pub enum Prefix<P, D, U, T> {
499 UnaryOperator {
500 precedence: P,
501 operator: U,
502 no_rhs: Option<T>,
503 },
504 LeftDelimiter {
505 delimiter: D,
506 operator: Option<U>,
507 empty: Option<T>,
508 },
509 RightDelimiter {
510 delimiter: D,
511 },
512 Term {
513 term: T,
514 },
515 None,
516}
517
518type ParserPrefix<P, T> = Prefix<
519 <P as Parser<T>>::Precedence,
520 <P as Parser<T>>::Delimiter,
521 <P as Parser<T>>::UnaryOperator,
522 <P as Parser<T>>::Term,
523>;
524
525pub enum Postfix<P, D, B, U> {
526 BinaryOperator {
527 fixity: Fixity<P>,
528 operator: B,
529 no_rhs: Option<U>,
530 },
531 PostfixOperator {
532 precedence: P,
533 operator: U,
534 },
535 LeftDelimiter {
536 delimiter: D,
537 operator: B,
538 empty: Option<U>,
539 },
540 RightDelimiter {
541 delimiter: D,
542 },
543 ImplicitOperator {
544 fixity: Fixity<P>,
545 operator: B,
546 },
547 None,
548}
549
550type ParserPostfix<P, T> = Postfix<
551 <P as Parser<T>>::Precedence,
552 <P as Parser<T>>::Delimiter,
553 <P as Parser<T>>::BinaryOperator,
554 <P as Parser<T>>::UnaryOperator,
555>;
556
557pub enum StackOrder<P, D> {
558 Precedence(P),
559 Delimiter(D),
560}
561
562impl<P, D> StackOrder<P, D> {
563 fn precedence(&self) -> Option<&P> {
564 match self {
565 Self::Precedence(p) => Some(p),
566 Self::Delimiter(_) => None,
567 }
568 }
569
570 fn is_delimiter(&self) -> bool {
571 matches!(self, Self::Delimiter(_))
572 }
573}
574
575#[derive(Clone, Copy, Debug, Eq, PartialEq)]
576enum State {
577 PostOperator,
578 PostTerm,
579}
580
581struct Stack<T, Idx, P: Parser<T>> {
582 stack: Vec<StackElement<T, Idx, P>>,
583 first_delimiter_idx: Option<usize>,
584}
585
586impl<T, Idx, P: Parser<T>> Default for Stack<T, Idx, P> {
587 fn default() -> Self {
588 Stack {
589 stack: Default::default(),
590 first_delimiter_idx: None,
591 }
592 }
593}
594
595impl<T, Idx, P: Parser<T>> Stack<T, Idx, P> {
596 fn new() -> Self {
597 Default::default()
598 }
599
600 fn push(&mut self, element: StackElement<T, Idx, P>) {
601 if element.order.is_delimiter() && self.first_delimiter_idx.is_none() {
602 self.first_delimiter_idx = Some(self.stack.len());
603 }
604 self.stack.push(element);
605 }
606
607 fn pop(&mut self) -> Option<StackElement<T, Idx, P>> {
608 let el = self.stack.pop();
609 if Some(self.stack.len()) == self.first_delimiter_idx {
610 self.first_delimiter_idx = None
611 }
612 el
613 }
614
615 fn peek_top(&self) -> Option<&StackElement<T, Idx, P>> {
616 self.stack.last()
617 }
618
619 fn has_delimiter(&self) -> bool {
620 self.first_delimiter_idx.is_some()
621 }
622
623 fn pop_if_lower_precedence(
625 &mut self,
626 fixity: &Fixity<P::Precedence>,
627 ) -> Option<StackElement<T, Idx, P>> {
628 if match fixity {
629 Fixity::Left(prec) => Some(prec) <= self.precedence(),
630 Fixity::Right(prec) => Some(prec) < self.precedence(),
631 } {
632 self.pop()
633 } else {
634 None
635 }
636 }
637
638 fn precedence(&self) -> Option<&P::Precedence> {
639 self.peek_top().and_then(StackElement::precedence)
640 }
641}
642
643struct StackElement<T, Idx, P: Parser<T>> {
644 span: Span<Idx>,
645 order: StackOrder<P::Precedence, P::Delimiter>,
646 operator: StackOperator<P::BinaryOperator, P::UnaryOperator, P::Term>,
647}
648
649impl<T, Idx, P: Parser<T>> StackElement<T, Idx, P> {
650 fn precedence(&self) -> Option<&P::Precedence> {
651 self.order.precedence()
652 }
653}
654
655#[derive(Clone, Copy, Debug)]
656enum StackOperator<B, U, T> {
657 None { term: Option<T> },
658 Binary { binary: B, unary: Option<U> },
659 Unary { unary: U, term: Option<T> },
660}
661
662impl<B, U, T> StackOperator<B, U, T> {
663 fn unary_delimiter(unary: Option<U>, term: Option<T>) -> Self {
664 match unary {
665 None => Self::None { term },
666 Some(unary) => Self::Unary { unary, term },
667 }
668 }
669
670 fn expression_kind_rhs(self) -> Option<ExpressionKind<B, U, T>> {
671 match self {
672 Self::None { .. } => None,
673 Self::Binary { binary, .. } => Some(ExpressionKind::BinaryOperator(binary)),
674 Self::Unary { unary, .. } => Some(ExpressionKind::UnaryOperator(unary)),
675 }
676 }
677
678 fn expression_kind_no_rhs(self) -> Option<ExpressionKind<B, U, T>> {
679 match self {
680 Self::None { term } | Self::Unary { term, .. } => term.map(ExpressionKind::Term),
681 Self::Binary { unary, .. } => unary.map(ExpressionKind::UnaryOperator),
682 }
683 }
684 fn can_have_no_rhs(&self) -> bool {
685 match self {
686 Self::None { term } | Self::Unary { term, .. } => term.is_some(),
687 Self::Binary { unary, .. } => unary.is_some(),
688 }
689 }
690}
691
692#[cfg(test)]
693mod tests {
694 #![allow(clippy::type_complexity)]
695
696 use std::{convert::Infallible, ops::Range};
697
698 use test_case::test_case;
699
700 use super::{
701 parse, parse_one_term, Delimiter, Element, ParseState, Parser, Postfix, Prefix,
702 EXPECT_OPERATOR, EXPECT_TERM,
703 };
704 use crate::{
705 error::ParseErrorKind,
706 expression::{Expression, ExpressionKind},
707 operator::Fixity,
708 token::{
709 charset::{SimpleCharSetTokenKind, SimpleTokenizer, StrSource},
710 Tokenizer,
711 },
712 };
713
714 struct SimpleExprContext;
715
716 #[derive(Clone, Copy, Eq, PartialEq)]
717 enum SimpleDelimiter {
718 Paren,
719 SquareBracket,
720 Pipe,
721 }
722
723 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
724 enum SimplePrecedence {
725 Comma,
727 Additive,
729 Multiplicative,
731 Exponential,
733 }
734
735 impl Delimiter for SimpleDelimiter {
736 fn matches(&self, other: &Self) -> bool {
737 self == other
738 }
739 }
740
741 impl<'s> Parser<(&'s str, SimpleCharSetTokenKind)> for SimpleExprContext {
742 type Error = Infallible;
743 type Precedence = SimplePrecedence;
744 type Delimiter = SimpleDelimiter;
745 type BinaryOperator = &'s str;
746 type UnaryOperator = &'s str;
747 type Term = &'s str;
748
749 fn parse_token(
750 &self,
751 (s, kind): (&'s str, SimpleCharSetTokenKind),
752 ) -> Result<
753 Element<
754 Self::Precedence,
755 Self::Delimiter,
756 Self::BinaryOperator,
757 Self::UnaryOperator,
758 Self::Term,
759 >,
760 Self::Error,
761 > {
762 Ok(match s {
763 "(" => Element {
764 prefix: Prefix::LeftDelimiter {
765 delimiter: SimpleDelimiter::Paren,
766 operator: None,
767 empty: None,
768 },
769 postfix: Postfix::LeftDelimiter {
770 delimiter: SimpleDelimiter::Paren,
771 operator: s,
772 empty: Some("()"),
773 },
774 },
775 ")" => Element {
776 prefix: Prefix::RightDelimiter {
777 delimiter: SimpleDelimiter::Paren,
778 },
779 postfix: Postfix::RightDelimiter {
780 delimiter: SimpleDelimiter::Paren,
781 },
782 },
783 "[" => Element {
784 prefix: Prefix::LeftDelimiter {
785 delimiter: SimpleDelimiter::SquareBracket,
786 operator: Some(s),
787 empty: Some("[]"),
788 },
789 postfix: Postfix::None,
790 },
791 "]" => Element {
792 prefix: Prefix::RightDelimiter {
793 delimiter: SimpleDelimiter::SquareBracket,
794 },
795 postfix: Postfix::RightDelimiter {
796 delimiter: SimpleDelimiter::SquareBracket,
797 },
798 },
799 "|" => Element {
800 prefix: Prefix::LeftDelimiter {
801 delimiter: SimpleDelimiter::Pipe,
802 operator: Some(s),
803 empty: None,
804 },
805 postfix: Postfix::RightDelimiter {
806 delimiter: SimpleDelimiter::Pipe,
807 },
808 },
809 "," => Element {
810 prefix: Prefix::None,
811 postfix: Postfix::BinaryOperator {
812 fixity: Fixity::Left(SimplePrecedence::Comma),
813 operator: s,
814 no_rhs: Some("(,)"),
815 },
816 },
817 "-" => Element {
818 prefix: Prefix::UnaryOperator {
819 precedence: SimplePrecedence::Multiplicative,
820 operator: s,
821 no_rhs: None,
822 },
823 postfix: Postfix::BinaryOperator {
824 fixity: Fixity::Left(SimplePrecedence::Additive),
825 operator: s,
826 no_rhs: None,
827 },
828 },
829 "+" => Element {
830 prefix: Prefix::None,
831 postfix: Postfix::BinaryOperator {
832 fixity: Fixity::Left(SimplePrecedence::Additive),
833 operator: s,
834 no_rhs: None,
835 },
836 },
837 "*" | "/" => Element {
838 prefix: Prefix::None,
839 postfix: Postfix::BinaryOperator {
840 fixity: Fixity::Left(SimplePrecedence::Multiplicative),
841 operator: s,
842 no_rhs: None,
843 },
844 },
845 "^" => Element {
846 prefix: Prefix::None,
847 postfix: Postfix::BinaryOperator {
848 fixity: Fixity::Right(SimplePrecedence::Exponential),
849 operator: s,
850 no_rhs: None,
851 },
852 },
853 "!" => Element {
854 prefix: Prefix::None,
855 postfix: Postfix::PostfixOperator {
856 precedence: SimplePrecedence::Exponential,
857 operator: s,
858 },
859 },
860 _ => {
861 let postfix = if let SimpleCharSetTokenKind::Tag = kind {
864 Postfix::ImplicitOperator {
865 fixity: Fixity::Left(SimplePrecedence::Multiplicative),
866 operator: "{*}",
867 }
868 } else {
869 Postfix::None
870 };
871 Element {
872 prefix: Prefix::Term { term: s },
873 postfix,
874 }
875 }
876 })
877 }
878 }
879
880 fn expr_to_str<'s, Idx>(expr: Expression<Idx, &'s str, &'s str, &'s str>) -> &'s str {
881 match expr.kind {
882 ExpressionKind::BinaryOperator(s) => s,
883 ExpressionKind::UnaryOperator(s) => s,
884 ExpressionKind::Term(s) => s,
885 }
886 }
887
888 #[test_case("3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3", "3 4 2 * 1 5 - 2 3 ^ ^ / +" ; "simple arithmetic" )]
889 #[test_case("sin(max(5/2, 3)) / 3 * pi", "sin max 5 2 / 3 , ( ( 3 / pi *" ; "with functions" )]
890 #[test_case("2^3!", "2 3 ! ^" ; "postfix operators" )]
891 #[test_case("-2^3 + (-2)^3", "2 3 ^ - 2 - 3 ^ +" ; "prefix operators" )]
892 #[test_case("[1, 2, 3, 4]", "1 2 , 3 , 4 , [" ; "delimiter operators" )]
893 #[test_case("[1, (2, 3), 4]", "1 2 3 , , 4 , [" ; "nested delimiter operators" )]
894 #[test_case("[ ]", "[]" ; "empty list" )]
895 #[test_case("[ ] + [ ]", "[] [] +" ; "adding lists" )]
896 #[test_case("f()", "f ()" ; "empty function call" )]
897 #[test_case("[1, 2, 3, 4, ]", "1 2 , 3 , 4 , (,) [" ; "trailing comma" )]
898 #[test_case("a * |b|", "a b | *" ; "absolute value" )]
899 #[test_case("a, * b", "a (,) b *" ; "trailing comma with binary operator" )]
900 #[test_case("5x^2", "5 x 2 ^ {*}" ; "implicit operator" )]
901 fn parse_expression(input: &str, output: &str) -> anyhow::Result<()> {
902 let actual = parse(
903 SimpleTokenizer::new(StrSource::new(input)),
904 SimpleExprContext,
905 )?
906 .into_iter()
907 .map(expr_to_str)
908 .collect::<Vec<_>>();
909 let expected = output.split_whitespace().collect::<Vec<_>>();
910 assert_eq!(actual, expected);
911 Ok(())
912 }
913
914 #[test_case("3", "3", "" ; "single term" )]
915 #[test_case("-3!", "3 -", "!" ; "unary operators" )]
916 #[test_case("3!", "3", "!" ; "postfix operator" )]
917 #[test_case("-3 a", "3 -", "a" ; "unary operators with additional" )]
918 #[test_case("(5 + 4) * (3 - 2)", "5 4 +", "* (3 - 2)" ; "delimited group" )]
919 #[test_case("(3)!", "3", "!" ; "delimited with unary operators" )]
920 #[test_case("abc def)", "abc", "def)" ; "ignores invalid after first term" )]
921 fn parse_one(input: &str, output: &str, rest: &str) -> anyhow::Result<()> {
922 let mut tokens = SimpleTokenizer::new(StrSource::new(input));
923 let actual = parse_one_term(&mut tokens, SimpleExprContext)?
924 .into_iter()
925 .map(expr_to_str)
926 .collect::<Vec<_>>();
927 let expected = output.split_whitespace().collect::<Vec<_>>();
928 assert_eq!(actual, expected);
929 let actual_rest = tokens
930 .map(|res| res.map(|tok| tok.kind))
931 .collect::<Result<Vec<_>, _>>()?;
932 let expected_rest = SimpleTokenizer::new(StrSource::new(rest))
933 .map(|res| res.map(|tok| tok.kind))
934 .collect::<Result<Vec<_>, _>>()?;
935 assert_eq!(actual_rest, expected_rest);
936 Ok(())
937 }
938
939 #[test_case("-", false ; "unary")]
940 #[test_case("-3", true ; "unary with rhs")]
941 #[test_case("-3 *", false ; "binary")]
942 #[test_case("-3 * 3", true ; "binary with rhs")]
943 #[test_case("-(4 + (3 * 3)", false ; "incomplete delimiter")]
944 #[test_case("-(4 + (3 * 3))", true ; "complete delimiter")]
945 #[test_case("3,", true ; "binary with optional rhs")]
946 fn is_complete(input: &str, is_complete: bool) -> anyhow::Result<()> {
947 let mut tokens = SimpleTokenizer::new(StrSource::new(input));
948 let mut state = ParseState::new(SimpleExprContext);
949 while let Some(t) = tokens.next_token() {
950 state.parse_result(t);
951 }
952 assert_eq!(state.has_parsed_expression(), is_complete);
953 if is_complete {
954 state.finish()?;
955 } else {
956 state.finish().unwrap_err();
957 }
958 Ok(())
959 }
960
961 #[test_case("1 )", &[(ParseErrorKind::UnmatchedRightDelimiter, 2..3)] ; "unmatched right paren" )]
962 #[test_case("1 +", &[(ParseErrorKind::EndOfInput { expected: EXPECT_TERM }, 3..3)] ; "end of input" )]
963 #[test_case("(5 5 +", &[
964 (ParseErrorKind::UnexpectedToken { expected: EXPECT_OPERATOR }, 3..4),
965 (ParseErrorKind::EndOfInput { expected: EXPECT_TERM }, 6..6),
966 (ParseErrorKind::UnmatchedLeftDelimiter, 0..1),
967 ] ; "multiple errors")]
968 #[test_case("[ 1 )", &[
969 (ParseErrorKind::MismatchedDelimiter { opening: (0..1).into() }, 4..5),
970 ] ; "mismatched delimiters" )]
971 #[test_case("( [ 1 )", &[
972 (ParseErrorKind::MismatchedDelimiter { opening: (2..3).into() }, 6..7),
973 (ParseErrorKind::UnmatchedLeftDelimiter, 0..1),
974 ] ; "mismatched delimiters 2" )]
975 #[test_case("[ 1 + )", &[
976 (ParseErrorKind::UnexpectedToken { expected: EXPECT_TERM }, 6..7),
977 (ParseErrorKind::MismatchedDelimiter { opening: (0..1).into() }, 6..7),
978 ] ; "mismatched delimiters with missing rhs" )]
979 #[test_case("1 + * 2", &[
980 (ParseErrorKind::UnexpectedToken { expected: EXPECT_TERM }, 4..5),
981 ] ; "extra operator" )]
982 fn parse_expression_fail(
983 input: &str,
984 expected: &[(ParseErrorKind<Infallible, Infallible, usize>, Range<usize>)],
985 ) {
986 let actual = parse(
987 SimpleTokenizer::new(StrSource::new(input)),
988 SimpleExprContext,
989 )
990 .unwrap_err()
991 .errors
992 .into_iter()
993 .map(|err| {
994 (
995 err.kind.map_tokenizer_error(|_| unreachable!()),
996 err.span.into_range(),
997 )
998 })
999 .collect::<Vec<_>>();
1000 assert_eq!(actual, expected);
1001 }
1002}