use crate::pattern::regex;
use crate::types::{Rule, TokenData};
use super::OrdinalData;
fn parse_ja_numeral(s: &str) -> Option<i64> {
if let Ok(v) = s.parse::<i64>() {
return Some(v);
}
let mut total = 0i64;
let mut current = 0i64;
for ch in s.chars() {
match ch {
'一' => current = current.checked_add(1)?,
'二' => current = current.checked_add(2)?,
'三' => current = current.checked_add(3)?,
'四' => current = current.checked_add(4)?,
'五' => current = current.checked_add(5)?,
'六' => current = current.checked_add(6)?,
'七' => current = current.checked_add(7)?,
'八' => current = current.checked_add(8)?,
'九' => current = current.checked_add(9)?,
'十' => {
let lhs = if current == 0 { 1 } else { current };
total = total.checked_add(lhs.checked_mul(10)?)?;
current = 0;
}
'百' => {
let lhs = if current == 0 { 1 } else { current };
total = total.checked_add(lhs.checked_mul(100)?)?;
current = 0;
}
'千' => {
let lhs = if current == 0 { 1 } else { current };
total = total.checked_add(lhs.checked_mul(1000)?)?;
current = 0;
}
_ => return None,
}
}
total.checked_add(current)
}
pub fn rules() -> Vec<Rule> {
vec![Rule {
name: "ordinal (ja 第...)".to_string(),
pattern: vec![regex("第([0-9一二三四五六七八九十百千]+)")],
production: Box::new(|nodes| {
let s = match &nodes[0].token_data {
TokenData::RegexMatch(m) => m.group(1)?,
_ => return None,
};
Some(TokenData::Ordinal(OrdinalData::new(parse_ja_numeral(s)?)))
}),
}]
}