Skip to content

Commit 3625ba2

Browse files
committed
style: move c_expression examples to separate file
Resolves: * winnow-rs#804 (comment)
1 parent 644ee94 commit 3625ba2

File tree

2 files changed

+271
-247
lines changed

2 files changed

+271
-247
lines changed

examples/c_expression/parser.rs

Lines changed: 23 additions & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ use winnow::error::{ContextError, ErrMode};
110110
use winnow::prelude::*;
111111
use winnow::token::{any, one_of, take, take_while};
112112

113+
#[cfg(test)]
114+
mod test;
115+
113116
// Abstract syntax tree for an expression
114117
pub(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

Comments
 (0)