add string split method

This commit is contained in:
Ava Hahn 2023-03-08 19:42:08 -08:00
parent 7438b2c9e5
commit 6961fcc9fa
Signed by untrusted user who does not match committer: affine
GPG key ID: 3A4645B8CF806069
4 changed files with 90 additions and 2 deletions

View file

@ -1,7 +1,7 @@
[package] [package]
name = "relish" name = "relish"
version = "0.1.0" version = "0.1.0"
authors = ["Aidan <aidan@aidanis.online>"] authors = ["Ava <ava@sunnypup.io>"]
edition = "2018" edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -9,4 +9,3 @@ edition = "2018"
[dependencies] [dependencies]
dirs = "3.0" dirs = "3.0"
rustyline = "8.2.0" rustyline = "8.2.0"
once_cell = "1.17.1"

View file

@ -74,6 +74,17 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> {
}, },
); );
syms.insert(
"split".to_string(),
Symbol {
name: String::from("split"),
args: Args::Strict(vec![Type::String, Type::String]),
conditional_branches: false,
docs: strings::SPLIT_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(strings::split_callback)),
},
);
syms.insert( syms.insert(
"strlen".to_string(), "strlen".to_string(),
Symbol { Symbol {

View file

@ -115,3 +115,36 @@ pub fn contains_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String>
Ok(Ctr::Bool(parent_str.contains(&child_str))) Ok(Ctr::Bool(parent_str.contains(&child_str)))
} }
pub const SPLIT_DOCSTRING: &str = "Takes two strings. String 1 is a source string and string 2 is a delimiter.
Returns a list of substrings from string 1 that were found delimited by string 2.";
pub fn split_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
let parent_str: String;
if let Ctr::String(ref s) = *ast.car {
parent_str = s.to_string();
} else {
return Err("first argument must be a string".to_string());
}
let second_arg_obj: &Ctr;
let delim_str: String;
if let Ctr::Seg(ref s) = *ast.cdr {
second_arg_obj = &*s.car;
} else {
return Err("impossible error: needs two arguments".to_string());
}
if let Ctr::String(ref s) = &*second_arg_obj {
delim_str = s.clone();
} else {
return Err("second argument must be a string".to_string());
}
let mut ret = Seg::new();
for substr in parent_str.split(&delim_str) {
ret.append(Box::new(Ctr::String(substr.to_string())));
}
Ok(Ctr::Seg(ret))
}

View file

@ -181,4 +181,49 @@ mod str_lib_tests {
result.to_string(), result.to_string(),
); );
} }
#[test]
fn test_split() {
let document = "(split 'one.two.three' '.')";
let result = "('one' 'two' 'three')";
let mut syms = SymTable::new();
static_stdlib(&mut syms).unwrap();
dynamic_stdlib(&mut syms).unwrap();
assert_eq!(
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
.unwrap()
.to_string(),
result.to_string(),
);
}
#[test]
fn test_split_big_delim() {
let document = "(split 'one:d:two:d:three' ':d:')";
let result = "('one' 'two' 'three')";
let mut syms = SymTable::new();
static_stdlib(&mut syms).unwrap();
dynamic_stdlib(&mut syms).unwrap();
assert_eq!(
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
.unwrap()
.to_string(),
result.to_string(),
);
}
#[test]
fn test_splitnt() {
let document = "(split 'one.two.three' '-')";
let result = "('one.two.three')";
let mut syms = SymTable::new();
static_stdlib(&mut syms).unwrap();
dynamic_stdlib(&mut syms).unwrap();
assert_eq!(
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
.unwrap()
.to_string(),
result.to_string(),
);
}
} }