cl-ast: Add filename to File
- Better error reporting - Better pizza - Papa Cow's
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
|
||||
use cl_ast::Expr;
|
||||
use cl_ast::{Expr, Sym};
|
||||
use cl_lexer::error::{Error as LexError, Reason};
|
||||
use std::fmt::Display;
|
||||
pub type PResult<T> = Result<T, Error>;
|
||||
@@ -8,6 +8,7 @@ pub type PResult<T> = Result<T, Error>;
|
||||
/// Contains information about [Parser] errors
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Error {
|
||||
pub in_file: Sym,
|
||||
pub reason: ErrorKind,
|
||||
pub while_parsing: Parsing,
|
||||
pub loc: Loc,
|
||||
@@ -129,13 +130,18 @@ pub enum Parsing {
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { reason, while_parsing, loc } = self;
|
||||
let Self { in_file, reason, while_parsing, loc } = self;
|
||||
match reason {
|
||||
// TODO entries are debug-printed
|
||||
ErrorKind::Todo(_) => write!(f, "{loc} {reason} {while_parsing:?}"),
|
||||
ErrorKind::Todo(_) => write!(f, "{in_file}:{loc} {reason} {while_parsing:?}"),
|
||||
// lexical errors print their own higher-resolution loc info
|
||||
ErrorKind::Lexical(e) => write!(f, "{e} (while parsing {while_parsing})"),
|
||||
_ => write!(f, "{loc}: {reason} while parsing {while_parsing}"),
|
||||
_ => {
|
||||
if !in_file.is_empty() {
|
||||
write!(f, "{in_file}:")?
|
||||
}
|
||||
write!(f, "{loc}: {reason} while parsing {while_parsing}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,25 +76,29 @@ impl Fold for ModuleInliner {
|
||||
impl ModuleInliner {
|
||||
/// Attempts to read and parse a file for every module in the tree
|
||||
fn fold_module_kind(&mut self, m: Option<File>) -> Option<File> {
|
||||
use std::borrow::Cow;
|
||||
if let Some(f) = m {
|
||||
return Some(self.fold_file(f));
|
||||
}
|
||||
|
||||
// cd path/mod.cl
|
||||
self.path.set_extension("cl");
|
||||
let mut used_path: Cow<Path> = Cow::Borrowed(&self.path);
|
||||
|
||||
let file = match std::fs::read_to_string(&self.path) {
|
||||
Err(error) => {
|
||||
let Some(basename) = self.path.file_name() else {
|
||||
return self.handle_io_error(error);
|
||||
};
|
||||
let path = self
|
||||
.path
|
||||
.parent()
|
||||
.and_then(Path::parent)
|
||||
.map(|path| path.join(basename))
|
||||
.unwrap_or_default();
|
||||
used_path = Cow::Owned(
|
||||
self.path
|
||||
.parent()
|
||||
.and_then(Path::parent)
|
||||
.map(|path| path.join(basename))
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
|
||||
match std::fs::read_to_string(&path) {
|
||||
match std::fs::read_to_string(&used_path) {
|
||||
Err(error) => return self.handle_io_error(error),
|
||||
Ok(file) => file,
|
||||
}
|
||||
@@ -102,7 +106,7 @@ impl ModuleInliner {
|
||||
Ok(file) => file,
|
||||
};
|
||||
|
||||
match Parser::new(Lexer::new(&file)).parse() {
|
||||
match Parser::new(used_path.display().to_string(), Lexer::new(&file)).parse() {
|
||||
Err(e) => self.handle_parse_error(e),
|
||||
Ok(file) => {
|
||||
self.path.set_extension("");
|
||||
|
||||
@@ -13,6 +13,8 @@ mod prec;
|
||||
/// Parses a sequence of [Tokens](Token) into an [AST](cl_ast)
|
||||
#[derive(Debug)]
|
||||
pub struct Parser<'t> {
|
||||
/// Name of the file being parsed
|
||||
file: Sym,
|
||||
/// Lazy tokenizer
|
||||
lexer: Lexer<'t>,
|
||||
/// Look-ahead buffer
|
||||
@@ -23,8 +25,8 @@ pub struct Parser<'t> {
|
||||
|
||||
/// Basic parser functionality
|
||||
impl<'t> Parser<'t> {
|
||||
pub fn new(lexer: Lexer<'t>) -> Self {
|
||||
Self { loc: Loc::from(&lexer), lexer, next: None }
|
||||
pub fn new(filename: impl AsRef<str>, lexer: Lexer<'t>) -> Self {
|
||||
Self { file: filename.as_ref().into(), loc: Loc::from(&lexer), lexer, next: None }
|
||||
}
|
||||
|
||||
/// Gets the location of the last consumed [Token]
|
||||
@@ -40,7 +42,7 @@ impl<'t> Parser<'t> {
|
||||
|
||||
/// Constructs an [Error]
|
||||
pub fn error(&self, reason: ErrorKind, while_parsing: Parsing) -> Error {
|
||||
Error { reason, while_parsing, loc: self.loc }
|
||||
Error { in_file: self.file, reason, while_parsing, loc: self.loc }
|
||||
}
|
||||
|
||||
/// Internal impl of peek and consume
|
||||
@@ -262,7 +264,7 @@ impl Parse<'_> for File {
|
||||
} {
|
||||
items.push(Item::parse(p)?)
|
||||
}
|
||||
Ok(File { items })
|
||||
Ok(File { name: p.file.to_ref(), items })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,6 +636,7 @@ impl Parse<'_> for ImplKind {
|
||||
Ok(ImplKind::Trait { impl_trait, for_type: Ty::parse(p)?.into() })
|
||||
} else {
|
||||
Err(Error {
|
||||
in_file: p.file,
|
||||
reason: ExpectedParsing { want: Parsing::Path },
|
||||
while_parsing: P,
|
||||
loc: target.span.head,
|
||||
|
||||
Reference in New Issue
Block a user