cleanup and correct string literal content implementation

This commit is contained in:
Moritz Hölting 2024-07-08 15:03:09 +02:00
parent a0a27cda96
commit bc25da6f2c
4 changed files with 67 additions and 18 deletions

View File

@ -27,6 +27,15 @@ impl Default for FsProvider {
}
}
impl<P> From<P> for FsProvider
where
P: Into<PathBuf>,
{
fn from(root: P) -> Self {
Self { root: root.into() }
}
}
impl FileProvider for FsProvider {
fn read_to_string<P: AsRef<Path>>(&self, path: P) -> Result<String, Error> {
let full_path = self.root.join(path);

View File

@ -1,7 +1,6 @@
//! Module containing structures and implementations for logging messages to the user.
use colored::Colorize;
use path_absolutize::Absolutize;
use std::{fmt::Display, sync::Arc};
use super::source_file::{Location, SourceFile, Span};
@ -74,7 +73,7 @@ impl<'a, T> SourceCodeDisplay<'a, T> {
}
}
impl<'a, T: std::fmt::Display> Display for SourceCodeDisplay<'a, T> {
impl<'a, T: Display> Display for SourceCodeDisplay<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let start_location = self.span.start_location();
let end_location = self.span.end_location();
@ -100,12 +99,7 @@ impl<'a, T: std::fmt::Display> Display for SourceCodeDisplay<'a, T> {
"-->".cyan().bold(),
format_args!(
"{}:{}:{}",
self.span
.source_file()
.path()
.absolutize()
.unwrap_or_else(|_| std::borrow::Cow::Borrowed(self.span.source_file().path()))
.display(),
self.span.source_file().path().display(),
start_location.line,
start_location.column
)

View File

@ -1,6 +1,6 @@
//! Contains the [`Token`] struct and its related types.
use std::{collections::HashMap, str::FromStr, sync::OnceLock};
use std::{borrow::Cow, collections::HashMap, fmt::Display, str::FromStr, sync::OnceLock};
use crate::base::{
source_file::{SourceElement, SourceIterator, Span},
@ -42,9 +42,9 @@ pub enum KeywordKind {
Import,
}
impl ToString for KeywordKind {
fn to_string(&self) -> String {
self.as_str().to_string()
impl Display for KeywordKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
@ -259,11 +259,22 @@ pub struct StringLiteral {
}
impl StringLiteral {
/// Returns the string without the leading and trailing double quotes.
/// Returns the string content without escapement characters, leading and trailing double quotes.
#[must_use]
pub fn str_content(&self) -> &str {
pub fn str_content(&self) -> Cow<str> {
let string = self.span.str();
&string[1..string.len() - 1]
let string = &string[1..string.len() - 1];
if string.contains('\\') {
let escaped = string
.replace("\\n", "\n")
.replace("\\r", "\r")
.replace("\\t", "\t")
.replace("\\\"", "\"")
.replace("\\\\", "\\");
Cow::Owned(escaped)
} else {
Cow::Borrowed(string)
}
}
}
@ -603,3 +614,38 @@ impl Token {
}
}
}
#[cfg(test)]
mod tests {
use crate::base::source_file::SourceFile;
use shulkerbox::virtual_fs::{VFile, VFolder};
use std::path::Path;
use super::*;
fn get_span(content: &str) -> Span {
let source_file = VFile::Text(String::from(content));
let mut vfolder = VFolder::new();
vfolder.add_file("test.shu", source_file);
let source_file = SourceFile::load(Path::new("test.shu"), &vfolder).unwrap();
Span::new(source_file, 0, content.len()).unwrap()
}
#[test]
fn test_string_literal() {
let span = get_span(r#""Hello, World!""#);
let string_literal = StringLiteral { span };
let content = string_literal.str_content();
assert_eq!(content, "Hello, World!");
assert!(matches!(content, Cow::Borrowed(_)));
let escaped_string_literal = StringLiteral {
span: get_span(r#""Hello, \"World\"!""#),
};
let escaped_content = escaped_string_literal.str_content();
assert_eq!(escaped_content, "Hello, \"World\"!");
assert!(matches!(escaped_content, Cow::Owned(_)));
}
}

View File

@ -89,9 +89,9 @@ impl<'a> Parser<'a> {
// eat the keyword
self.forward();
let namespace_name = self
.parse_string_literal(handler)
.and_then(|name| Namespace::validate_str(name.str_content()).then_some(name))?;
let namespace_name = self.parse_string_literal(handler).and_then(|name| {
Namespace::validate_str(name.str_content().as_ref()).then_some(name)
})?;
let semicolon = self.parse_punctuation(';', true, handler)?;