just/src/string_kind.rs
2022-09-11 08:41:24 +00:00

93 lines
2.7 KiB
Rust

use super::*;
#[derive(Debug, PartialEq, Clone, Copy, Ord, PartialOrd, Eq)]
pub(crate) struct StringKind {
delimiter: StringDelimiter,
indented: bool,
}
#[derive(Debug, PartialEq, Clone, Copy, Ord, PartialOrd, Eq)]
enum StringDelimiter {
Backtick,
QuoteDouble,
QuoteSingle,
}
impl StringKind {
// Indented values must come before un-indented values, or else
// `Self::from_token_start` will incorrectly return indented = false
// for indented strings.
const ALL: &'static [Self] = &[
Self::new(StringDelimiter::Backtick, true),
Self::new(StringDelimiter::Backtick, false),
Self::new(StringDelimiter::QuoteDouble, true),
Self::new(StringDelimiter::QuoteDouble, false),
Self::new(StringDelimiter::QuoteSingle, true),
Self::new(StringDelimiter::QuoteSingle, false),
];
const fn new(delimiter: StringDelimiter, indented: bool) -> Self {
Self {
delimiter,
indented,
}
}
pub(crate) fn delimiter(self) -> &'static str {
match (self.delimiter, self.indented) {
(StringDelimiter::Backtick, false) => "`",
(StringDelimiter::Backtick, true) => "```",
(StringDelimiter::QuoteDouble, false) => "\"",
(StringDelimiter::QuoteDouble, true) => "\"\"\"",
(StringDelimiter::QuoteSingle, false) => "'",
(StringDelimiter::QuoteSingle, true) => "'''",
}
}
pub(crate) fn delimiter_len(self) -> usize {
self.delimiter().len()
}
pub(crate) fn token_kind(self) -> TokenKind {
match self.delimiter {
StringDelimiter::QuoteDouble | StringDelimiter::QuoteSingle => TokenKind::StringToken,
StringDelimiter::Backtick => TokenKind::Backtick,
}
}
pub(crate) fn unterminated_error_kind(self) -> CompileErrorKind<'static> {
match self.delimiter {
StringDelimiter::QuoteDouble | StringDelimiter::QuoteSingle => {
CompileErrorKind::UnterminatedString
}
StringDelimiter::Backtick => CompileErrorKind::UnterminatedBacktick,
}
}
pub(crate) fn processes_escape_sequences(self) -> bool {
match self.delimiter {
StringDelimiter::QuoteDouble => true,
StringDelimiter::Backtick | StringDelimiter::QuoteSingle => false,
}
}
pub(crate) fn indented(self) -> bool {
self.indented
}
pub(crate) fn from_string_or_backtick(token: Token) -> CompileResult<Self> {
Self::from_token_start(token.lexeme()).ok_or_else(|| {
token.error(CompileErrorKind::Internal {
message: "StringKind::from_token: Expected String or Backtick".to_owned(),
})
})
}
pub(crate) fn from_token_start(token_start: &str) -> Option<Self> {
Self::ALL
.iter()
.find(|&&kind| token_start.starts_with(kind.delimiter()))
.copied()
}
}