Created
February 1, 2020 19:28
-
-
Save zicklag/aad1944ef7f5dd256218892477f32c64 to your computer and use it in GitHub Desktop.
Example of using rust-peg parser and chic error messages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "parserator" | |
version = "0.1.0" | |
authors = ["Zicklag"] | |
edition = "2018" | |
[dependencies] | |
peg = "0.6.1" | |
anyhow = "1.0.26" | |
chic = "1.2.2" | |
thiserror = "1.0.10" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
error: Parser error | |
| | |
4 | [ 1, 3,4, 5, | |
5 | 6, | |
6 | | |
7 | 8, 9, 10, 7,10d] | |
| ^ Expected: one of ",", "]" | |
| |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(thiserror::Error, Debug)] | |
#[error("Parser error")] | |
struct ParseratorError { | |
error: peg::error::ParseError<peg::str::LineCol>, | |
src: String, | |
} | |
impl ParseratorError { | |
fn new(error: peg::error::ParseError<peg::str::LineCol>, src: &str) -> Self { | |
ParseratorError { | |
error, | |
src: src.to_string(), | |
} | |
} | |
} | |
peg::parser! { | |
grammar list_parser() for str { | |
// Whitespace character | |
rule whitespace_char() = ['\t' | ' '] | |
// Line comment | |
rule line_comment() = "//" (!"\n" [_])* ("\n" / ![_]) | |
// Inline comment | |
rule inline_comment() = "/*" (!"*/" [_])* "*/" | |
// Whitespace including comments | |
rule w() = quiet!{ (whitespace_char() / inline_comment())* } | |
// Whitespace including newlines and line comments | |
rule wn() = quiet!{ (whitespace_char() / "\n" / inline_comment() / line_comment())* } | |
rule number() -> u32 | |
= quiet!{ | |
n:$(['0'..='9']+) { n.parse().unwrap() } | |
} / expected!("number") | |
pub rule list() -> Vec<u32> | |
= "[" wn() n:number() ** (wn() "," wn()) "]" { n } | |
} | |
} | |
pub fn run() { | |
if let Err(e) = execute() { | |
if let Some(parserator_err) = e.downcast_ref::<ParseratorError>() { | |
let peg_err = &parserator_err.error; | |
let msg = chic::Error::new("Parser error") | |
.error( | |
peg_err.location.line, | |
peg_err.location.offset + peg_err.location.line - 1, | |
peg_err.location.offset + peg_err.location.line, | |
&parserator_err.src, | |
format!("Expected: {}", peg_err.expected), | |
) | |
.to_string(); | |
eprintln!("{}", msg); | |
} | |
} | |
} | |
fn execute() -> anyhow::Result<()> { | |
dbg!(parse_list( | |
"[ 1, 3,4, 5, | |
6, | |
8, 9, 10, 7,10d]" | |
)?); | |
Ok(()) | |
} | |
fn parse_list(data: &str) -> anyhow::Result<Vec<u32>> { | |
Ok(list_parser::list(data).map_err(|e| ParseratorError::new(e, data))?) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use parserator; | |
fn main() { | |
parserator::run(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment