Skip to content

Commit

Permalink
fix escaped \w, \d etc
Browse files Browse the repository at this point in the history
  • Loading branch information
nbittich committed Aug 18, 2024
1 parent 24ecd2a commit f623e43
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 41 deletions.
73 changes: 36 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -747,46 +747,45 @@ You already have seen `length` to find the length of an array or string, `includ

Here is a list of built-in functions available:

| name | description | example |
| ----------- | ---------------------------- | ---------------------------------------------- |
| sqrt | square root | `sqrt(2)` |
| abs | absolute value | `abs(-2)` |
| log | logarithm | `log(2)` |
| ln | natural logarithm | `ln(2)` |
| length | length of an array or string | `length("azert")` |
| sin | sine of a number | `sin(2)` |
| cos | cosine of a number | `cos(2)` |
| tan | tangent of a number | `tan(2.2)` |
| print | print without a newline | `print("hello")` |
| println | print with a newline | `println("hello")` |
| include | include a script | `include("scripts/test_fn.adana")` |
| require | load a shared object | `require("my_lib.so")` |
| to_int | cast to int | `to_int("2")`<br>`to_int(2.2)` |
| to_hex | format num to hex | `to_hex(2)`<br>`to_hex(2.2)` |
| to_binary | format num to binary | `to_binary(2)` |
| to_double | cast to double | `to_double("2.2")` |
| to_bool | cast to bool | `to_bool("true")` |
| to_string | cast to string | `to_string(true)` |
| drop | drop a variable from context | `drop("myvar")`<br>`drop(arr[0])` |
| eval | Evaluate a string as code | `eval("sqrt(9)")` |
| type_of | Type of variable | `type_of(true)` |
| is_u8 | Check if u8 | `is_u8(0x1)` |
| is_i8 | Check if i8 | `is_i8(-1)` |
| is_int | Check if int | `is_int(512)` |
| is_double | Check if double | `is_double(1.2)` |
| is_function | Check if function | `is_function(()=> {1})` |
| is_struct | Check if struct | `is_struct(struct {})` |
| is_bool | Check if bool | `is_bool(false)` |
| is_array | Check if array | `is_bool([1,2])` |
| is_error | Check if error | `is_error(err)` |
| make_err | Create an error | `make_err("oops")` |
| is_match | Check matching regex | `is_match("AaAaAbbBBBb", """(?i)a+(?-i)b+""")` |
| match | Match regex | `match("AaAaAbbBBBb", """(?i)a+(?-i)b+""")` |
| name | description | example |
| ----------- | ---------------------------- | ------------------------------------------ |
| sqrt | square root | `sqrt(2)` |
| abs | absolute value | `abs(-2)` |
| log | logarithm | `log(2)` |
| ln | natural logarithm | `ln(2)` |
| length | length of an array or string | `length("azert")` |
| sin | sine of a number | `sin(2)` |
| cos | cosine of a number | `cos(2)` |
| tan | tangent of a number | `tan(2.2)` |
| print | print without a newline | `print("hello")` |
| println | print with a newline | `println("hello")` |
| include | include a script | `include("scripts/test_fn.adana")` |
| require | load a shared object | `require("my_lib.so")` |
| to_int | cast to int | `to_int("2")`<br>`to_int(2.2)` |
| to_hex | format num to hex | `to_hex(2)`<br>`to_hex(2.2)` |
| to_binary | format num to binary | `to_binary(2)` |
| to_double | cast to double | `to_double("2.2")` |
| to_bool | cast to bool | `to_bool("true")` |
| to_string | cast to string | `to_string(true)` |
| drop | drop a variable from context | `drop("myvar")`<br>`drop(arr[0])` |
| eval | Evaluate a string as code | `eval("sqrt(9)")` |
| type_of | Type of variable | `type_of(true)` |
| is_u8 | Check if u8 | `is_u8(0x1)` |
| is_i8 | Check if i8 | `is_i8(-1)` |
| is_int | Check if int | `is_int(512)` |
| is_double | Check if double | `is_double(1.2)` |
| is_function | Check if function | `is_function(()=> {1})` |
| is_struct | Check if struct | `is_struct(struct {})` |
| is_bool | Check if bool | `is_bool(false)` |
| is_array | Check if array | `is_bool([1,2])` |
| is_error | Check if error | `is_error(err)` |
| make_err | Create an error | `make_err("oops")` |
| is_match | Check matching regex | `is_match("AaAaAbbBBBb", "(?i)a+(?-i)b+")` |
| match | Match regex | `match("AaAaAbbBBBb", "(?i)a+(?-i)b+")` |

#### Matching regexes

There are two built-in functions for matching a regex against a string. You must use F-string ("""s""")
notation for the pattern:
There are two built-in functions for matching a regex against a string:

```python
pattern = """(?i)a+(?-i)b+"""
Expand Down
12 changes: 12 additions & 0 deletions adana-script/src/string_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::borrow::Cow;
/// copied from https://github.com/rust-bakery/nom/blob/7.1.3/examples/string.rs
use nom::branch::alt;
use nom::bytes::streaming::{is_not, take_while_m_n};
use nom::character::complete::anychar;
use nom::character::streaming::{char, multispace1};
use nom::combinator::{map, map_opt, map_res, value, verify};
use nom::error::{FromExternalError, ParseError};
Expand Down Expand Up @@ -84,6 +85,11 @@ fn parse_escaped_whitespace<'a, E: ParseError<&'a str>>(
) -> IResult<&'a str, &'a str, E> {
preceded(char('\\'), multispace1)(input)
}
fn parse_escaped_anychar<'a, E: ParseError<&'a str>>(
input: &'a str,
) -> IResult<&'a str, char, E> {
preceded(char('\\'), anychar)(input)
}

/// Parse a non-empty block of text that doesn't include \ or "
fn parse_literal<'a, E: ParseError<&'a str>>(
Expand All @@ -108,6 +114,7 @@ enum StringFragment<'a> {
Literal(&'a str),
EscapedChar(char),
EscapedWS,
EscapedAnychar(char),
}

/// Combine parse_literal, parse_escaped_whitespace, and parse_escaped_char
Expand All @@ -125,6 +132,7 @@ where
map(parse_literal, StringFragment::Literal),
map(parse_escaped_char, StringFragment::EscapedChar),
value(StringFragment::EscapedWS, parse_escaped_whitespace),
map(parse_escaped_anychar, StringFragment::EscapedAnychar),
))(input)
}

Expand Down Expand Up @@ -152,6 +160,10 @@ where
StringFragment::Literal(s) => string.push_str(s),
StringFragment::EscapedChar(c) => string.push(c),
StringFragment::EscapedWS => {}
StringFragment::EscapedAnychar(c) => {
string.push('\\');
string.push(c)
}
}
string
},
Expand Down
8 changes: 4 additions & 4 deletions adana-script/src/tests/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ fn test_is_match() {
let mut ctx = BTreeMap::new();
let r = compute(
r#"
pattern = """(?i)a+(?-i)b+"""
pattern = "(?i)a+(?-i)b+"
text = "AaAaAbbBBBb"
is_match(text, pattern)
Expand All @@ -90,7 +90,7 @@ fn test_is_match() {
let mut ctx = BTreeMap::new();
let r = compute(
r#"
pattern = """(\w+): \$(\d+)"""
pattern = "(\w+): \$(\d+)"
text = "Item1: $100, Item2: $200, Item3: $300"
is_match(text, pattern)
Expand All @@ -106,7 +106,7 @@ fn test_match() {
let mut ctx = BTreeMap::new();
let r = compute(
r#"
pattern = """(?i)a+(?-i)b+"""
pattern = "(?i)a+(?-i)b+"
text = "AaAaAbbBBBb"
match(text, pattern)
Expand All @@ -122,7 +122,7 @@ fn test_match() {
let mut ctx = BTreeMap::new();
let r = compute(
r#"
pattern = """(\w+): \$(\d+)"""
pattern = "(\w+): \$(\d+)"
text = "Item1: $100, Item2: $200, Item3: $300"
match(text, pattern)
Expand Down
12 changes: 12 additions & 0 deletions adana-script/src/tests/strings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ fn test_string_escape() {
);
}
#[test]
fn test_string_regex() {
let expr = r#"
s = "(\w+): \$(\d+)"
"#;
let mut ctx = BTreeMap::new();
let _ = compute(expr, &mut ctx, "N/A").unwrap();
assert_eq!(
Primitive::String(r#"(\w+): \$(\d+)"#.to_string()),
ctx["s"].read().unwrap().clone()
);
}
#[test]
fn test_string_block_with_parameters() {
let expr = r#"
name = "nordine"
Expand Down

0 comments on commit f623e43

Please sign in to comment.