add example

This commit is contained in:
elkowar 2021-07-03 20:25:50 +02:00
parent af19291bf9
commit 55e3d17f73
No known key found for this signature in database
GPG Key ID: E321AD71B1D1F27F
8 changed files with 80 additions and 16 deletions

35
Cargo.lock generated
View File

@ -93,6 +93,16 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 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]] [[package]]
name = "console" name = "console"
version = "0.14.1" version = "0.14.1"
@ -177,6 +187,7 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
name = "eww_config" name = "eww_config"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"codespan-reporting",
"insta", "insta",
"itertools", "itertools",
"lalrpop", "lalrpop",
@ -525,6 +536,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "terminal_size" name = "terminal_size"
version = "0.1.17" version = "0.1.17"
@ -564,6 +584,12 @@ dependencies = [
"crunchy", "crunchy",
] ]
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.2" version = "0.2.2"
@ -598,6 +624,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 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]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"

View File

@ -14,6 +14,7 @@ regex = "1"
itertools = "0.10" itertools = "0.10"
thiserror = "1.0" thiserror = "1.0"
maplit = "1.0" maplit = "1.0"
codespan-reporting = "0.11"
[build-dependencies] [build-dependencies]
lalrpop = "0.19.5" lalrpop = "0.19.5"

18
examples/errors.rs Normal file
View File

@ -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<Expr, Expr>, _> = 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();
}

View File

@ -10,8 +10,6 @@ use std::{
str::FromStr, str::FromStr,
}; };
// https://michael-f-bryan.github.io/static-analyser-in-rust/book/codemap.html
type VarName = String; type VarName = String;
type AttrValue = String; type AttrValue = String;
type AttrName = String; type AttrName = String;
@ -59,7 +57,7 @@ mod test {
let parser = parser::ExprParser::new(); let parser = parser::ExprParser::new();
insta::with_settings!({sort_maps => true}, { insta::with_settings!({sort_maps => true}, {
insta::assert_debug_snapshot!( insta::assert_debug_snapshot!(
Element::<Expr, Expr>::from_expr(parser.parse("(box :bar 12 :baz \"hi\" foo (bar))").unwrap()).unwrap() Element::<Expr, Expr>::from_expr(parser.parse(0, "(box :bar 12 :baz \"hi\" foo (bar))").unwrap()).unwrap()
); );
}); });
} }

View File

@ -1,4 +1,5 @@
use crate::expr::{Expr, ExprType, Span}; use crate::expr::{Expr, ExprType, Span};
use codespan_reporting::{diagnostic, files};
use thiserror::Error; use thiserror::Error;
pub type AstResult<T> = Result<T, AstError>; pub type AstResult<T> = Result<T, AstError>;
@ -13,6 +14,17 @@ pub enum AstError {
WrongExprType(Option<Span>, ExprType, ExprType), WrongExprType(Option<Span>, ExprType, ExprType),
} }
impl AstError {
pub fn pretty_diagnostic(&self, files: &files::SimpleFiles<&str, &str>) -> diagnostic::Diagnostic<usize> {
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>) -> AstError { pub fn spanned(span: Span, err: impl Into<AstError>) -> AstError {
use AstError::*; use AstError::*;
match err.into() { match err.into() {

View File

@ -5,7 +5,7 @@ use crate::{config::FromExpr, error::*};
use std::fmt::Display; use std::fmt::Display;
#[derive(Eq, PartialEq, Clone, Copy)] #[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 { impl std::fmt::Display for Span {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

View File

@ -2,9 +2,9 @@
#![allow(unused)] #![allow(unused)]
#![feature(try_blocks)] #![feature(try_blocks)]
mod config; pub mod config;
mod error; pub mod error;
mod expr; pub mod expr;
use error::AstError; use error::AstError;
use std::{fmt::Display, ops::Deref}; use std::{fmt::Display, ops::Deref};
@ -17,7 +17,7 @@ lalrpop_mod!(pub parser);
macro_rules! test_parser { macro_rules! test_parser {
($p:expr, $($text:literal),*) => {{ ($p:expr, $($text:literal),*) => {{
$(insta::assert_debug_snapshot!($p.parse($text));)* $(insta::assert_debug_snapshot!($p.parse(0, $text));)*
}} }}
} }

View File

@ -2,23 +2,23 @@ use std::str::FromStr;
//use crate::lexer; //use crate::lexer;
use crate::expr::{Expr, Span}; use crate::expr::{Expr, Span};
grammar; grammar(file_id: usize);
pub Expr: Expr = { pub Expr: Expr = {
<l:@L> "(" <elems:(<Expr>)+> ")" <r:@R> => Expr::List(Span(l, r), elems), <l:@L> "(" <elems:(<Expr>)+> ")" <r:@R> => Expr::List(Span(l, r, file_id), elems),
<l:@L> "{" <elems:(<(<Expr>)> <(<Expr>)>)*> "}" <r:@R> => Expr::Table(Span(l, r), elems), <l:@L> "{" <elems:(<(<Expr>)> <(<Expr>)>)*> "}" <r:@R> => Expr::Table(Span(l, r, file_id), elems),
<x:Keyword> => x, <x:Keyword> => x,
<x:Symbol> => x, <x:Symbol> => x,
<l:@L> <x:StrLit> <r:@R> => Expr::Str(Span(l, r), x), <l:@L> <x:StrLit> <r:@R> => Expr::Str(Span(l, r, file_id), x),
<l:@L> <x:Num> <r:@R> => Expr::Number(Span(l, r), x), <l:@L> <x:Num> <r:@R> => Expr::Number(Span(l, r, file_id), x),
<l:@L> Comment <r:@R> => Expr::Comment(Span(l, r)), <l:@L> Comment <r:@R> => Expr::Comment(Span(l, r, file_id)),
}; };
Keyword: Expr = <l:@L> <x:r":[^\s]+"> <r:@R> => Expr::Keyword(Span(l, r), x.to_string()); Keyword: Expr = <l:@L> <x:r":[^\s]+"> <r:@R> => Expr::Keyword(Span(l, r, file_id), x.to_string());
Symbol: Expr = <l:@L> <x:r"[a-zA-Z_!\?<>/.*-+][^\s{}\(\)]*"> <r:@R> => Expr::Symbol(Span(l, r), x.to_string()); Symbol: Expr = <l:@L> <x:r"[a-zA-Z_!\?<>/.*-+][^\s{}\(\)]*"> <r:@R> => Expr::Symbol(Span(l, r, file_id), x.to_string());
StrLit: String = { StrLit: String = {
<x:r#""(?:[^"\\]|\\.)*""#> => { <x:r#""(?:[^"\\]|\\.)*""#> => {