From 55e3d17f73b7ef22fa99a477fb9cd0ddf082708b Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Sat, 3 Jul 2021 20:25:50 +0200 Subject: [PATCH] add example --- Cargo.lock | 35 +++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + examples/errors.rs | 18 ++++++++++++++++++ src/config.rs | 4 +--- src/error.rs | 12 ++++++++++++ src/expr.rs | 2 +- src/lib.rs | 8 ++++---- src/parser.lalrpop | 16 ++++++++-------- 8 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 examples/errors.rs diff --git a/Cargo.lock b/Cargo.lock index b50e278..943b8e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,6 +93,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "console" version = "0.14.1" @@ -177,6 +187,7 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" name = "eww_config" version = "0.1.0" dependencies = [ + "codespan-reporting", "insta", "itertools", "lalrpop", @@ -525,6 +536,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + [[package]] name = "terminal_size" version = "0.1.17" @@ -564,6 +584,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + [[package]] name = "unicode-xid" version = "0.2.2" @@ -598,6 +624,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 650302b..449e909 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ regex = "1" itertools = "0.10" thiserror = "1.0" maplit = "1.0" +codespan-reporting = "0.11" [build-dependencies] lalrpop = "0.19.5" diff --git a/examples/errors.rs b/examples/errors.rs new file mode 100644 index 0000000..241ac3c --- /dev/null +++ b/examples/errors.rs @@ -0,0 +1,18 @@ +use eww_config::{config::*, error, expr::*, parser}; + +fn main() { + let parser = parser::ExprParser::new(); + let mut files = codespan_reporting::files::SimpleFiles::new(); + + let input = "(12 :bar 22 (foo) (baz))"; + + let file_id = files.add("foo.eww", input); + let ast = parser.parse(file_id, input).unwrap(); + let element: Result, _> = Element::from_expr(ast); + let err = element.unwrap_err(); + + let diag = err.pretty_diagnostic(&files); + use codespan_reporting::term; + let mut writer = term::termcolor::StandardStream::stderr(term::termcolor::ColorChoice::Always); + term::emit(&mut writer, &term::Config::default(), &files, &diag).unwrap(); +} diff --git a/src/config.rs b/src/config.rs index b3f687e..8e0c7c8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,8 +10,6 @@ use std::{ str::FromStr, }; -// https://michael-f-bryan.github.io/static-analyser-in-rust/book/codemap.html - type VarName = String; type AttrValue = String; type AttrName = String; @@ -59,7 +57,7 @@ mod test { let parser = parser::ExprParser::new(); insta::with_settings!({sort_maps => true}, { insta::assert_debug_snapshot!( - Element::::from_expr(parser.parse("(box :bar 12 :baz \"hi\" foo (bar))").unwrap()).unwrap() + Element::::from_expr(parser.parse(0, "(box :bar 12 :baz \"hi\" foo (bar))").unwrap()).unwrap() ); }); } diff --git a/src/error.rs b/src/error.rs index 82a722c..14cf169 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,5 @@ use crate::expr::{Expr, ExprType, Span}; +use codespan_reporting::{diagnostic, files}; use thiserror::Error; pub type AstResult = Result; @@ -13,6 +14,17 @@ pub enum AstError { WrongExprType(Option, ExprType, ExprType), } +impl AstError { + pub fn pretty_diagnostic(&self, files: &files::SimpleFiles<&str, &str>) -> diagnostic::Diagnostic { + let diag = diagnostic::Diagnostic::error().with_message(format!("{}", self)); + if let AstError::WrongExprType(Some(span), ..) = self { + diag.with_labels(vec![diagnostic::Label::primary(span.2, span.0..span.1)]) + } else { + diag + } + } +} + pub fn spanned(span: Span, err: impl Into) -> AstError { use AstError::*; match err.into() { diff --git a/src/expr.rs b/src/expr.rs index 97a0b92..8535642 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -5,7 +5,7 @@ use crate::{config::FromExpr, error::*}; use std::fmt::Display; #[derive(Eq, PartialEq, Clone, Copy)] -pub struct Span(pub usize, pub usize); +pub struct Span(pub usize, pub usize, pub usize); impl std::fmt::Display for Span { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/src/lib.rs b/src/lib.rs index 5135ce4..cdda0b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,9 @@ #![allow(unused)] #![feature(try_blocks)] -mod config; -mod error; -mod expr; +pub mod config; +pub mod error; +pub mod expr; use error::AstError; use std::{fmt::Display, ops::Deref}; @@ -17,7 +17,7 @@ lalrpop_mod!(pub parser); macro_rules! test_parser { ($p:expr, $($text:literal),*) => {{ - $(insta::assert_debug_snapshot!($p.parse($text));)* + $(insta::assert_debug_snapshot!($p.parse(0, $text));)* }} } diff --git a/src/parser.lalrpop b/src/parser.lalrpop index c306776..6268611 100644 --- a/src/parser.lalrpop +++ b/src/parser.lalrpop @@ -2,23 +2,23 @@ use std::str::FromStr; //use crate::lexer; use crate::expr::{Expr, Span}; -grammar; +grammar(file_id: usize); pub Expr: Expr = { - "(" )+> ")" => Expr::List(Span(l, r), elems), + "(" )+> ")" => Expr::List(Span(l, r, file_id), elems), - "{" )> <()>)*> "}" => Expr::Table(Span(l, r), elems), + "{" )> <()>)*> "}" => Expr::Table(Span(l, r, file_id), elems), => x, => x, - => Expr::Str(Span(l, r), x), - => Expr::Number(Span(l, r), x), - Comment => Expr::Comment(Span(l, r)), + => Expr::Str(Span(l, r, file_id), x), + => Expr::Number(Span(l, r, file_id), x), + Comment => Expr::Comment(Span(l, r, file_id)), }; -Keyword: Expr = => Expr::Keyword(Span(l, r), x.to_string()); -Symbol: Expr = /.*-+][^\s{}\(\)]*"> => Expr::Symbol(Span(l, r), x.to_string()); +Keyword: Expr = => Expr::Keyword(Span(l, r, file_id), x.to_string()); +Symbol: Expr = /.*-+][^\s{}\(\)]*"> => Expr::Symbol(Span(l, r, file_id), x.to_string()); StrLit: String = { => {