use crate::uax29::{Action, sentence::properties::SentenceBreakProperty, state_enum};
state_enum! {
StartOfText, Any, CR, ParaSep, Upper, Lower, ATerm, LetterATerm, STerm,
ATermClose, ATermCloseSp, STermClose, STermCloseSp, SB8Pending,
}
impl State {
pub const fn is_deferred(self) -> bool {
matches!(self, State::SB8Pending)
}
}
#[derive(Clone, Copy)]
pub(crate) struct Transition(pub(crate) State, pub(crate) Action);
type Row = [Transition; SentenceBreakProperty::NUM_VARIANTS];
pub(crate) const TRANSITION_TABLE: [Row; State::NUM_VARIANTS] = [
start_of_text_transitions(),
any_transitions(),
cr_transitions(),
parasep_transitions(),
upper_transitions(),
lower_transitions(),
aterm_transitions(),
letter_aterm_transitions(),
sterm_transitions(),
aterm_close_transitions(),
aterm_close_sp_transitions(),
sterm_close_transitions(),
sterm_close_sp_transitions(),
sb8_pending_transitions(),
];
const fn default_all_break() -> Row {
let mut row = [brk(State::Any); SentenceBreakProperty::NUM_VARIANTS];
row[SentenceBreakProperty::CR as usize] = brk(State::CR);
row[SentenceBreakProperty::LF as usize] = brk(State::ParaSep);
row[SentenceBreakProperty::Sep as usize] = brk(State::ParaSep);
row[SentenceBreakProperty::Upper as usize] = brk(State::Upper);
row[SentenceBreakProperty::Lower as usize] = brk(State::Lower);
row[SentenceBreakProperty::ATerm as usize] = brk(State::ATerm);
row[SentenceBreakProperty::STerm as usize] = brk(State::STerm);
row[SentenceBreakProperty::Extend as usize] = transparent();
row[SentenceBreakProperty::Format as usize] = transparent();
row
}
const fn default_no_break() -> Row {
let mut row = [nb(State::Any); SentenceBreakProperty::NUM_VARIANTS];
row[SentenceBreakProperty::CR as usize] = nb(State::CR);
row[SentenceBreakProperty::LF as usize] = nb(State::ParaSep);
row[SentenceBreakProperty::Sep as usize] = nb(State::ParaSep);
row[SentenceBreakProperty::Upper as usize] = nb(State::Upper);
row[SentenceBreakProperty::Lower as usize] = nb(State::Lower);
row[SentenceBreakProperty::ATerm as usize] = nb(State::ATerm);
row[SentenceBreakProperty::STerm as usize] = nb(State::STerm);
row[SentenceBreakProperty::Extend as usize] = transparent();
row[SentenceBreakProperty::Format as usize] = transparent();
row
}
const fn without_sb5(row: &mut Row) {
row[SentenceBreakProperty::Extend as usize] = brk(State::Any);
row[SentenceBreakProperty::Format as usize] = brk(State::Any);
}
const fn with_sb8a(row: &mut Row) {
row[SentenceBreakProperty::SContinue as usize] = nb(State::Any);
row[SentenceBreakProperty::ATerm as usize] = nb(State::ATerm);
row[SentenceBreakProperty::STerm as usize] = nb(State::STerm);
}
const fn with_sb9(row: &mut Row, close_state: State, sp_state: State) {
row[SentenceBreakProperty::Close as usize] = nb(close_state);
row[SentenceBreakProperty::Sp as usize] = nb(sp_state);
row[SentenceBreakProperty::CR as usize] = nb(State::CR);
row[SentenceBreakProperty::LF as usize] = nb(State::ParaSep);
row[SentenceBreakProperty::Sep as usize] = nb(State::ParaSep);
}
const fn start_of_text_transitions() -> Row {
let mut row = default_all_break();
without_sb5(&mut row);
row
}
const fn any_transitions() -> Row {
default_no_break()
}
const fn cr_transitions() -> Row {
let mut row = default_all_break();
row[SentenceBreakProperty::LF as usize] = nb(State::ParaSep);
without_sb5(&mut row);
row
}
const fn parasep_transitions() -> Row {
let mut row = default_all_break();
without_sb5(&mut row);
row
}
const fn upper_transitions() -> Row {
let mut row = default_no_break();
row[SentenceBreakProperty::ATerm as usize] = nb(State::LetterATerm);
row
}
const fn lower_transitions() -> Row {
let mut row = default_no_break();
row[SentenceBreakProperty::ATerm as usize] = nb(State::LetterATerm);
row
}
const fn aterm_transitions() -> Row {
let mut row = default_all_break();
row[SentenceBreakProperty::Numeric as usize] = nb(State::Any);
row[SentenceBreakProperty::Lower as usize] = nb(State::Lower);
row[SentenceBreakProperty::Other as usize] = nb(State::SB8Pending);
with_sb8a(&mut row);
with_sb9(&mut row, State::ATermClose, State::ATermCloseSp);
row
}
const fn letter_aterm_transitions() -> Row {
let mut row = aterm_transitions();
row[SentenceBreakProperty::Upper as usize] = nb(State::Upper);
row
}
const fn sterm_transitions() -> Row {
let mut row = default_all_break();
with_sb8a(&mut row);
with_sb9(&mut row, State::STermClose, State::STermCloseSp);
row
}
const fn aterm_close_transitions() -> Row {
let mut row = default_all_break();
row[SentenceBreakProperty::Lower as usize] = nb(State::Lower);
row[SentenceBreakProperty::Other as usize] = nb(State::SB8Pending);
row[SentenceBreakProperty::Numeric as usize] = nb(State::SB8Pending);
with_sb8a(&mut row);
with_sb9(&mut row, State::ATermClose, State::ATermCloseSp);
row
}
const fn aterm_close_sp_transitions() -> Row {
let mut row = default_all_break();
row[SentenceBreakProperty::Lower as usize] = nb(State::Lower);
row[SentenceBreakProperty::Other as usize] = nb(State::SB8Pending);
row[SentenceBreakProperty::Numeric as usize] = nb(State::SB8Pending);
row[SentenceBreakProperty::Close as usize] = nb(State::SB8Pending);
with_sb8a(&mut row);
row[SentenceBreakProperty::Sp as usize] = nb(State::ATermCloseSp);
row[SentenceBreakProperty::CR as usize] = nb(State::CR);
row[SentenceBreakProperty::LF as usize] = nb(State::ParaSep);
row[SentenceBreakProperty::Sep as usize] = nb(State::ParaSep);
row
}
const fn sterm_close_transitions() -> Row {
let mut row = default_all_break();
with_sb8a(&mut row);
with_sb9(&mut row, State::STermClose, State::STermCloseSp);
row
}
const fn sterm_close_sp_transitions() -> Row {
let mut row = default_all_break();
with_sb8a(&mut row);
row[SentenceBreakProperty::Sp as usize] = nb(State::STermCloseSp);
row[SentenceBreakProperty::CR as usize] = nb(State::CR);
row[SentenceBreakProperty::LF as usize] = nb(State::ParaSep);
row[SentenceBreakProperty::Sep as usize] = nb(State::ParaSep);
row
}
const fn sb8_pending_transitions() -> Row {
let mut row = [deferred(State::Any); SentenceBreakProperty::NUM_VARIANTS];
row[SentenceBreakProperty::CR as usize] = deferred(State::CR);
row[SentenceBreakProperty::LF as usize] = deferred(State::ParaSep);
row[SentenceBreakProperty::Sep as usize] = deferred(State::ParaSep);
row[SentenceBreakProperty::Upper as usize] = deferred(State::Upper);
row[SentenceBreakProperty::ATerm as usize] = deferred(State::ATerm);
row[SentenceBreakProperty::STerm as usize] = deferred(State::STerm);
row[SentenceBreakProperty::Extend as usize] = transparent();
row[SentenceBreakProperty::Format as usize] = transparent();
row[SentenceBreakProperty::Lower as usize] = nb(State::Lower);
row[SentenceBreakProperty::Other as usize] = nb(State::SB8Pending);
row[SentenceBreakProperty::Close as usize] = nb(State::SB8Pending);
row[SentenceBreakProperty::Numeric as usize] = nb(State::SB8Pending);
row[SentenceBreakProperty::Sp as usize] = nb(State::SB8Pending);
row[SentenceBreakProperty::SContinue as usize] = nb(State::SB8Pending);
row
}
const fn brk(s: State) -> Transition {
Transition(s, Action::Break)
}
const fn nb(s: State) -> Transition {
Transition(s, Action::NoBreak)
}
const fn deferred(s: State) -> Transition {
Transition(s, Action::DeferredBreak)
}
const fn transparent() -> Transition {
Transition(State::Any, Action::Transparent)
}