diff --git a/Cargo.lock b/Cargo.lock index d3e1fa3..e3eb7fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,6 +55,7 @@ dependencies = [ name = "kabel" version = "0.1.0" dependencies = [ + "colored", "is-terminal", "libkabel", "tracing-subscriber", diff --git a/examples/try.kab b/examples/try.kab index b208a54..4185f53 100644 --- a/examples/try.kab +++ b/examples/try.kab @@ -4,108 +4,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"aaaaaa \ No newline at end of file +"aaaaaa diff --git a/kabel/Cargo.toml b/kabel/Cargo.toml index 9cfbb8f..16522a6 100644 --- a/kabel/Cargo.toml +++ b/kabel/Cargo.toml @@ -10,4 +10,5 @@ description = "A dead-simple scripting language for use in games" [dependencies] libkabel = { version = "0.1", path = "../libkabel", features = ["pretty-emitter"] } is-terminal = "0.4" -tracing-subscriber = "0.3" \ No newline at end of file +tracing-subscriber = "0.3" +colored = "2" diff --git a/kabel/src/main.rs b/kabel/src/main.rs index 150b40e..f56a743 100644 --- a/kabel/src/main.rs +++ b/kabel/src/main.rs @@ -5,6 +5,7 @@ use std::io::{self, Read}; use libkabel::diagnostics::emitters::Emitter; use libkabel::error::KError; use libkabel::lexer::token::Token; +use colored::Colorize; fn main() -> Result<(), Box> { let argv: Vec = env::args().collect(); @@ -19,7 +20,7 @@ fn main() -> Result<(), Box> { } Err(e) => { eprintln!( - "Error: Tried opening `{}' and got unexpected error: {}", + "error: Tried opening file `{}' and got unexpected error: {}", argv[1], e.kind() ); @@ -38,7 +39,14 @@ fn main() -> Result<(), Box> { Err(e) => { match e { KError::InternalError(e) => { - eprintln!("ICE! Please report this to the kabel developers, along with what you were doing: {:?}", e); + eprintln!("{} {}", + "error: Internal Kabel error!".red(), + "THIS IS NOT YOUR FAULT.".bold().red()); + eprintln!("{}", "error: Please report this error to the kabel developers along with your".red()); + eprintln!("{}", "fail: program's complete source code. Either"); + eprintln!("{}", "fail: - Open an Issue at https://git.e3t.cc/tm85/kabel, or".red()); + eprintln!("{}", "fail: - E-Mail the developers at kabel@e3t.cc".red()); + eprintln!("{} {:?}", "fail: Error message follows:".red(), e); } KError::UserError(diags) => { //eprintln!("{}", libkabel::diagnostics::emitters::basic::BasicEmitter::emit(diags, text_source)); diff --git a/libkabel/src/diagnostics/emitters/mod.rs b/libkabel/src/diagnostics/emitters/mod.rs index a2d056e..41c7463 100644 --- a/libkabel/src/diagnostics/emitters/mod.rs +++ b/libkabel/src/diagnostics/emitters/mod.rs @@ -8,4 +8,4 @@ pub(crate) mod util; pub trait Emitter { type Output; fn emit(diag: Vec, source: String, source_name: String) -> Self::Output; -} \ No newline at end of file +} diff --git a/libkabel/src/diagnostics/emitters/pretty.rs b/libkabel/src/diagnostics/emitters/pretty.rs index 14f63d5..5536ecf 100644 --- a/libkabel/src/diagnostics/emitters/pretty.rs +++ b/libkabel/src/diagnostics/emitters/pretty.rs @@ -50,7 +50,7 @@ impl Emitter for PrettyEmitter { let line_hdr_padding = line.to_string().len() + 1; writeln!(output, "{}{}", " ".repeat(line_hdr_padding), "|".bright_blue().bold()).unwrap(); - writeln!(output, "{}{} {} {}", line.to_string().bright_blue().bold(), " ".repeat(line_no_padding - line.to_string().len()), "|".bright_blue().bold(), get_line(line, &source).unwrap()).unwrap(); + writeln!(output, "{}{} {} {}", line.to_string().bright_blue().bold(), " ".repeat(line_no_padding - line.to_string().len()), "|".bright_blue().bold(), get_line(line, &source).unwrap_or("")).unwrap(); @@ -107,4 +107,4 @@ impl Emitter for PrettyEmitter { output } -} \ No newline at end of file +} diff --git a/libkabel/src/diagnostics/emitters/util.rs b/libkabel/src/diagnostics/emitters/util.rs index cf5726e..b98e9e8 100644 --- a/libkabel/src/diagnostics/emitters/util.rs +++ b/libkabel/src/diagnostics/emitters/util.rs @@ -1,10 +1,10 @@ pub fn pos_to_line_col(pos: usize, source: &str) -> (usize, usize) { - let mut line = 0; + let mut line = 1; let mut col = 1; for (n, c) in source.chars().enumerate() { if c == '\n' { line += 1; - col = 0; + col = 1; } else { col += 1; } @@ -17,4 +17,4 @@ pub fn pos_to_line_col(pos: usize, source: &str) -> (usize, usize) { pub fn get_line(line: usize, source: &str) -> Option<&str> { source.lines().nth(line) -} \ No newline at end of file +} diff --git a/libkabel/src/lexer/mod.rs b/libkabel/src/lexer/mod.rs index cfb8dee..4f9d6b8 100644 --- a/libkabel/src/lexer/mod.rs +++ b/libkabel/src/lexer/mod.rs @@ -38,22 +38,45 @@ pub fn lexer(text_source: &str) -> Result, KError> { } State::Stringing => { // If next char is an unescaped quote - if let Some(c_peek) = chars.peek() { - if c != '\\' && *c_peek == '\"' { - chars.next(); - pos += 1; + // TODO: when possible, make this 1 `if'. Ability to + // do that remains unimplemented, hence the stupid copied + // code below. + if c != '\n' { + if let Some(c_peek) = chars.peek() { + if c != '\\' && *c_peek == '\"' { + chars.next(); + pos += 1; - current_token.push(c); - let tok_cpy = current_token.clone(); - lexed.push(Token::Literal(Span::new(span_start, pos), Literal::Str(tok_cpy))); + current_token.push(c); + let tok_cpy = current_token.clone(); + lexed.push(Token::Literal(Span::new(span_start, pos), Literal::Str(tok_cpy))); - state = State::BuildingToken; - current_token = String::new(); + state = State::BuildingToken; + current_token = String::new(); + } else { + current_token.push(c); + } } else { - current_token.push(c); + return Err(KError::UserError(vec![ + Diagnostic { + diag_type: DiagnosticType::Error, + message: "unterminated string literal".to_string(), + spans: vec![ + SpanWithLabel { + span: Span::new(span_start-1, span_start-1), + span_type: DiagnosticType::SecondaryError, + label: Some("string began here".to_string()) + }, + SpanWithLabel { + span: Span::new(pos, pos), + span_type: DiagnosticType::Error, + label: Some("expected end quote here".to_string()) + } + ] + } + ])); } } else { - return Err(KError::UserError(vec![ Diagnostic { diag_type: DiagnosticType::Error,