Skip to content

Commit

Permalink
feat: spread operator
Browse files Browse the repository at this point in the history
Adds a new spread operator, allowing you to merge objects/arrays using
`..$input` inside objects or arrays.
  • Loading branch information
JakeStanger committed May 24, 2023
1 parent 2be933d commit 48304d4
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,50 @@ if you need more power you should use a full language.
That said, they hopefully provide a way of quickly viewing/changing values
without needing to trawl through the whole file.

#### Merging

Somtimes you want to re-use an object or array to compose a larger object/array.
It is possible to achieve this by merging two together using the `..$input` spread operator.
This allows you to spread object inputs into other objects, and array inputs into other arrays.

```corn
let {
$base = { foo = "bar"}
} in {
..$base
}
```

Evaluates to:

```json
{
"foo": "bar"
}
```

And with arrays:

```corn
let {
$low = [ 1 2 ]
$high = [ 3 4 ]
} in {
nums = [ ..$low ..$high ]
}
```

Evaluates to:

```json
{
"nums": ["1", "2", "3", "4"]
}
```

Object keys and spreads are evaulated in the order they are written,
which allows you to spread a base object and then manually overwrite specific keys.

### Comments

At any point you can start a comment using `//`. A comment is terminated by a newline `\n` character.
Expand Down Expand Up @@ -510,4 +554,4 @@ Make sure to enable it when building:

```sh
wasm-pack build -- --features wasm
```
```
5 changes: 5 additions & 0 deletions assets/inputs/invalid_spread.corn
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let {
foo = 23
} in {
..$foo
}
10 changes: 10 additions & 0 deletions assets/inputs/spread.corn
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
let {
$foo = { bar = "baz" }

$nums_low = [ 1 2 ]
$num_high = [ 3 4 ]
} in {
hello = "world"
..$foo
nums = [ ..$nums_low ..$num_high ]
}
10 changes: 10 additions & 0 deletions assets/outputs/json/spread.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"bar": "baz",
"hello": "world",
"nums": [
1,
2,
3,
4
]
}
9 changes: 9 additions & 0 deletions assets/outputs/toml/spread.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
bar = 'baz'
hello = 'world'
nums = [
1,
2,
3,
4,
]

8 changes: 8 additions & 0 deletions assets/outputs/yaml/spread.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
bar: baz
hello: world
nums:
- 1
- 2
- 3
- 4

32 changes: 24 additions & 8 deletions libcorn/src/grammar.pest
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,34 @@ WHITESPACE = _{ " " | "\t" | "\r" | "\n" }
COMMENT = _{ "//" ~ (!"\n" ~ ANY)* }

object = {
"{" ~ pair* ~ "}"
"{"
~ object_value*
~ "}"
}

object_value = _{
pair | spread
}

spread = {
".." ~ input
}

array = {
"[" ~ value* ~ "]"
"["
~ array_value*
~ "]"
}

array_value = _{
value | spread
}

pair = { path ~ "=" ~ value }

path = ${
path_seg
~ ( "." ~ path_seg )*
path_seg
~ ( "." ~ path_seg )*
}

path_seg = ${ path_char + }
Expand All @@ -33,9 +49,9 @@ string_val = ${ char* }

char = {
// input
!("\"" | "\\") ~ ANY
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
!("\"" | "\\") ~ ANY
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}

integer = @{
Expand All @@ -56,4 +72,4 @@ assignment = { input ~ "=" ~ value }

assign_block = { "let" ~ "{" ~ assignment* ~ "}" ~ "in" }

config = _{ SOI ~ assign_block? ~ object ~ EOI }
config = _{ SOI ~ assign_block? ~ object ~ EOI }
32 changes: 28 additions & 4 deletions libcorn/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,25 @@ impl<'a> CornParser<'a> {
/// to form a vector of `Value`s.
fn parse_array(&self, block: Pair<'a, Rule>) -> Result<Vec<Value<'a>>> {
assert_eq!(block.as_rule(), Rule::array);
block
.into_inner()
.map(|pair| self.parse_value(pair))
.collect::<Result<Vec<_>>>()

let mut arr = vec![];

for pair in block.into_inner() {
match pair.as_rule() {
Rule::spread => {
let input = pair.into_inner().next().unwrap();
let value = self.parse_value(input)?;

match value {
Value::Array(other) => arr.extend(other),
_ => unreachable!(),
}
}
_ => arr.push(self.parse_value(pair)?),
};
}

Ok(arr)
}

/// Parses each key/value pair in a `Rule::object`
Expand All @@ -118,6 +133,15 @@ impl<'a> CornParser<'a> {
value,
);
}
Rule::spread => {
let input = pair.into_inner().next().unwrap();
let value = self.parse_value(input)?;

match value {
Value::Object(other) => obj.extend(other),
_ => unreachable!(),
}
}
_ => unreachable!(),
}
}
Expand Down
3 changes: 2 additions & 1 deletion libcorn/tests/parser_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,10 @@ generate_eq_tests!(
object,
object_in_array,
readme_example,
spread,
string,
value_after_table,
very_compact
);

generate_invalid_tests!(invalid, invalid_input);
generate_invalid_tests!(invalid, invalid_input, invalid_spread);

0 comments on commit 48304d4

Please sign in to comment.