Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,134 @@ impl Grouping {
}
}

#[derive(Debug, Clone, Copy)]
pub(crate) enum GroupingKind {
Normal,
OptionalArgument,
BeginEnd,
LeftRight,
Array { display: bool },
Matrix { ty: MatrixType, column_spec: bool },
Cases { left: bool, display: bool },
Equation { eq_numbers: bool },
Align { eq_numbers: bool },
Aligned,
SubArray,
Alignat { eq_numbers: bool },
Alignedat,
Gather { eq_numbers: bool },
Gathered,
Multline,
Split,
}

impl GroupingKind {
pub(crate) fn opening_str(&self) -> &'static str {
match self {
Self::Normal => "{",
Self::OptionalArgument => "[",
Self::BeginEnd => "\\begin",
Self::LeftRight => "\\left",
Self::Array { display: false } => "\\begin{array}",
Self::Array { display: true } => "\\begin{darray}",
Self::Matrix { ty, column_spec } => match (ty, column_spec) {
(MatrixType::Normal, true) => "\\begin{matrix*}",
(MatrixType::Normal, false) => "\\begin{matrix}",
(MatrixType::Small, true) => "\\begin{smallmatrix*}",
(MatrixType::Small, false) => "\\begin{smallmatrix}",
(MatrixType::Parens, true) => "\\begin{pmatrix*}",
(MatrixType::Parens, false) => "\\begin{pmatrix}",
(MatrixType::Brackets, true) => "\\begin{bmatrix*}",
(MatrixType::Brackets, false) => "\\begin{bmatrix}",
(MatrixType::Braces, true) => "\\begin{Bmatrix*}",
(MatrixType::Braces, false) => "\\begin{Bmatrix}",
(MatrixType::Vertical, true) => "\\begin{vmatrix*}",
(MatrixType::Vertical, false) => "\\begin{vmatrix}",
(MatrixType::DoubleVertical, true) => "\\begin{Vmatrix*}",
(MatrixType::DoubleVertical, false) => "\\begin{Vmatrix}",
},
Self::Cases { left, display } => match (left, display) {
(true, false) => "\\begin{cases}",
(true, true) => "\\begin{dcases}",
(false, false) => "\\begin{rcases}",
(false, true) => "\\begin{drcases}",
},
Self::Equation { eq_numbers: true } => "\\begin{equation}",
Self::Equation { eq_numbers: false } => "\\begin{equation*}",
Self::Align { eq_numbers: true } => "\\begin{align}",
Self::Align { eq_numbers: false } => "\\begin{align*}",
Self::Aligned => "\\begin{aligned}",
Self::SubArray => "\\begin{subarray}",
Self::Alignat { eq_numbers: true } => "\\begin{alignat}",
Self::Alignat { eq_numbers: false } => "\\begin{alignat*}",
Self::Alignedat => "\\begin{alignedat}",
Self::Gather { eq_numbers: true } => "\\begin{gather}",
Self::Gather { eq_numbers: false } => "\\begin{gather*}",
Self::Gathered => "\\begin{gathered}",
Self::Multline => "\\begin{multline}",
Self::Split => "\\begin{split}",
}
}

pub(crate) fn closing_str(&self) -> &'static str {
match self {
Self::Normal => "}",
Self::OptionalArgument => "]",
Self::BeginEnd => "\\end",
Self::LeftRight => "\\right",
Self::Array { display: false } => "\\end{array}",
Self::Array { display: true } => "\\end{darray}",
Self::Matrix { ty, column_spec } => match (ty, column_spec) {
(MatrixType::Normal, true) => "\\end{matrix*}",
(MatrixType::Normal, false) => "\\end{matrix}",
(MatrixType::Small, true) => "\\end{smallmatrix*}",
(MatrixType::Small, false) => "\\end{smallmatrix}",
(MatrixType::Parens, true) => "\\end{pmatrix*}",
(MatrixType::Parens, false) => "\\end{pmatrix}",
(MatrixType::Brackets, true) => "\\end{bmatrix*}",
(MatrixType::Brackets, false) => "\\end{bmatrix}",
(MatrixType::Braces, true) => "\\end{Bmatrix*}",
(MatrixType::Braces, false) => "\\end{Bmatrix}",
(MatrixType::Vertical, true) => "\\end{vmatrix*}",
(MatrixType::Vertical, false) => "\\end{vmatrix}",
(MatrixType::DoubleVertical, true) => "\\end{Vmatrix*}",
(MatrixType::DoubleVertical, false) => "\\end{Vmatrix}",
},
Self::Cases { left, display } => match (left, display) {
(true, false) => "\\end{cases}",
(true, true) => "\\end{dcases}",
(false, false) => "\\end{rcases}",
(false, true) => "\\end{drcases}",
},
Self::Equation { eq_numbers: true } => "\\end{equation}",
Self::Equation { eq_numbers: false } => "\\end{equation*}",
Self::Align { eq_numbers: true } => "\\end{align}",
Self::Align { eq_numbers: false } => "\\end{align*}",
Self::Aligned => "\\end{aligned}",
Self::SubArray => "\\end{subarray}",
Self::Alignat { eq_numbers: true } => "\\end{alignat}",
Self::Alignat { eq_numbers: false } => "\\end{alignat*}",
Self::Alignedat => "\\end{alignedat}",
Self::Gather { eq_numbers: true } => "\\end{gather}",
Self::Gather { eq_numbers: false } => "\\end{gather*}",
Self::Gathered => "\\end{gathered}",
Self::Multline => "\\end{multline}",
Self::Split => "\\end{split}",
}
}
}

#[derive(Debug, Clone, Copy)]
pub(crate) enum MatrixType {
Normal,
Small,
Parens,
Brackets,
Braces,
Vertical,
DoubleVertical,
}

/// Represents a column in a matrix or array environment.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ColumnAlignment {
Expand Down
11 changes: 6 additions & 5 deletions src/parser/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use std::{error::Error, fmt::Display};

use super::SpanStack;
use crate::event::Grouping;
use crate::event::GroupingKind;

/// Anything that could possibly go wrong while parsing.
///
Expand Down Expand Up @@ -145,8 +145,7 @@ pub(crate) type InnerResult<T> = std::result::Result<T, ErrorKind>;

#[derive(Debug)]
pub(crate) enum ErrorKind {
// TODO: this error is very misleading. Rework it.
UnbalancedGroup(Option<Grouping>),
UnbalancedGroup(Option<GroupingKind>),
Environment,
MathShift,
HashSign,
Expand Down Expand Up @@ -175,7 +174,6 @@ pub(crate) enum ErrorKind {
IncorrectReplacementParams(u8, u8),
TooManyParams,
StandaloneHashSign,
// TODO: should specify what the macro expects the prefix string to be.
IncorrectMacroPrefix,
MacroAlreadyDefined,
MacroNotDefined,
Expand All @@ -185,7 +183,10 @@ impl Display for ErrorKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
// TODO: this error is very misleading. Rework it.
ErrorKind::UnbalancedGroup(_) => f.write_str("unbalanced group found"),
ErrorKind::UnbalancedGroup(Some(missing)) => {
write!(f, "unbalanced group found, expected it to be closed with `{}`", missing.closing_str())
},
ErrorKind::UnbalancedGroup(None) => f.write_str("unbalanced group found, unexpected group closing found"),
ErrorKind::Environment => f.write_str("unkown mathematical environment found"),
ErrorKind::MathShift => f.write_str(
"unexpected math `$` (math shift) character - this character cannot be used inside math mode"),
Expand Down
27 changes: 15 additions & 12 deletions src/parser/lex.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
attribute::{Dimension, DimensionUnit, Glue},
event::DelimiterType,
event::{DelimiterType, GroupingKind},
};

use super::{tables::token_to_delim, Argument, CharToken, ErrorKind, InnerResult, Token};
Expand All @@ -23,7 +23,7 @@ pub fn definition<'a>(input: &mut &'a str) -> InnerResult<(&'a str, &'a str, &'a
}

*input = rest;
let replacement_text = group_content(input, "{", "}")?;
let replacement_text = group_content(input, GroupingKind::Normal)?;

Ok((control_sequence, parameter_text, replacement_text))
}
Expand All @@ -32,27 +32,27 @@ pub fn definition<'a>(input: &mut &'a str) -> InnerResult<(&'a str, &'a str, &'a
pub fn argument<'a>(input: &mut &'a str) -> InnerResult<Argument<'a>> {
if let Some(rest) = input.trim_start().strip_prefix('{') {
*input = rest;
let content = group_content(input, "{", "}")?;
let content = group_content(input, GroupingKind::Normal)?;
Ok(Argument::Group(content))
} else {
Ok(Argument::Token(token(input)?))
}
}

pub fn optional_argument<'a>(input: &mut &'a str) -> InnerResult<Option<&'a str>> {
pub fn optional_argument<'a>(input: &mut &'a str) -> Option<&'a str> {
if let Some(rest) = input.trim_start().strip_prefix('[') {
*input = rest;
let content = group_content(input, "[", "]")?;
Ok(Some(content))
let content = group_content(input, GroupingKind::OptionalArgument).ok()?;
Some(content)
} else {
Ok(None)
None
}
}

pub fn brace_argument<'a>(input: &mut &'a str) -> InnerResult<&'a str> {
if let Some(rest) = input.trim_start().strip_prefix('{') {
*input = rest;
group_content(input, "{", "}")
group_content(input, GroupingKind::Normal)
} else {
Err(ErrorKind::GroupArgument)
}
Expand All @@ -62,7 +62,9 @@ pub fn brace_argument<'a>(input: &mut &'a str) -> InnerResult<&'a str> {
///
/// The output is the content within the group without the surrounding `start` and `end`.
/// This content is guaranteed to be balanced.
pub fn group_content<'a>(input: &mut &'a str, start: &str, end: &str) -> InnerResult<&'a str> {
pub fn group_content<'a>(input: &mut &'a str, grouping_kind: GroupingKind) -> InnerResult<&'a str> {
let start = grouping_kind.opening_str();
let end = grouping_kind.closing_str();
let mut escaped = false;
let mut index = 0;
let mut depth = 0u32;
Expand Down Expand Up @@ -123,8 +125,8 @@ pub fn content_with_suffix<'a>(input: &mut &'a str, suffix: &str) -> InnerResult
index += rest_pos;
}
b'{' if !escaped => {
let conetent = group_content(&mut &input[index + 1..], "{", "}")?;
index += conetent.len() + 1;
let content = group_content(&mut &input[index + 1..], GroupingKind::Normal)?;
index += content.len() + 1;
}
_ => escaped = false,
}
Expand Down Expand Up @@ -449,6 +451,7 @@ pub fn token<'a>(input: &mut &'a str) -> InnerResult<Token<'a>> {
mod tests {
use crate::{
attribute::DimensionUnit,
event::GroupingKind,
parser::{lex, Token},
};

Expand Down Expand Up @@ -550,7 +553,7 @@ mod tests {
fn group_content() {
let mut input =
"this { { is a test } to see if { the content parsing { of this } } } works }";
let content = lex::group_content(&mut input, "{", "}").unwrap();
let content = lex::group_content(&mut input, GroupingKind::Normal).unwrap();
assert_eq!(
content,
"this { { is a test } to see if { the content parsing { of this } } } works "
Expand Down
2 changes: 1 addition & 1 deletion src/parser/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ impl<'input> MacroContext<'input> {

if let Some(default_argument) = first_arg_default {
arguments.push(Ok(Argument::Group(
lex::optional_argument(&mut input_rest)?.unwrap_or(default_argument),
lex::optional_argument(&mut input_rest).unwrap_or(default_argument),
)));
}

Expand Down
Loading