@@ -110,6 +110,9 @@ use winnow::error::{ContextError, ErrMode};
110110use winnow:: prelude:: * ;
111111use winnow:: token:: { any, one_of, take, take_while} ;
112112
113+ #[ cfg( test) ]
114+ mod test;
115+
113116// Abstract syntax tree for an expression
114117pub ( crate ) enum Expr {
115118 Name ( String ) ,
@@ -503,252 +506,25 @@ impl core::fmt::Display for Expr {
503506 }
504507}
505508
506- #[ cfg( test) ]
507- mod test {
508-
509- #[ allow( clippy:: useless_attribute) ]
510- #[ allow( unused_imports) ] // its dead for benches
511- use super :: * ;
512- use winnow:: error:: ParseError ;
513-
514- #[ allow( dead_code) ]
515- // to invoke fmt_delimited()
516- struct PrefixNotation ( Expr ) ;
517-
518- impl core:: fmt:: Display for PrefixNotation {
519- fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
520- self . 0 . fmt_delimited ( f)
521- }
522- }
523-
524- #[ allow( dead_code) ]
525- fn parse ( i : & str ) -> Result < String , ParseError < & str , winnow:: error:: ContextError > > {
509+ #[ test]
510+ fn parse_example ( ) {
511+ // Check out the [`crate::parser::test`] in this example for more samples.
512+ let result =
526513 pratt_parser
527- . parse ( i)
528- . map ( |r| format ! ( "{}" , PrefixNotation ( r) ) )
529- }
530-
531- #[ allow( dead_code) ]
532- fn parse_ok ( i : & str , expect : & str ) {
533- assert_eq ! ( parse( i) . unwrap( ) , expect) ;
534- }
535-
536- #[ test]
537- fn op ( ) {
538- parse_ok ( " 1 " , "1" ) ;
539- }
540-
541- #[ test]
542- fn neither ( ) {
543- assert ! ( parse( "1 == 2 == 3" ) . is_err( ) ) ;
544- assert ! ( parse( "1 -le 2 -gt 3" ) . is_err( ) ) ;
545- assert ! ( parse( "1 < 2 < 3" ) . is_err( ) ) ;
546- assert ! ( parse( "1 != 2 == 3" ) . is_err( ) ) ;
547- }
548-
549- #[ test]
550- fn equal ( ) {
551- parse_ok ( "x=3" , "(= x 3)" ) ;
552- parse_ok ( "x = 2*3" , "(= x (* 2 3))" ) ;
553- parse_ok ( "x = y" , "(= x y)" ) ;
554- parse_ok ( "a = b = 10" , "(= a (= b 10))" ) ;
555- parse_ok ( "x = ((y*4)-2)" , "(= x (- (* y 4) 2))" ) ;
556- }
557-
558- #[ test]
559- fn unary ( ) {
560- parse_ok ( "- - a" , "(-(-a))" ) ;
561- parse_ok ( "+ - a" , "(-a)" ) ;
562- parse_ok ( "++ -- a" , "(pre++(pre--a))" ) ;
563- parse_ok ( "a ++ --" , "(post--(post++a))" ) ;
564- parse_ok ( "!x" , "(!x)" ) ;
565- parse_ok ( "x--" , "(post--x)" ) ;
566- parse_ok ( "x[1]--" , "(post--([] x 1))" ) ;
567- parse_ok ( "--x" , "(pre--x)" ) ;
568- parse_ok ( "++x[1]" , "(pre++([] x 1))" ) ;
569- parse_ok ( "!x--" , "(!(post--x))" ) ;
570- parse_ok ( "~x++" , "(~(post++x))" ) ;
571- parse_ok ( "x++ - y++" , "(- (post++x) (post++y))" ) ;
572- parse_ok ( "++x - ++y" , "(- (pre++x) (pre++y))" ) ;
573- parse_ok ( "--1 * 2" , "(* (pre--1) 2)" ) ;
574- parse_ok ( "--f . g" , "(pre--(. f g))" ) ;
575- }
576-
577- #[ test]
578- fn same_precedence ( ) {
579- // left associative
580- parse_ok ( "1 + 2 + 3" , "(+ (+ 1 2) 3)" ) ;
581- parse_ok ( "1 - 2 - 3" , "(- (- 1 2) 3)" ) ;
582- parse_ok ( "1 * 2 * 3" , "(* (* 1 2) 3)" ) ;
583- parse_ok ( "1 / 2 / 3" , "(/ (/ 1 2) 3)" ) ;
584- parse_ok ( "1 % 2 % 3" , "(% (% 1 2) 3)" ) ;
585- parse_ok ( "1 ^ 2 ^ 3" , "(^ (^ 1 2) 3)" ) ;
586- parse_ok ( "+-+1" , "(-1)" ) ;
587- parse_ok ( "f . g . h" , "(. (. f g) h)" ) ;
588- parse_ok ( "++--++1" , "(pre++(pre--(pre++1)))" ) ;
589- // right associative
590- parse_ok ( "2 ** 3 ** 2" , "(** 2 (** 3 2))" ) ;
591- }
592-
593- #[ test]
594- fn different_precedence ( ) {
595- parse_ok ( "1 + 2 * 3" , "(+ 1 (* 2 3))" ) ;
596- parse_ok ( "1 + 2 * 3 - 4 / 5" , "(- (+ 1 (* 2 3)) (/ 4 5))" ) ;
597- parse_ok ( "a + b * c * d + e" , "(+ (+ a (* (* b c) d)) e)" ) ;
598- parse_ok ( "1 + ++2 * 3 * 5 + 6" , "(+ (+ 1 (* (* (pre++2) 3) 5)) 6)" ) ;
599- parse_ok ( "**3 + &1" , "(+ (*(*3)) (&1))" ) ;
600- parse_ok ( "x*y - y*z" , "(- (* x y) (* y z))" ) ;
601- parse_ok ( "x/y - y%z" , "(- (/ x y) (% y z))" ) ;
602- parse_ok ( "1<2 * 3" , "(< 1 (* 2 3))" ) ;
603- parse_ok (
604- " 1 + 2 + f . g . h * 3 * 4" ,
605- "(+ (+ 1 2) (* (* (. (. f g) h) 3) 4))" ,
606- ) ;
607- }
608-
609- #[ test]
610- fn prefix_postfix_power ( ) {
611- // https://en.cppreference.com/w/c/language/operator_precedence
612- // `post++` has `1`, `pre--` and `*` have 2
613- parse_ok ( "--**3++" , "(pre--(*(*(post++3))))" ) ;
614- parse_ok ( "**--3++" , "(*(*(pre--(post++3))))" ) ;
615- parse_ok ( "&foo()[0]" , "(&([] (call foo) 0))" ) ;
616- parse_ok ( "-9!" , "(-(!9))" ) ;
617- parse_ok ( "f . g !" , "(!(. f g))" ) ;
618- }
619-
620- #[ test]
621- fn prefix_infix ( ) {
622- parse_ok ( "x - -y" , "(- x (-y))" ) ;
623- parse_ok ( "-1 * -2" , "(* (-1) (-2))" ) ;
624- parse_ok ( "-x * -y" , "(* (-x) (-y))" ) ;
625- parse_ok ( "x - -234" , "(- x (-234))" ) ;
626- }
627-
628- #[ test]
629- fn ternary ( ) {
630- parse_ok ( "a ? 2 + c : -2 * 2" , "(? a (+ 2 c) (* (-2) 2))" ) ;
631- parse_ok ( "a ? b : c ? d : e" , "(? a b (? c d e))" ) ;
632- parse_ok ( "2! > 1 ? 3 : 1" , "(? (> (!2) 1) 3 1)" ) ;
633- parse_ok (
634- "2 > 1 ? 1 -ne 3 ? 4 : 5 : 1" ,
635- "(? (> 2 1) (? (!= 1 3) 4 5) 1)" ,
636- ) ;
637- parse_ok ( "a > b ? 0 : 1" , "(? (> a b) 0 1)" ) ;
638- parse_ok ( "a > b ? x+1 : y+1" , "(? (> a b) (+ x 1) (+ y 1))" ) ;
639- parse_ok (
640- "1 ? true1 : 2 ? true2 : false" ,
641- "(? 1 true1 (? 2 true2 false))" ,
642- ) ;
643- parse_ok (
644- "1 ? true1 : (2 ? true2 : false)" ,
645- "(? 1 true1 (? 2 true2 false))" ,
646- ) ;
647-
648- parse_ok (
649- "1 ? (2 ? true : false1) : false2" ,
650- "(? 1 (? 2 true false1) false2)" ,
651- ) ;
652- parse_ok (
653- "1 ? 2 ? true : false1 : false2" ,
654- "(? 1 (? 2 true false1) false2)" ,
655- ) ;
656- }
657-
658- #[ test]
659- fn comma ( ) {
660- parse_ok ( "x=1,y=2,z=3" , "(, (, (= x 1) (= y 2)) (= z 3))" ) ;
661- parse_ok ( "a, b, c" , "(, (, a b) c)" ) ;
662- parse_ok ( "(a, b, c)" , "(, (, a b) c)" ) ;
663- parse_ok ( "f(a, b, c), d" , "(, (call f (, (, a b) c)) d)" ) ;
664- parse_ok ( "(a, b, c), d" , "(, (, (, a b) c) d)" ) ;
665- }
666-
667- #[ test]
668- fn comma_ternary ( ) {
669- parse_ok ( "x ? 1 : 2, y ? 3 : 4" , "(, (? x 1 2) (? y 3 4))" ) ;
670- // Comma expressions can be inside
671- parse_ok ( "a , b ? c, d : e, f" , "(, (, a (? b (, c d) e)) f)" ) ;
672- parse_ok ( "a = 0 ? b : c = d" , "(= a (= (? 0 b c) d))" ) ;
673- }
674-
675- #[ test]
676- fn braces ( ) {
677- parse_ok ( "4*(2+3)" , "(* 4 (+ 2 3))" ) ;
678- parse_ok ( "(2+3)*4" , "(* (+ 2 3) 4)" ) ;
679- parse_ok ( "(((0)))" , "0" ) ;
680- }
681-
682- #[ test]
683- fn logical ( ) {
684- parse_ok ( "a && b || c && d" , "(|| (&& a b) (&& c d))" ) ;
685- parse_ok ( "!a && !b" , "(&& (!a) (!b))" ) ;
686- parse_ok ( "a != b && c == d" , "(&& (!= a b) (== c d))" ) ;
687- }
688-
689- #[ test]
690- fn array ( ) {
691- parse_ok ( "x[1,2]" , "([] x (, 1 2))" ) ;
692- parse_ok ( "x[1]" , "([] x 1)" ) ;
693- parse_ok ( "x[a+b]" , "([] x (+ a b))" ) ;
694- parse_ok ( "c = pal[i*8]" , "(= c ([] pal (* i 8)))" ) ;
695- parse_ok ( "f[x] = 1" , "(= ([] f x) 1)" ) ;
696- parse_ok ( "x[0][1]" , "([] ([] x 0) 1)" ) ;
697- }
698-
699- #[ test]
700- fn function_call ( ) {
701- parse_ok ( "a()" , "(call a)" ) ;
702- parse_ok ( "a(+1)" , "(call a 1)" ) ;
703- parse_ok ( "a()+1" , "(+ (call a) 1)" ) ;
704- parse_ok ( "f(a, b, c)" , "(call f (, (, a b) c))" ) ;
705- parse_ok ( "print(x)" , "(call print x)" ) ;
706- parse_ok (
707- "x = y(2)*3 + y(4)*5" ,
708- "(= x (+ (* (call y 2) 3) (* (call y 4) 5)))" ,
709- ) ;
710- parse_ok ( "x(1,2)+y(3,4)" , "(+ (call x (, 1 2)) (call y (, 3 4)))" ) ;
711- parse_ok ( "x(a,b,c[d])" , "(call x (, (, a b) ([] c d)))" ) ;
712- parse_ok (
713- "x(1,2)*j+y(3,4)*k+z(5,6)*l" ,
714- "(+ (+ (* (call x (, 1 2)) j) (* (call y (, 3 4)) k)) (* (call z (, 5 6)) l))" ,
715- ) ;
716- parse_ok ( "print(test(2,3))" , "(call print (call test (, 2 3)))" ) ;
717- parse_ok ( "min(255,n*2)" , "(call min (, 255 (* n 2)))" ) ;
718- }
719-
720- #[ test]
721- fn member_access ( ) {
722- parse_ok ( "a.b" , "(. a b)" ) ;
723- parse_ok ( "a.b.c" , "(. (. a b) c)" ) ;
724- parse_ok ( "a->b" , "(-> a b)" ) ;
725- parse_ok ( "++a->b" , "(pre++(-> a b))" ) ;
726- parse_ok ( "a++ ->b" , "(-> (post++a) b)" ) ;
727- parse_ok ( "a.(x)" , "(. a x)" ) ;
728- parse_ok ( "a.(x+3)" , "(. a (+ x 3))" ) ;
729- }
730-
731- #[ test]
732- fn errors ( ) {
733- assert ! ( parse( "x + a b" ) . is_err( ) ) ;
734- assert ! ( parse( "x[a b]" ) . is_err( ) ) ;
735- assert ! ( parse( "x[a)]" ) . is_err( ) ) ;
736- assert ! ( parse( "x(a])" ) . is_err( ) ) ;
737- assert ! ( parse( "[a + b]" ) . is_err( ) ) ;
738- assert ! ( parse( "[a b]" ) . is_err( ) ) ;
739- assert ! ( parse( "+" ) . is_err( ) ) ;
740- assert ! ( parse( "a +" ) . is_err( ) ) ;
741- assert ! ( parse( "<=" ) . is_err( ) ) ;
742- assert ! ( parse( "<= - a + b" ) . is_err( ) ) ;
743- assert ! ( parse( "a b" ) . is_err( ) ) ;
744- assert ! ( parse( "a + b @" ) . is_err( ) ) ;
745- assert ! ( parse( "a + b )" ) . is_err( ) ) ;
746- assert ! ( parse( "( a + b" ) . is_err( ) ) ;
747- assert ! ( parse( "( a + b) c" ) . is_err( ) ) ;
748- assert ! ( parse( "f ( a + b ) c" ) . is_err( ) ) ;
749- assert ! ( parse( "@ a + b" ) . is_err( ) ) ;
750- assert ! ( parse( "a @ b" ) . is_err( ) ) ;
751- assert ! ( parse( "(a @ b)" ) . is_err( ) ) ;
752- assert ! ( parse( ")" ) . is_err( ) ) ;
753- }
514+ . parse ( "a*a + b - c" )
515+ . map ( |r| format ! ( "{}" , r) )
516+ . unwrap ( ) ;
517+
518+ let expect = "\
519+ SUB
520+ ADD
521+ MUL
522+ NAME a
523+ NAME a
524+ NAME b
525+ NAME c
526+
527+ (- (+ (* a a) b) c)" ;
528+
529+ assert_eq ! ( result, expect) ;
754530}
0 commit comments