2019-04-11 15:23:14 -07:00
|
|
|
use crate::common::*;
|
2017-11-16 23:30:08 -08:00
|
|
|
|
|
|
|
#[derive(PartialEq, Debug)]
|
2019-04-15 22:40:02 -07:00
|
|
|
pub struct StringLiteral<'a> {
|
2018-12-08 14:29:41 -08:00
|
|
|
pub raw: &'a str,
|
2019-04-11 23:58:08 -07:00
|
|
|
pub cooked: Cow<'a, str>,
|
2017-11-16 23:30:08 -08:00
|
|
|
}
|
|
|
|
|
2019-04-15 22:40:02 -07:00
|
|
|
impl<'a> StringLiteral<'a> {
|
|
|
|
pub fn new(token: &Token<'a>) -> CompilationResult<'a, StringLiteral<'a>> {
|
|
|
|
let raw = &token.lexeme()[1..token.lexeme().len() - 1];
|
2017-11-16 23:30:08 -08:00
|
|
|
|
2019-04-15 22:40:02 -07:00
|
|
|
if let TokenKind::StringRaw = token.kind {
|
|
|
|
Ok(StringLiteral {
|
2019-04-11 23:58:08 -07:00
|
|
|
cooked: Cow::Borrowed(raw),
|
2018-12-08 14:29:41 -08:00
|
|
|
raw,
|
|
|
|
})
|
2019-04-15 22:40:02 -07:00
|
|
|
} else if let TokenKind::StringCooked = token.kind {
|
2017-11-16 23:30:08 -08:00
|
|
|
let mut cooked = String::new();
|
|
|
|
let mut escape = false;
|
|
|
|
for c in raw.chars() {
|
|
|
|
if escape {
|
|
|
|
match c {
|
2018-12-08 14:29:41 -08:00
|
|
|
'n' => cooked.push('\n'),
|
|
|
|
'r' => cooked.push('\r'),
|
|
|
|
't' => cooked.push('\t'),
|
|
|
|
'\\' => cooked.push('\\'),
|
|
|
|
'"' => cooked.push('"'),
|
|
|
|
other => {
|
|
|
|
return Err(
|
|
|
|
token.error(CompilationErrorKind::InvalidEscapeSequence { character: other }),
|
2019-04-11 12:30:29 -07:00
|
|
|
);
|
2018-12-08 14:29:41 -08:00
|
|
|
}
|
2017-11-16 23:30:08 -08:00
|
|
|
}
|
|
|
|
escape = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if c == '\\' {
|
|
|
|
escape = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cooked.push(c);
|
|
|
|
}
|
2019-04-15 22:40:02 -07:00
|
|
|
Ok(StringLiteral {
|
2019-04-11 23:58:08 -07:00
|
|
|
raw,
|
|
|
|
cooked: Cow::Owned(cooked),
|
|
|
|
})
|
2017-11-16 23:30:08 -08:00
|
|
|
} else {
|
|
|
|
Err(token.error(CompilationErrorKind::Internal {
|
2018-12-08 14:29:41 -08:00
|
|
|
message: "cook_string() called on non-string token".to_string(),
|
2017-11-16 23:30:08 -08:00
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-11 23:58:08 -07:00
|
|
|
|
2019-04-15 22:40:02 -07:00
|
|
|
impl<'a> Display for StringLiteral<'a> {
|
2019-04-11 23:58:08 -07:00
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
match self.cooked {
|
|
|
|
Cow::Borrowed(raw) => write!(f, "'{}'", raw),
|
|
|
|
Cow::Owned(_) => write!(f, "\"{}\"", self.raw),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|