Skip to content

Commit

Permalink
pretty error (#3)
Browse files Browse the repository at this point in the history
Co-authored-by: chenyan-dfinity <[email protected]>
  • Loading branch information
chenyan2002 and chenyan-dfinity authored Apr 26, 2021
1 parent 979765c commit 1c46d16
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 3 deletions.
14 changes: 13 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ candid = { git = "https://github.com/dfinity/candid.git", branch = "fix-beta", f
rustyline = "8.0"
rustyline-derive = "0.4"
ansi_term = "0.12"
codespan-reporting = "0.11"
pretty = "0.10.0"
ic-agent = { git = "https://github.com/dfinity/agent-rs.git", branch = "yan/test" }
tokio = { version = "1.5.0", features = ["full"] }
delay = "0.3.1"
Expand Down
3 changes: 2 additions & 1 deletion src/command.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::error::pretty_parse;
use super::helper::{MyHelper, NameEnv};
use super::token::{ParserError, Spanned, Tokenizer};
use anyhow::{anyhow, Context};
Expand Down Expand Up @@ -176,7 +177,7 @@ impl Command {
let line_end = script.find('\n').unwrap_or(0);
script.drain(..line_end);
}
let cmds = script.parse::<Commands>()?;
let cmds = pretty_parse::<Commands>(&file, &script)?;
helper.base_path = path.parent().unwrap().to_path_buf();
for cmd in cmds.0.iter() {
println!("> {:?}", cmd);
Expand Down
56 changes: 56 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use crate::token::ParserError;
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFile;
use codespan_reporting::term::{self, termcolor::StandardStream};

fn report(e: &ParserError) -> Diagnostic<()> {
use lalrpop_util::ParseError::*;
let mut diag = Diagnostic::error().with_message("parser error");
let label = match e {
User { error } => Label::primary((), error.span.clone()).with_message(&error.err),
InvalidToken { location } => {
Label::primary((), *location..location + 1).with_message("Invalid token")
}
UnrecognizedEOF { location, expected } => {
diag = diag.with_notes(report_expected(&expected));
Label::primary((), *location..location + 1).with_message("Unexpected EOF")
}
UnrecognizedToken { token, expected } => {
diag = diag.with_notes(report_expected(&expected));
Label::primary((), token.0..token.2).with_message("Unexpected token")
}
ExtraToken { token } => Label::primary((), token.0..token.2).with_message("Extra token"),
};
diag.with_labels(vec![label])
}

fn report_expected(expected: &[String]) -> Vec<String> {
if expected.is_empty() {
return Vec::new();
}
use pretty::RcDoc;
let doc: RcDoc<()> = RcDoc::intersperse(
expected.iter().map(RcDoc::text),
RcDoc::text(",").append(RcDoc::softline()),
);
let header = if expected.len() == 1 {
"Expects"
} else {
"Expects one of"
};
let doc = RcDoc::text(header).append(RcDoc::softline().append(doc));
vec![doc.pretty(70).to_string()]
}

pub fn pretty_parse<T>(name: &str, str: &str) -> Result<T, ParserError>
where
T: std::str::FromStr<Err = ParserError>,
{
str.parse::<T>().map_err(|e| {
let writer = StandardStream::stderr(term::termcolor::ColorChoice::Auto);
let config = term::Config::default();
let file = SimpleFile::new(name, str);
term::emit(&mut writer.lock(), &config, &file, &report(&e)).unwrap();
e
})
}
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ use rustyline::CompletionType;
use tokio::runtime::Runtime;

mod command;
mod error;
mod grammar;
mod helper;
mod token;
use crate::command::Command;
use crate::error::pretty_parse;
use crate::helper::MyHelper;

fn unwrap<T, E, F>(v: Result<T, E>, f: F)
Expand Down Expand Up @@ -69,7 +71,7 @@ fn repl(opts: Opts) -> anyhow::Result<()> {
match input {
Ok(line) => {
rl.add_history_entry(&line);
unwrap(line.parse::<Command>(), |cmd| {
unwrap(pretty_parse::<Command>("stdin", &line), |cmd| {
let mut helper = rl.helper_mut().unwrap();
helper.history.push(line.clone());
unwrap(cmd.run(&mut helper), |_| {});
Expand Down

0 comments on commit 1c46d16

Please sign in to comment.