use crate::atom::AtomClass;
use crate::style::Style;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Span {
pub start: usize,
pub end: usize,
}
impl Span {
#[must_use]
pub const fn new(start: usize, end: usize) -> Self {
Self { start, end }
}
#[must_use]
pub fn union(self, other: Self) -> Self {
Self {
start: self.start.min(other.start),
end: self.end.max(other.end),
}
}
#[must_use]
pub const fn len(&self) -> usize {
self.end.saturating_sub(self.start)
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.end <= self.start
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Node {
pub kind: NodeKind,
pub span: Span,
}
impl Node {
#[must_use]
pub const fn new(kind: NodeKind, span: Span) -> Self {
Self { kind, span }
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Delim {
pub ch: Option<char>,
pub span: Span,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum DelimSize {
Big,
BBig,
Bigg,
BBigg,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum Limits {
#[default]
Default,
Limits,
NoLimits,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FracSpec {
pub bar: bool,
pub delims: Option<(char, char)>,
pub forced_style: Option<Style>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AccentKind {
Hat,
Check,
Tilde,
Acute,
Grave,
Dot,
Ddot,
Breve,
Bar,
Vec,
Dddot,
Ddddot,
Ring,
WideHat,
WideTilde,
OverLine,
UnderLine,
OverBrace,
UnderBrace,
OverRightArrow,
OverLeftArrow,
}
impl AccentKind {
#[must_use]
pub const fn is_over(self) -> bool {
!matches!(self, Self::UnderLine | Self::UnderBrace)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TextStyle {
Bold,
Emph,
Underline,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MathFont {
Blackboard,
Calligraphic,
Roman,
Bold,
BoldItalic,
SansSerif,
Typewriter,
Italic,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SpaceKind {
Thin,
Med,
Thick,
NegThin,
Quad,
Qquad,
ControlSpace,
}
impl SpaceKind {
#[must_use]
pub const fn mu(self) -> i32 {
match self {
Self::Thin => 3,
Self::Med => 4,
Self::Thick => 5,
Self::NegThin => -3,
Self::Quad => 18,
Self::Qquad => 36,
Self::ControlSpace => 6,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PhantomKind {
Full,
Horizontal,
Vertical,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum StackKind {
Stackrel,
Overset,
Underset,
}
#[derive(Clone, Debug, PartialEq)]
pub enum NodeKind {
List(Vec<Node>),
Symbol {
ch: char,
class: AtomClass,
},
BigOp {
ch: char,
limits: Limits,
integral: bool,
},
OpName {
name: String,
limits: bool,
},
Scripts {
base: Option<Box<Node>>,
sub: Option<Box<Node>>,
sup: Option<Box<Node>>,
primes: Vec<Span>,
},
Frac {
num: Box<Node>,
den: Box<Node>,
spec: FracSpec,
},
Radical {
index: Option<Box<Node>>,
radicand: Box<Node>,
},
Accent {
accent: AccentKind,
base: Box<Node>,
},
LeftRight {
left: Delim,
right: Delim,
body: Vec<Node>,
},
SizedDelim {
size: DelimSize,
class: AtomClass,
delim: Delim,
},
Text {
body: Vec<Node>,
},
TextRun {
text: String,
char_spans: Vec<Span>,
},
TextStyled {
style: TextStyle,
body: Vec<Node>,
},
MathIsland {
body: Vec<Node>,
display: bool,
},
StyleChange(Style),
AlignChange(LineAlign),
SizeChange(f64),
ColorChange(String),
LineSpacing(f64),
MathFont {
font: MathFont,
body: Box<Node>,
},
Phantom {
kind: PhantomKind,
body: Box<Node>,
},
Stack {
kind: StackKind,
annotation: Box<Node>,
base: Box<Node>,
},
XArrow {
mapsto: bool,
above: Box<Node>,
below: Option<Box<Node>>,
},
Space(SpaceKind),
Tie,
Linebreak,
AlignTab,
AlignBlock {
align: LineAlign,
lines: Vec<Node>,
},
Environment {
name: String,
spec: Option<String>,
rows: Vec<Vec<Node>>,
},
Fragment(FragmentKind),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum LineAlign {
#[default]
Left,
Center,
Right,
}
impl LineAlign {
#[must_use]
pub fn slack_factor(self) -> f64 {
match self {
Self::Left => 0.0,
Self::Center => 0.5,
Self::Right => 1.0,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum FragmentKind {
UnmatchedClose,
StrayRight(Delim),
RedundantMathShift,
}