File: conditional_block.rs

package info (click to toggle)
rust-peg 0.8.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 756 kB
  • sloc: makefile: 20; sh: 12
file content (55 lines) | stat: -rw-r--r-- 1,790 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
extern crate peg;

peg::parser!( grammar parse() for str {

    pub rule dec_byte() -> u8
        = match_str:$(['0'..='9']*<,3>) {?
            let val: u64 = match_str.parse().unwrap();

            // only let this rule match if the value is in range 0..255
            if val <= 255 {
                Ok(val as u8)
            } else {
                // the message explains what the rule expected and is used in the parse error
                Err("decimal byte")
            }
        }

    rule tag() -> &'input str
        = $(['a'..='z']+)

    pub rule xml()
        = "<" open:tag() ">" xml()* "</" close:tag() ">" {?
            if open == close {
                Ok(())
            } else {
                // TODO this has to be a `&'static str`, so we can't use a dynamic string
                Err("matching close tag")
            }
        }

    pub rule return_early() -> i32 = vs:$([_]+) {?
        let v = vs.parse::<i32>().map_err(|_| "number")?;
        if v > 100 {
            return Err("smaller number");
        }
        Ok(v)
    }
});

fn main() {
    assert_eq!(parse::dec_byte("0"), Ok(0));
    assert_eq!(parse::dec_byte("255"), Ok(255));
    assert_eq!(parse::dec_byte("1"), Ok(1));
    assert!(parse::dec_byte("256").is_err());
    assert!(parse::dec_byte("1234").is_err());

    assert!(parse::xml("<a></a>").is_ok());
    assert!(parse::xml("<a><b></b><c></c></a>").is_ok());
    assert!(parse::xml("<a><b><c></b></c></a>").is_err());
    assert!(parse::xml("<a><b></c><c></b></a>").is_err());

    assert!(parse::return_early("a").unwrap_err().expected.tokens().any(|e| e == "number"));
    assert!(parse::return_early("123").unwrap_err().expected.tokens().any(|e| e == "smaller number"));
    assert_eq!(parse::return_early("99").unwrap(), 99);
}