aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2016-11-29 23:13:19 -0800
committerbnewbold <bnewbold@robocracy.org>2016-11-29 23:23:06 -0800
commita4e33306fffe87cada79c8ba47d4172d39f3fba5 (patch)
tree82aaab103a35c306177fe4c5ba2dc63cdd48d03b
parent2eb8e3e5e3d3df5ccaf5d92cb5b53cbf321688d1 (diff)
downloadmodelthing-a4e33306fffe87cada79c8ba47d4172d39f3fba5.tar.gz
modelthing-a4e33306fffe87cada79c8ba47d4172d39f3fba5.zip
first pass at pretty-printing parser errors
-rw-r--r--Cargo.lock10
-rw-r--r--Cargo.toml6
-rw-r--r--src/bin/mt-tool.rs2
-rw-r--r--src/lib.rs60
4 files changed, 77 insertions, 1 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d78a4ff..14c1291 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,7 @@
name = "modelthing"
version = "0.1.0"
dependencies = [
+ "colored 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"docopt 0.6.86 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -61,6 +62,14 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "colored"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "cookie"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -774,6 +783,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum buf-read-ext 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc384072fac32fb50f4a327c33e2004897d11c561d008dd6031fb7f19b04de2c"
+"checksum colored 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "585756a5d597a0ecdf9c963be84c6eb0e25a3590b535ac6f27e98254266b4f4c"
"checksum cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e3d6405328b6edb412158b3b7710e2634e23f3614b9bb1c412df7952489a626"
"checksum diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e48977eec6d3b7707462c2dc2e1363ad91b5dd822cf942537ccdc2085dc87587"
"checksum difference 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ffef4c144e881a906ed5bd6e1e749dc1955cd3f0c7969d3d34122a971981c5ea"
diff --git a/Cargo.toml b/Cargo.toml
index 3266ce5..57aa54b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,6 +14,7 @@ log = "0.3"
env_logger = "0.3"
lalrpop-util = "^0.12.4"
markdown = "0.1"
+colored = "1.3"
# parser util
rustc-serialize = "0.3"
@@ -21,3 +22,8 @@ docopt = "0.6"
# webface
pencil = "0.3"
+
+
+[features]
+# this effectively enables the feature `no-color` of colored when testing
+test = ["colored/no-color"]
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)),
}
}
}
diff --git a/src/lib.rs b/src/lib.rs
index c733dc7..3f6021d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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]