Skip to content

Commit

Permalink
Add location information to errors (#169)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmke8 authored Jul 31, 2024
2 parents 2aabe56 + ce1a7f7 commit 9f344b8
Show file tree
Hide file tree
Showing 43 changed files with 573 additions and 305 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions latex2mmlc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ keywords = ["latex", "mathml"]
categories = ["science"]

[dependencies]
no-panic = "0.1.30"
phf = { version = "0.11.2", features = ["macros"] }
strum_macros = "0.26.4"

Expand Down
12 changes: 12 additions & 0 deletions latex2mmlc/src/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ pub struct Arena<'source> {
nodes: Vec<NodeListElement<'source>>,
}

impl<'source> Default for Arena<'source> {
fn default() -> Self {
Self::new()
}
}

impl<'source> Arena<'source> {
pub fn new() -> Self {
// We fill the arena with one dummy element, so that all indices
Expand Down Expand Up @@ -179,6 +185,12 @@ pub enum SingletonOrList {
Singleton(NodeReference),
}

impl Default for NodeListBuilder {
fn default() -> Self {
Self::new()
}
}

impl NodeListBuilder {
pub fn new() -> Self {
NodeListBuilder(None)
Expand Down
15 changes: 8 additions & 7 deletions latex2mmlc/src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub enum FracAttr {
CFracStyle,
}

#[derive(Debug, Clone, PartialEq, AsRefStr)]
#[derive(Debug, Clone, Copy, PartialEq, AsRefStr)]
pub enum Style {
#[strum(serialize = r#" displaystyle="true" scriptlevel="0""#)]
DisplayStyle = 1,
Expand Down Expand Up @@ -71,7 +71,7 @@ pub enum MathSpacing {
}

/// <mi> mathvariant attribute
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum TextTransform {
Bold,
BoldFraktur,
Expand All @@ -93,13 +93,14 @@ pub enum TextTransform {
}

fn add_offset(c: char, offset: u32) -> char {
let new_char = c as u32 + offset;
let new_char = char::from_u32(c as u32 + offset);
debug_assert!(
char::from_u32(new_char).is_some(),
"Invalid char: {}",
new_char
new_char.is_some(),
"Invalid char: {}, offset: {}",
c,
offset
);
unsafe { char::from_u32_unchecked(new_char) }
unsafe { new_char.unwrap_unchecked() }
}

impl TextTransform {
Expand Down
2 changes: 1 addition & 1 deletion latex2mmlc/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ static COMMANDS: phf::Map<&'static str, Token> = phf::phf_map! {

pub fn get_command(command: &str) -> Token<'_> {
match COMMANDS.get(command) {
Some(token) => token.clone(),
Some(token) => *token,
None => Token::UnknownCommand(command),
}
}
Expand Down
100 changes: 80 additions & 20 deletions latex2mmlc/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
use std::fmt;

use strum_macros::AsRefStr;

// use no_panic::no_panic;

use crate::token::Token;

#[derive(Debug)]
pub enum LatexError<'source> {
pub struct LatexError<'source>(pub usize, pub LatexErrKind<'source>);

#[derive(Debug)]
pub enum LatexErrKind<'source> {
UnexpectedToken {
expected: Token<'source>,
expected: &'static Token<'static>,
got: Token<'source>,
},
UnclosedGroup(Token<'source>),
UnexpectedClose(Token<'source>),
UnexpectedEOF,
MissingParenthesis {
location: Token<'source>,
location: &'static Token<'static>,
got: Token<'source>,
},
UnknownEnvironment(&'source str),
Expand All @@ -23,58 +30,72 @@ pub enum LatexError<'source> {
},
CannotBeUsedHere {
got: Token<'source>,
correct_place: &'static str,
correct_place: Place,
},
ExpectedText(&'static str),
}

impl LatexError<'_> {
#[derive(Debug, AsRefStr)]
#[repr(u32)] // A different value here somehow increases code size on WASM enormously.
pub enum Place {
#[strum(serialize = r"after \int, \sum, ...")]
AfterBigOp,
#[strum(serialize = r"before supported operators")]
BeforeSomeOps,
#[strum(serialize = r"after an identifier or operator")]
AfterOpOrIdent,
}

impl LatexErrKind<'_> {
/// Returns the error message as a string.
///
/// This serves the same purpose as the `Display` implementation,
/// but produces more compact WASM code.
pub fn string(&self) -> String {
match self {
LatexError::UnexpectedToken { expected, got } => {
LatexErrKind::UnexpectedToken { expected, got } => {
"Expected token \"".to_string()
+ expected.as_ref()
+ "\", but found token \""
+ got.as_ref()
+ "\"."
}
LatexError::UnclosedGroup(expected) => {
LatexErrKind::UnclosedGroup(expected) => {
"Expected token \"".to_string() + expected.as_ref() + "\", but not found."
}
LatexError::UnexpectedClose(got) => {
LatexErrKind::UnexpectedClose(got) => {
"Unexpected closing token: \"".to_string() + got.as_ref() + "\"."
}
LatexError::UnexpectedEOF => "Unexpected end of file.".to_string(),
LatexError::MissingParenthesis { location, got } => {
LatexErrKind::UnexpectedEOF => "Unexpected end of file.".to_string(),
LatexErrKind::MissingParenthesis { location, got } => {
"There must be a parenthesis after \"".to_string()
+ location.as_ref()
+ "\", but not found. Instead, \""
+ got.as_ref()
+ "\" was found."
}
LatexError::UnknownEnvironment(environment) => {
LatexErrKind::UnknownEnvironment(environment) => {
"Unknown environment \"".to_string() + environment + "\"."
}
LatexError::UnknownCommand(cmd) => "Unknown command \"\\".to_string() + cmd + "\".",
LatexError::MismatchedEnvironment { expected, got } => {
"Expected \"\\end{".to_string() + expected + "}\", but got \"\\end{" + got + "}\""
LatexErrKind::UnknownCommand(cmd) => "Unknown command \"\\".to_string() + cmd + "\".",
LatexErrKind::MismatchedEnvironment { expected, got } => {
"Expected \"\\end{".to_string() + expected + "}\", but got \"\\end{" + got + "}\"."
}
LatexErrKind::CannotBeUsedHere { got, correct_place } => {
"Got \"".to_string()
+ got.as_ref()
+ "\", which may only appear "
+ correct_place.as_ref()
+ "."
}
LatexError::CannotBeUsedHere {
got,
correct_place: needs,
} => "Got \"".to_string() + got.as_ref() + "\", which may only appear " + needs + ".",
LatexError::ExpectedText(place) => "Expected text in ".to_string() + place + ".",
LatexErrKind::ExpectedText(place) => "Expected text in ".to_string() + place + ".",
}
}
}

impl fmt::Display for LatexError<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.string())
write!(f, "{}: {}", self.0, self.1.string())
}
}

Expand Down Expand Up @@ -121,3 +142,42 @@ impl GetUnwrap for str {
self.get(range).expect("valid range")
}
}

// static mut ITOA_BUF: [u8; 20] = [0; 20];

// // #[no_panic]
// fn itoa(val: u64) -> &'static str {
// if val == 0 {
// return "0";
// }
// let mut val = val;
// let base = 10;
// let digits = b"0123456789";
// let mut i = 20;

// while val != 0 && i > 0 {
// i -= 1;
// // let digit = unsafe { digits.get_unchecked((val % base) as usize) };
// let digit = digits[(val % base) as usize];
// unsafe { ITOA_BUF[i] = digit };
// val /= base;
// }

// let slice = unsafe { &ITOA_BUF[i..] };
// // This unsafe block wouldn't be necessary if the `ascii_char` feature were stable.
// unsafe { std::str::from_utf8_unchecked(slice) }
// }

// #[cfg(test)]
// mod tests {
// use super::*;

// #[test]
// fn itoa_test() {
// assert_eq!(itoa(0), "0");
// assert_eq!(itoa(1), "1");
// assert_eq!(itoa(10), "10");
// assert_eq!(itoa(1234567890), "1234567890");
// assert_eq!(itoa(u64::MAX), "18446744073709551615");
// }
// }
Loading

0 comments on commit 9f344b8

Please sign in to comment.