diff --git a/src/base/file_provider.rs b/src/base/file_provider.rs
index ca69af9..037a710 100644
--- a/src/base/file_provider.rs
+++ b/src/base/file_provider.rs
@@ -27,6 +27,15 @@ impl Default for FsProvider {
}
}
+impl
From
for FsProvider
+where
+ P: Into,
+{
+ fn from(root: P) -> Self {
+ Self { root: root.into() }
+ }
+}
+
impl FileProvider for FsProvider {
fn read_to_string>(&self, path: P) -> Result {
let full_path = self.root.join(path);
diff --git a/src/base/log.rs b/src/base/log.rs
index 8ae26b6..a7b853e 100644
--- a/src/base/log.rs
+++ b/src/base/log.rs
@@ -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
)
diff --git a/src/lexical/token.rs b/src/lexical/token.rs
index 713d2d3..4415b51 100644
--- a/src/lexical/token.rs
+++ b/src/lexical/token.rs
@@ -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 {
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(_)));
+ }
+}
diff --git a/src/syntax/syntax_tree/program.rs b/src/syntax/syntax_tree/program.rs
index 6389c77..69ee059 100644
--- a/src/syntax/syntax_tree/program.rs
+++ b/src/syntax/syntax_tree/program.rs
@@ -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)?;