Find escaped characters in strings

This commit is contained in:
Eryn Wells 2016-12-28 08:35:02 -07:00
parent 575ebceb7c
commit 5d5ddf30d0
2 changed files with 32 additions and 0 deletions

View file

@ -10,6 +10,8 @@ pub trait Lexable {
fn is_hash(&self) -> bool; fn is_hash(&self) -> bool;
fn is_dot(&self) -> bool; fn is_dot(&self) -> bool;
fn is_string_quote(&self) -> bool; fn is_string_quote(&self) -> bool;
fn is_string_escape_leader(&self) -> bool;
fn is_string_escaped(&self) -> bool;
fn is_newline(&self) -> bool; fn is_newline(&self) -> bool;
fn is_eof(&self) -> bool; fn is_eof(&self) -> bool;
@ -44,6 +46,14 @@ impl Lexable for char {
*self == '"' *self == '"'
} }
fn is_string_escape_leader(&self) -> bool {
*self == '\\'
}
fn is_string_escaped(&self) -> bool {
*self == '"' || *self == '\\'
}
fn is_boolean_true(&self) -> bool { fn is_boolean_true(&self) -> bool {
*self == 't' *self == 't'
} }

View file

@ -38,6 +38,7 @@ enum State {
NumberSign, NumberSign,
Sign, Sign,
String, String,
StringEscape,
} }
pub struct Lexer { pub struct Lexer {
@ -357,6 +358,20 @@ impl Lexer {
if c.is_string_quote() { if c.is_string_quote() {
return self.token_result(Token::String(self.value())); return self.token_result(Token::String(self.value()));
} }
else if c.is_string_escape_leader() {
self.state = State::StringEscape;
}
Ok(None)
}
fn state_string_escape(&mut self, c: char) -> StateResult {
if c.is_string_escaped() {
self.state = State::String;
self.advance();
}
else {
return Err(self.error_string(format!("Invalid string escape character: {}", c)));
}
Ok(None) Ok(None)
} }
@ -402,6 +417,7 @@ impl Iterator for Lexer {
State::NumberSign => self.state_number_sign(c), State::NumberSign => self.state_number_sign(c),
State::Sign => self.state_sign(c), State::Sign => self.state_sign(c),
State::String => self.state_string(c), State::String => self.state_string(c),
State::StringEscape => self.state_string_escape(c),
State::Comment => self.state_comment(c), State::Comment => self.state_comment(c),
}; };
assert!(result.has_token() || self.forward != previous_forward, "No lexing progress made!"); assert!(result.has_token() || self.forward != previous_forward, "No lexing progress made!");
@ -488,6 +504,12 @@ mod tests {
check_single_token("\"abc\"", Token::String(String::from("\"abc\""))); check_single_token("\"abc\"", Token::String(String::from("\"abc\"")));
} }
#[test]
fn finds_escaped_characters_in_strings() {
check_single_token("\"\\\\\"", Token::String(String::from("\"\\\\\"")));
check_single_token("\"\\\"\"", Token::String(String::from("\"\\\"\"")));
}
#[test] #[test]
fn finds_numbers() { fn finds_numbers() {
check_single_token(".34", Token::Number(Number::new(0.34))); check_single_token(".34", Token::Number(Number::new(0.34)));