diff options
| author | bnewbold <bnewbold@robocracy.org> | 2016-11-29 23:13:19 -0800 | 
|---|---|---|
| committer | bnewbold <bnewbold@robocracy.org> | 2016-11-29 23:23:06 -0800 | 
| commit | a4e33306fffe87cada79c8ba47d4172d39f3fba5 (patch) | |
| tree | 82aaab103a35c306177fe4c5ba2dc63cdd48d03b /src | |
| parent | 2eb8e3e5e3d3df5ccaf5d92cb5b53cbf321688d1 (diff) | |
| download | modelthing-a4e33306fffe87cada79c8ba47d4172d39f3fba5.tar.gz modelthing-a4e33306fffe87cada79c8ba47d4172d39f3fba5.zip  | |
first pass at pretty-printing parser errors
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/mt-tool.rs | 2 | ||||
| -rw-r--r-- | src/lib.rs | 60 | 
2 files changed, 61 insertions, 1 deletions
diff --git a/src/bin/mt-tool.rs b/src/bin/mt-tool.rs index 03f590a..61db3fe 100644 --- a/src/bin/mt-tool.rs +++ b/src/bin/mt-tool.rs @@ -31,7 +31,7 @@ fn parse_modelica_files(paths: Vec<String>) {          match result {              Ok(_) => println!("Input `{}` ({}s): OK", input, elapsed), -            Err(err) => println!("Input `{}` ({}s): parse error {:?}", input, elapsed, err), +            Err(err) => println!("Input `{}` ({}sec): ERROR\n{}", input, elapsed, modelthing::pp_parseerror(&s, err)),          }      }  } @@ -3,6 +3,8 @@  extern crate log;  extern crate toml; +extern crate colored; +extern crate lalrpop_util;  pub mod modelica_parser;  pub mod modelica_ast; @@ -14,6 +16,9 @@ use std::fs;  use std::io::Read;  use std::fs::File; +use lalrpop_util::ParseError; +use colored::*; +  #[derive(Debug, PartialEq)]  pub struct ModelMetadata {      pub name_en: String, @@ -119,6 +124,61 @@ pub fn search_models(p: &Path) -> Vec<String> {      }  } +fn pp_segment(raw: &str, start: usize, end: usize) -> String { +    let mut line_start = 0; +    let mut num = 0; +    let mut ret = String::new(); +    for line in raw.lines() { +        num += 1; +        let line_end = line_start + line.len(); +        if (line_start <= start) && (start < line_end) { +            ret += &format!("    {}\n{:>3} {} {}{}{}\n    {} {}{}\n", +                "|".blue().bold(), +                num.to_string().blue().bold(), +                "|".blue().bold(), +                raw[line_start..start].normal(), +                raw[start..end].red().bold(), +                if end < line_end { +                    raw[end..line_end].normal() +                } else { +                    "".normal() +                }, +                "|".blue().bold(), +                std::iter::repeat(" ").take(start - line_start).collect::<String>(), +                std::iter::repeat("^").take(end - start).collect::<String>().red().bold()); +        } +        line_start += line.len() + 1; +        if line_start > end { break }; +    } +    ret +} + +pub fn pp_parseerror(raw: &str, pe: ParseError<usize, (usize, &str), ()>) -> String { +    match pe { +        ParseError::InvalidToken{location} => { +            format!("{} invalid token starting at:\n{}", +                "parse error:".red().bold(), +                pp_segment(raw, location, location+1)) }, +        ParseError::UnrecognizedToken{token: Some((start, (_, tok), end)), expected} => { +            format!("{} unrecognized token '{}' (expected one of {:?}):\n{}", +                "parse error:".red().bold(), +                tok, +                expected, +                pp_segment(raw, start, end)) }, +        ParseError::UnrecognizedToken{token: None, expected} => { +            format!("{} premature end-of-file (expected one of {:?})", +                "parse error:".red().bold(), +                expected) }, +        ParseError::ExtraToken{token: (start, (_, tok), end)} => { +            format!("{} unexpected extra token '{}':\n{}", +                "parse error:".red().bold(), +                tok, +                pp_segment(raw, start, end)) }, +        _ => { +            format!("{} {:?}", "parse error:".red().bold(), pe) }, +    } +} +  /* ******************************** Tests ******************************* */  #[test]  | 
