cleanup and correct string literal content implementation
This commit is contained in:
parent
a0a27cda96
commit
bc25da6f2c
|
@ -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 {
|
impl FileProvider for FsProvider {
|
||||||
fn read_to_string<P: AsRef<Path>>(&self, path: P) -> Result<String, Error> {
|
fn read_to_string<P: AsRef<Path>>(&self, path: P) -> Result<String, Error> {
|
||||||
let full_path = self.root.join(path);
|
let full_path = self.root.join(path);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
//! Module containing structures and implementations for logging messages to the user.
|
//! Module containing structures and implementations for logging messages to the user.
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use path_absolutize::Absolutize;
|
|
||||||
use std::{fmt::Display, sync::Arc};
|
use std::{fmt::Display, sync::Arc};
|
||||||
|
|
||||||
use super::source_file::{Location, SourceFile, Span};
|
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 {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let start_location = self.span.start_location();
|
let start_location = self.span.start_location();
|
||||||
let end_location = self.span.end_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(),
|
"-->".cyan().bold(),
|
||||||
format_args!(
|
format_args!(
|
||||||
"{}:{}:{}",
|
"{}:{}:{}",
|
||||||
self.span
|
self.span.source_file().path().display(),
|
||||||
.source_file()
|
|
||||||
.path()
|
|
||||||
.absolutize()
|
|
||||||
.unwrap_or_else(|_| std::borrow::Cow::Borrowed(self.span.source_file().path()))
|
|
||||||
.display(),
|
|
||||||
start_location.line,
|
start_location.line,
|
||||||
start_location.column
|
start_location.column
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Contains the [`Token`] struct and its related types.
|
//! 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::{
|
use crate::base::{
|
||||||
source_file::{SourceElement, SourceIterator, Span},
|
source_file::{SourceElement, SourceIterator, Span},
|
||||||
|
@ -42,9 +42,9 @@ pub enum KeywordKind {
|
||||||
Import,
|
Import,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for KeywordKind {
|
impl Display for KeywordKind {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
self.as_str().to_string()
|
write!(f, "{}", self.as_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,11 +259,22 @@ pub struct StringLiteral {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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]
|
#[must_use]
|
||||||
pub fn str_content(&self) -> &str {
|
pub fn str_content(&self) -> Cow<str> {
|
||||||
let string = self.span.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(_)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -89,9 +89,9 @@ impl<'a> Parser<'a> {
|
||||||
// eat the keyword
|
// eat the keyword
|
||||||
self.forward();
|
self.forward();
|
||||||
|
|
||||||
let namespace_name = self
|
let namespace_name = self.parse_string_literal(handler).and_then(|name| {
|
||||||
.parse_string_literal(handler)
|
Namespace::validate_str(name.str_content().as_ref()).then_some(name)
|
||||||
.and_then(|name| Namespace::validate_str(name.str_content()).then_some(name))?;
|
})?;
|
||||||
|
|
||||||
let semicolon = self.parse_punctuation(';', true, handler)?;
|
let semicolon = self.parse_punctuation(';', true, handler)?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue