use crate::{Field, PieceType, Turn};
use pest::{Parser, iterators::Pair};
use super::Lan;
#[derive(Parser)]
#[grammar = "parser/long_algebraic_notation/long_algebraic_notation.pest"]
struct LanStruct;
impl Lan {
#[must_use]
pub fn import(raw: &str) -> Option<Turn> {
let Ok(mut parsed_data) = LanStruct::parse(Rule::turn, raw) else {
return None;
};
if let Some(turn_type) = parsed_data.next().unwrap().into_inner().next() {
match turn_type.as_rule() {
Rule::from_to_turn => {
let (from, to) = Self::handle_from_to_turn_rule(turn_type);
return Some(Turn {
current: from,
target: to,
promotion: None,
});
}
Rule::piece_descriptor_turn => {
let (from, to) = Self::handle_piece_descriptor_turn_rule(turn_type);
return Some(Turn {
current: from,
target: to,
promotion: None,
});
}
Rule::promotion_turn => {
return Some(Self::handle_promotion_turn_rule(turn_type));
}
_ => unreachable!(),
}
}
unreachable!()
}
fn handle_promotion_turn_rule(promotion_turn: Pair<Rule>) -> Turn {
let mut from_field: Option<Field> = None;
let mut to_field: Option<Field> = None;
for promotion_turn_descriptor in promotion_turn.into_inner() {
match promotion_turn_descriptor.as_rule() {
Rule::from_to_turn => {
let (temp_from_field, temp_to_field) =
Self::handle_from_to_turn_rule(promotion_turn_descriptor);
from_field = Some(temp_from_field);
to_field = Some(temp_to_field);
}
Rule::piece_descriptor_turn => {
let (temp_from_field, temp_to_field) =
Self::handle_piece_descriptor_turn_rule(promotion_turn_descriptor);
from_field = Some(temp_from_field);
to_field = Some(temp_to_field);
}
Rule::promotion_piece => {
let piece_representation = promotion_turn_descriptor.as_str().as_bytes()[0];
let piece_type =
PieceType::import_piecetype(piece_representation as char).unwrap();
return Turn {
current: from_field.unwrap(),
target: to_field.unwrap(),
promotion: Some(piece_type),
};
}
_ => unreachable!(),
}
}
unreachable!()
}
fn handle_piece_descriptor_turn_rule(piece_descriptor_turn: Pair<Rule>) -> (Field, Field) {
for piece_descriptor in piece_descriptor_turn.into_inner() {
if piece_descriptor.as_rule() == Rule::from_to_turn {
return Self::handle_from_to_turn_rule(piece_descriptor);
}
}
unreachable!()
}
fn handle_from_to_turn_rule(from_to_turn: Pair<Rule>) -> (Field, Field) {
let mut from_field: Option<Field> = None;
for field_descriptor in from_to_turn.into_inner() {
if field_descriptor.as_rule() == Rule::field_descriptor {
let field = Field::new_from_string(field_descriptor.as_str()).unwrap();
if let Some(from) = from_field {
return (from, field);
}
from_field = Some(field);
}
}
unreachable!()
}
}