Parse GameType, BoardSize, VariationDisplay, and TimeLimit

This commit is contained in:
Savanni D'Gerinel 2023-09-16 17:27:03 -04:00
parent aa1c28c022
commit 1eee8280f6
1 changed files with 62 additions and 7 deletions

View File

@ -620,9 +620,11 @@ fn parse_property<'a, E: nom::error::ParseError<&'a str>>(
"AP" => parse_propval(parse_simple_text().map(Property::Application))(input)?,
"CA" => parse_propval(parse_simple_text().map(Property::Charset))(input)?,
"FF" => parse_propval(parse_number().map(Property::FileFormat))(input)?,
"GM" => unimplemented!(),
"ST" => unimplemented!(),
"SZ" => unimplemented!(),
"GM" => parse_propval(parse_gametype().map(Property::GameType))(input)?,
"ST" => discard_propval()
.map(|_| Property::VariationDisplay)
.parse(input)?,
"SZ" => parse_propval(parse_size().map(Property::BoardSize))(input)?,
"DM" => discard_propval()
.map(|_| Property::Evaluation(Evaluation::Even))
.parse(input)?,
@ -653,7 +655,9 @@ fn parse_property<'a, E: nom::error::ParseError<&'a str>>(
"RO" => parse_propval(parse_simple_text().map(Property::Round))(input)?,
"RU" => parse_propval(parse_simple_text().map(Property::Ruleset))(input)?,
"SO" => parse_propval(parse_simple_text().map(Property::Source))(input)?,
"TM" => unimplemented!(),
"TM" => parse_propval(
parse_real().map(|seconds| Property::TimeLimit(Duration::from_secs(seconds as u64))),
)(input)?,
"US" => parse_propval(parse_simple_text().map(Property::User))(input)?,
"WR" => parse_propval(parse_simple_text().map(Property::WhiteRank))(input)?,
"WT" => parse_propval(parse_simple_text().map(Property::WhiteTeam))(input)?,
@ -674,7 +678,7 @@ fn parse_comment<'a, E: nom::error::ParseError<&'a str>>() -> impl Parser<&'a st
fn parse_move<'a, E: nom::error::ParseError<&'a str>>(
color: Color,
) -> impl FnMut(&'a str) -> IResult<&'a str, Property, E> {
) -> impl Parser<&'a str, Property, E> {
{
let color = color.clone();
move |input: &'a str| {
@ -685,6 +689,14 @@ fn parse_move<'a, E: nom::error::ParseError<&'a str>>(
}
}
fn parse_gametype<'a, E: nom::error::ParseError<&'a str>>() -> impl Parser<&'a str, GameType, E> {
|input: &'a str| {
take_until1("]")
.map(|text: &'a str| GameType::from(text))
.parse(input)
}
}
fn parse_time_left<'a, E: ParseError<&'a str>>(
color: Color,
) -> impl FnMut(&'a str) -> IResult<&'a str, Property, E> {
@ -701,6 +713,21 @@ fn parse_time_left<'a, E: ParseError<&'a str>>(
}
}
pub fn parse_size<'a, E: nom::error::ParseError<&'a str>>() -> impl Parser<&'a str, Size, E> {
|input: &'a str| {
let (input, dimensions) = separated_list1(tag(":"), digit1)(input)?;
let (width, height) = match dimensions.as_slice() {
[width] => (width.parse::<i32>().unwrap(), width.parse::<i32>().unwrap()),
[width, height] => (
width.parse::<i32>().unwrap(),
height.parse::<i32>().unwrap(),
),
_ => (19, 19),
};
Ok((input, Size { width, height }))
}
}
fn parse_propval<'a, E: nom::error::ParseError<&'a str>>(
mut parser: impl Parser<&'a str, Property, E>,
) -> impl FnMut(&'a str) -> IResult<&'a str, Property, E> {
@ -734,7 +761,24 @@ fn parse_number<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, i32, E> {
}
fn parse_real<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, f32, E> {
|input| unimplemented!()
|input| {
let (input, sign) = opt(alt((tag("+"), tag("-"))))(input)?;
let (input, whole_value) = digit1(input)?;
let (input, fractional_value) = opt(|input| {
let (input, _) = tag(".")(input)?;
let (input, fractional_value) = digit1(input)?;
Ok((input, format!(".{}", fractional_value)))
})(input)?;
let value = format!(
"{}{}{}",
sign.unwrap_or("+"),
whole_value,
fractional_value.unwrap_or("".to_owned())
)
.parse::<f32>()
.unwrap();
Ok((input, value))
}
}
fn parse_double<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, Double, E> {
@ -742,7 +786,18 @@ fn parse_double<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, Double, E>
}
fn parse_simple_text<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, String, E> {
|input| unimplemented!()
|input| {
let (input, value) = opt(escaped_transform(
none_of("\\]"),
'\\',
alt((
value("]", tag("]")),
value("\\", tag("\\")),
value("", tag("\n")),
)),
))(input)?;
Ok((input, value.unwrap_or("".to_owned())))
}
}
fn parse_text<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, String, E> {