1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
#![feature(box_syntax, specialization, raw, int_error_matching, concat_idents)] #[macro_use] extern crate kg_display_derive; #[macro_use] extern crate serde_derive; pub use self::detail::{Detail, Severity, DetailExt}; pub use self::diag::{BasicDiag, Diag, ParseDiag, SimpleDiag}; pub use self::io::{ ByteReader, CharReader, FileBuffer, FileType, IoErrorDetail, IoResult, LexTerm, LexToken, MemByteReader, MemCharReader, OpType, Position, Quote, Reader, Span, }; pub use self::multi::{Diags, Errors}; pub use self::stacktrace::Stacktrace; mod detail; mod diag; pub mod io; pub mod parse; mod multi; mod stacktrace; #[macro_export] macro_rules! basic_diag { ($kind: expr) => {{ $crate::BasicDiag::from($kind) }}; ($logger: expr, $kind: expr) => {{ let e = $crate::BasicDiag::from($kind); slog_debug!($logger, "diagnostic created:\n{}", e); e }}; } #[macro_export] macro_rules! parse_diag { ($kind: expr) => {{ $crate::ParseDiag::from($kind) }}; ($kind: expr, $reader: expr, { $($p1: expr, $p2: expr => $msg: expr),+ $(,)* }) => {{ let mut e = $crate::ParseDiag::from($kind); $( e.add_quote($reader.quote($p1, $p2, 2, 2, $msg.into())); )+ e }}; ($logger: expr, $kind: expr) => {{ let e = $crate::ParseDiag::from($kind); slog_debug!("parse diagnostic created:\n{}", e); e }}; ($logger: expr, $kind: expr, $reader: expr, { $($p1: expr, $p2: expr => $msg: expr),+ $(,)* }) => {{ let mut e = $crate::ParseDiag::from($kind); $( e.add_quote($reader.quote($p1, $p2, 2, 2, $msg.into())); )+ slog_debug!("parse diagnostic created:\n{}", e); e }}; } pub trait IntoDiagRes<T> { fn into_diag_res(self) -> Result<T, BasicDiag>; } impl<T, E: Detail> IntoDiagRes<T> for Result<T, E> { fn into_diag_res(self) -> Result<T, BasicDiag> { self.map_err(|detail| BasicDiag::from(detail)) } } pub trait DiagResultExt<T> { fn map_err_as_cause<D: Detail,O: FnOnce() -> D>(self, op: O) -> Result<T, BasicDiag>; } impl<T, E: Diag> DiagResultExt<T> for Result<T, E> { fn map_err_as_cause<D: Detail, O: FnOnce() -> D>(self, op: O) -> Result<T, BasicDiag> { match self { Ok(t) => Ok(t), Err(e) => { Err(BasicDiag::with_cause(op(), e)) } } } } #[cfg(test)] mod tests { use super::*; #[test] fn detail_debug() { #[derive(Debug)] struct InvalidToken { expected: &'static [&'static str], found: String, } impl Detail for InvalidToken { fn severity(&self) -> Severity { Severity::Error } fn code(&self) -> u32 { 101 } } impl std::fmt::Display for InvalidToken { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, "invalid token '{}', expected one of {:?}", self.found, self.expected ) } } let err: ParseDiag = InvalidToken { expected: &["id", "num", "+", "-"], found: "*".into(), } .into(); println!("{:#?}", err); println!("{}", err); } }