Polish the parser

This commit is contained in:
Eunchong Yu 2018-08-19 12:36:16 +09:00
parent c311d37902
commit 8d07c117bb

View file

@ -1,14 +1,13 @@
//! An extension trait that provides the ability to strip IRC colors from a string //! An extension trait that provides the ability to strip IRC colors from a string
use std::borrow::Cow; use std::borrow::Cow;
#[derive(PartialEq)]
enum ParserState { enum ParserState {
Text, Text,
ColorCode, ColorCode,
Foreground1, Foreground1(char),
Foreground2, Foreground2,
Comma, Comma,
Background1, Background1(char),
} }
struct Parser { struct Parser {
state: ParserState, state: ParserState,
@ -49,60 +48,63 @@ impl<'a> FormattedStringExt<'a> for &'a str {
} }
fn strip_formatting(buf: &mut String) { fn strip_formatting(buf: &mut String) {
let mut parser = Parser { let mut parser = Parser::new();
state: ParserState::Text, buf.retain(|cur| parser.next(cur));
}; }
let mut prev: char = '\x00';
buf.retain(|cur| { impl Parser {
let result = match parser.state { fn new() -> Self {
ParserState::Text | ParserState::Foreground1 | ParserState::Foreground2 if cur == '\x03' => { Parser {
parser.state = ParserState::ColorCode; state: ParserState::Text,
}
}
fn next(&mut self, cur: char) -> bool {
use self::ParserState::*;
match self.state {
Text | Foreground1(_) | Foreground2 if cur == '\x03' => {
self.state = ColorCode;
false false
},
ParserState::Text => !FORMAT_CHARACTERS.contains(&cur),
ParserState::ColorCode if cur.is_digit(10) => {
parser.state = ParserState::Foreground1;
false
},
ParserState::Foreground1 if cur.is_digit(6) => {
// can only consume another digit if previous char was 1.
if prev == '1' {
parser.state = ParserState::Foreground2;
false
} else {
parser.state = ParserState::Text;
true
}
},
ParserState::Foreground1 if cur == ',' => {
parser.state = ParserState::Comma;
false
},
ParserState::Foreground2 if cur == ',' => {
parser.state = ParserState::Comma;
false
},
ParserState::Comma if (cur.is_digit(10)) => {
parser.state = ParserState::Background1;
false
},
ParserState::Background1 if cur.is_digit(6) => {
// can only consume another digit if previous char was 1.
parser.state = ParserState::Text;
if prev == '1' {
false
} else {
true
}
} }
_ => { Text => {
parser.state = ParserState::Text; !FORMAT_CHARACTERS.contains(&cur)
}
ColorCode if cur.is_digit(10) => {
self.state = Foreground1(cur);
false
}
Foreground1('1') if cur.is_digit(6) => {
// can only consume another digit if previous char was 1.
self.state = Foreground2;
false
}
Foreground1(_) if cur.is_digit(6) => {
self.state = Text;
true true
} }
}; Foreground1(_) if cur == ',' => {
prev = cur; self.state = Comma;
return result false
}); }
Foreground2 if cur == ',' => {
self.state = Comma;
false
}
Comma if (cur.is_digit(10)) => {
self.state = Background1(cur);
false
}
Background1(prev) if cur.is_digit(6) => {
// can only consume another digit if previous char was 1.
self.state = Text;
prev != '1'
}
_ => {
self.state = Text;
true
}
}
}
} }
impl FormattedStringExt<'static> for String { impl FormattedStringExt<'static> for String {