diff --git a/Cargo.lock b/Cargo.lock index f207f14..32f8483 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,16 +68,6 @@ dependencies = [ "vec_map", ] -[[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 = "heck" version = "0.3.3" @@ -210,15 +200,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - [[package]] name = "textwrap" version = "0.11.0" @@ -265,7 +246,6 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", - "codespan-reporting", "structopt", "thiserror", ] @@ -322,15 +302,6 @@ 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 d11ccd7..840471d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,5 @@ edition = "2018" [dependencies] anyhow = "1.0.45" chrono = "0.4.19" -codespan-reporting = "0.11.1" structopt = "0.3.25" thiserror = "1.0.30" diff --git a/src/main.rs b/src/main.rs index 4ac6e0a..887b3bc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,8 @@ use std::path::PathBuf; -use std::process; use structopt::StructOpt; -use crate::parse::Parser; -use crate::source::SourceFiles; - mod commands; -mod parse; -mod source; #[derive(Debug, StructOpt)] pub struct Opt { @@ -18,26 +12,5 @@ pub struct Opt { fn main() { let opt = Opt::from_args(); - - let mut files = SourceFiles::new(); - - let (file, content) = match files.load(&opt.file) { - Ok(result) => result, - Err(e) => { - eprintln!("Failed to load file: {}", e); - process::exit(1); - } - }; - - let mut parser = Parser::new(file, content); - - let commands = match parser.parse(parse::parse_commands) { - Ok(result) => result, - Err(es) => { - files.emit_all(&es); - process::exit(1); - } - }; - - println!("{:#?}", commands); + println!("{:#?}", opt); } diff --git a/src/parse.rs b/src/parse.rs deleted file mode 100644 index 1d571b0..0000000 --- a/src/parse.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod commands; -mod parser; - -pub use commands::parse as parse_commands; -pub use parser::{ParseError, ParseResult, Parser}; diff --git a/src/parse/commands.rs b/src/parse/commands.rs deleted file mode 100644 index 0ed21df..0000000 --- a/src/parse/commands.rs +++ /dev/null @@ -1,34 +0,0 @@ -use crate::commands::Command; - -use super::{ParseResult, Parser}; - -pub fn parse(p: &mut Parser<'_>) -> ParseResult> { - let mut commands = vec![]; - - skip_empty_lines(p); - while !p.at_eof() { - // Commands consume all their trailing lines, including empty ones - commands.push(parse_command(p)?); - } - - Ok(commands) -} - -fn skip_empty_lines(p: &mut Parser<'_>) { - while p.peek_line().chars().all(|c| c.is_whitespace()) { - p.take_line(); - } -} - -fn parse_command(p: &mut Parser<'_>) -> ParseResult { - let rest = p.peek_rest(); - if rest.starts_with("TASK") { - todo!() // TODO Implement parsing TASK command - } else if rest.starts_with("NOTE") { - todo!() // TODO Implement parsing NOTE command - } else if rest.starts_with("BIRTHDAY") { - todo!() // TODO Implement parsing BIRTHDAY command - } else { - p.critical(p.at(), "Expected command") - } -} diff --git a/src/parse/parser.rs b/src/parse/parser.rs deleted file mode 100644 index 87f5f2f..0000000 --- a/src/parse/parser.rs +++ /dev/null @@ -1,107 +0,0 @@ -use std::cmp::min; - -use codespan_reporting::diagnostic::{Diagnostic, Label}; - -use crate::source::{SourceFile, SourceSpan}; - -// TODO Add warnings for things like trailing whitespace - -#[derive(Debug)] -pub struct ParseError(SourceSpan, String); - -impl From<&ParseError> for Diagnostic { - fn from(e: &ParseError) -> Self { - Self::error() - .with_message(&e.1) - .with_labels(vec![Label::primary(e.0.file_id(), e.0.range())]) - } -} - -pub type ParseResult = Result; - -#[derive(Debug)] -pub struct Parser<'a> { - file: SourceFile, - content: &'a str, - offset: usize, - errors: Vec, -} - -impl<'a> Parser<'a> { - pub fn new(file: SourceFile, content: &'a str) -> Self { - Self { - file, - content, - offset: 0, - errors: vec![], - } - } - - pub fn peek(&self, amount: usize) -> &'a str { - // self.offset is always a valid start since take() ensures it is in the - // range 0..self.content.len() - let end = min(self.content.len(), self.offset + amount); - &self.content[self.offset..end] - } - - pub fn peek_rest(&self) -> &'a str { - // self.offset is always a valid start since take() ensures it is in the - // range 0..self.content.len() - &self.content[self.offset..] - } - - pub fn peek_line(&self) -> &'a str { - if let Some(i) = self.peek_rest().find('\n') { - self.peek(i) - } else { - self.peek_rest() - } - } - - pub fn at(&self) -> usize { - self.offset - } - - pub fn at_eof(&self) -> bool { - self.offset >= self.content.len() - } - - pub fn take(&mut self, amount: usize) { - // Ensure the offset always stays in the range 0..self.content.len() - self.offset = min(self.content.len(), self.offset + amount); - } - - pub fn take_line(&mut self) { - self.take(self.peek_line().len() + 1); - } - - fn error(&self, at: usize, error: impl ToString) -> ParseError { - ParseError(self.file.span(at..at), error.to_string()) - } - - pub fn uncritical(&mut self, at: usize, error: impl ToString) { - self.errors.push(self.error(at, error)); - } - - pub fn critical(&self, at: usize, error: impl ToString) -> ParseResult { - Err(self.error(at, error)) - } - - pub fn parse( - &mut self, - f: impl FnOnce(&mut Self) -> ParseResult, - ) -> Result> { - match f(self) { - Ok(result) => { - if self.errors.is_empty() { - return Ok(result); - } - } - Err(error) => { - self.errors.push(error); - } - }; - - Err(self.errors.split_off(0)) - } -} diff --git a/src/source.rs b/src/source.rs deleted file mode 100644 index 407c7d6..0000000 --- a/src/source.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::collections::HashMap; -use std::ops::Range; -use std::path::{Path, PathBuf}; -use std::{fs, io}; - -use codespan_reporting::diagnostic::Diagnostic; -use codespan_reporting::files::SimpleFiles; -use codespan_reporting::term; -use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; - -#[derive(Debug)] -pub struct SourceFiles { - files: SimpleFiles, - files_by_path: HashMap, -} - -impl SourceFiles { - pub fn new() -> Self { - Self { - files: SimpleFiles::new(), - files_by_path: HashMap::new(), - } - } - - pub fn load(&mut self, path: &Path) -> io::Result<(SourceFile, &str)> { - let canonical_path = path.canonicalize()?; - let file_id = if let Some(&file_id) = self.files_by_path.get(&canonical_path) { - file_id - } else { - let name = path.as_os_str().to_string_lossy().into_owned(); - let content = fs::read_to_string(path)?; - self.files.add(name, content) - }; - - let content = self.files.get(file_id).unwrap().source() as &str; - Ok((SourceFile(file_id), content)) - } - - pub fn emit_all<'a, T>(&self, diagnostics: &'a [T]) - where - &'a T: Into>, - { - let stderr = StandardStream::stderr(ColorChoice::Auto); - let config = term::Config::default(); - - for diagnostic in diagnostics { - let diagnostic: Diagnostic = diagnostic.into(); - term::emit(&mut stderr.lock(), &config, &self.files, &diagnostic) - .expect("failed to print errors"); - } - } -} - -#[derive(Clone, Copy, Debug)] -pub struct SourceFile(usize); - -impl SourceFile { - pub fn span(&self, range: Range) -> SourceSpan { - SourceSpan { - file_id: self.0, - start: range.start, - end: range.end, - } - } -} - -#[derive(Clone, Copy, Debug)] -pub struct SourceSpan { - file_id: usize, - start: usize, - end: usize, -} - -impl SourceSpan { - pub fn file_id(&self) -> usize { - self.file_id - } - - pub fn range(&self) -> Range { - self.start..self.end - } -}