Implement match logic and syntax
This commit is contained in:
parent
99338dedc5
commit
06da345333
12
examples/match.ds
Normal file
12
examples/match.ds
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
foo_or_bar = match (random_boolean) {
|
||||||
|
true => "foo"
|
||||||
|
false => "bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
num = match (random_integer) {
|
||||||
|
1 => "one",
|
||||||
|
2 => { "two" },
|
||||||
|
* => "neither",
|
||||||
|
}
|
||||||
|
|
||||||
|
[foo_or_bar, num]
|
@ -13,6 +13,7 @@ use crate::{AbstractTree, Error, Expression, Map, Result, Statement, Type, Value
|
|||||||
pub struct Match {
|
pub struct Match {
|
||||||
matcher: Expression,
|
matcher: Expression,
|
||||||
options: Vec<(Expression, Statement)>,
|
options: Vec<(Expression, Statement)>,
|
||||||
|
fallback: Option<Box<Statement>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Match {
|
impl AbstractTree for Match {
|
||||||
@ -24,24 +25,37 @@ impl AbstractTree for Match {
|
|||||||
|
|
||||||
let mut options = Vec::new();
|
let mut options = Vec::new();
|
||||||
let mut previous_expression = None;
|
let mut previous_expression = None;
|
||||||
|
let mut next_statement_is_fallback = false;
|
||||||
|
let mut fallback = None;
|
||||||
|
|
||||||
for index in 2..node.child_count() {
|
for index in 2..node.child_count() {
|
||||||
let child = node.child(index).unwrap();
|
let child = node.child(index).unwrap();
|
||||||
|
|
||||||
|
if child.kind() == "*" {
|
||||||
|
next_statement_is_fallback = true;
|
||||||
|
}
|
||||||
|
|
||||||
if child.kind() == "expression" {
|
if child.kind() == "expression" {
|
||||||
previous_expression = Some(Expression::from_syntax_node(source, child, context)?);
|
previous_expression = Some(Expression::from_syntax_node(source, child, context)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if child.kind() == "statement" {
|
if child.kind() == "statement" {
|
||||||
if let Some(expression) = &previous_expression {
|
let statement = Statement::from_syntax_node(source, child, context)?;
|
||||||
let statement = Statement::from_syntax_node(source, child, context)?;
|
|
||||||
|
|
||||||
|
if next_statement_is_fallback {
|
||||||
|
fallback = Some(Box::new(statement));
|
||||||
|
next_statement_is_fallback = false;
|
||||||
|
} else if let Some(expression) = &previous_expression {
|
||||||
options.push((expression.clone(), statement));
|
options.push((expression.clone(), statement));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Match { matcher, options })
|
Ok(Match {
|
||||||
|
matcher,
|
||||||
|
options,
|
||||||
|
fallback,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
||||||
@ -55,7 +69,11 @@ impl AbstractTree for Match {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Empty)
|
if let Some(fallback) = &self.fallback {
|
||||||
|
fallback.run(source, context)
|
||||||
|
} else {
|
||||||
|
Ok(Value::Empty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use serde::{ser::SerializeMap, Deserialize, Serialize};
|
use serde::{ser::SerializeMap, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
|
@ -285,9 +285,13 @@ module.exports = grammar({
|
|||||||
'{',
|
'{',
|
||||||
repeat1(
|
repeat1(
|
||||||
seq(
|
seq(
|
||||||
$.expression,
|
choice(
|
||||||
|
$.expression,
|
||||||
|
'*',
|
||||||
|
),
|
||||||
'=>',
|
'=>',
|
||||||
$.statement,
|
$.statement,
|
||||||
|
optional(','),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'}',
|
'}',
|
||||||
|
@ -896,8 +896,17 @@
|
|||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "CHOICE",
|
||||||
"name": "expression"
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "expression"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "*"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
@ -906,6 +915,18 @@
|
|||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "statement"
|
"name": "statement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": ","
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user