Я внедряю робота, который принимает такие приказы, как L
(поворот налево), R
(поворот направо) и M
(движение вперед).Эти ордера могут быть увеличены с помощью квантификатора типа M3LMR2
(передвинуть на 3 шага, повернуть налево, сделать один шаг, повернуть лицо).Это эквивалент MMMLMRR
.
Я закодировал структуру робота, которая может понимать следующее перечисление:
pub enum Message {
TurnLeft(i8),
TurnRight(i8),
MoveForward(i8),
}
Robot::execute(&mut self, orders: Vec<Message>)
выполняет свою работу правильно.
Теперь я изо всех сил пытаюсь написать что-то приличное для разбора строк, жонглирования с &str
, String
, char
и небезопасных срезов, потому что токены могут содержать 1 или более символов.
Я пробовал сопоставление с регулярным выражением (почти сработало), но я действительно хочу токенизировать строку:
fn capture(orders: &String, start: &usize, end: &usize) -> Message {
unsafe {
let order = orders.get_unchecked(start..end);
// …
};
Message::TurnLeft(1) // temporary
}
pub fn parse_orders(orders: String) -> Result<Vec<Message>, String> {
let mut messages = vec![];
let mut start: usize = 0;
let mut end: usize = 0;
while end < orders.len() && end != start {
end += 1;
match orders.get(end) {
Some('0'...'9') => continue,
_ => {
messages.push(capture(&orders, &start, &end));
start = end;
}
}
}
Ok(messages)
}
Это не компилируется и неуклюже.
Идея состоит в том, чтобы написать синтаксический анализатор, который превратит строку заказа в вектор Message
:
let messages = parse_order("M3LMR2");
println!("Messages => {:?}", messages);
// would print
// [Message::MoveForward(3), Message::TurnLeft(1), Message::MoveForward(1), Message::TurnRight(2)]
Каким будет эффективный / элегантный способ сделать это?