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
mod ast;
mod io;
mod lexer;
mod parser;
mod render;
mod sexpr;
mod toplevel;
mod validate;
pub use ast::{
AliasDatatype, BuiltinType, Datatype, DatatypeIdent, DatatypeVariant, Definition, Document,
Entry, EnumDatatype, FlagsDatatype, Id, IntRepr, InterfaceFunc, InterfaceFuncParam, Module,
ModuleDefinition, ModuleEntry, ModuleImport, ModuleImportVariant, StructDatatype, StructMember,
UnionDatatype, UnionVariant,
};
pub use io::{Filesystem, MockFs, WitxIo};
pub use lexer::LexError;
pub use parser::{DeclSyntax, ParseError};
pub use render::{Render, SExpr as RenderSExpr};
pub use sexpr::SExprParseError;
pub use validate::ValidationError;
use failure::Fail;
use std::path::{Path, PathBuf};
pub fn load<P: AsRef<Path>>(path: P) -> Result<Document, WitxError> {
use toplevel::parse_witx;
use validate::validate_document;
let parsed_decls = parse_witx(path)?;
validate_document(&parsed_decls).map_err(WitxError::Validation)
}
pub fn parse(source: &str) -> Result<Document, WitxError> {
use toplevel::parse_witx_with;
use validate::validate_document;
let mockfs = MockFs::new(&[("-", source)]);
let parsed_decls = parse_witx_with(Path::new("-"), &mockfs)?;
validate_document(&parsed_decls).map_err(WitxError::Validation)
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Location {
pub path: PathBuf,
pub line: usize,
pub column: usize,
}
#[derive(Debug, Fail)]
pub enum WitxError {
#[fail(display = "{}", _0)]
SExpr(#[cause] SExprParseError),
#[fail(display = "with file {:?}: {}", _0, _1)]
Io(PathBuf, #[cause] ::std::io::Error),
#[fail(display = "{}", _0)]
Parse(#[cause] ParseError),
#[fail(display = "{}", _0)]
Validation(#[cause] ValidationError),
}
impl WitxError {
pub fn report_with(&self, witxio: &dyn WitxIo) -> String {
use WitxError::*;
match self {
SExpr(sexpr) => sexpr.report_with(witxio),
Io(path, ioerr) => format!("with file {:?}: {}", path, ioerr),
Parse(parse) => parse.report_with(witxio),
Validation(validation) => validation.report_with(witxio),
}
}
pub fn report(&self) -> String {
self.report_with(&Filesystem)
}
}
impl Location {
pub fn highlight_source_with(&self, witxio: &dyn WitxIo) -> String {
let mut msg = format!("in {:?}:\n", self.path);
if let Ok(src_line) = witxio.fget_line(&self.path, self.line) {
msg += &format!(
"{line_num: >5} | {src_line}\n{blank: >5} {caret: >column$}",
line_num = self.line,
src_line = src_line,
blank = " ",
caret = "^",
column = self.column,
);
}
msg
}
pub fn highlight_source(&self) -> String {
self.highlight_source_with(&Filesystem)
}
}