1
0

Compare commits

...

3 Commits

Author SHA1 Message Date
2178c67499 Implement await statements 2023-11-03 21:16:55 -04:00
bc1b88a5fa Begin adding futures 2023-11-03 19:39:34 -04:00
8ca97300d3 Clean up 2023-11-03 18:04:45 -04:00
29 changed files with 65295 additions and 82183 deletions

33
examples/async.ds Normal file
View File

@ -0,0 +1,33 @@
(output "This will print first.")
(output "This will print second.")
create_random_numbers = |count| => {
numbers = [];
while (length numbers) < count {
numbers += (random_integer)
}
}
do_a_lot = async {
(create_random_numbers 1000)
(output "Made 1000 numbers")
}
do_some = async {
(create_random_numbers 100)
(output "Made 100 numbers")
}
do_a_little = async {
(create_random_numbers 10)
(output "Made 10 numbers")
}
await {
do_a_lot
do_some
do_a_little
}
(output "This will print last.")

View File

@ -3,20 +3,26 @@ suspects = ['White' 'Green']
weapons = ['Rope' 'Lead_Pipe']
cards = [rooms suspects weapons]
take_turn = function current_room opponent_card
remove_card opponent_card
make_guess current_room
take_turn = |current_room opponent_card| => {
(remove_card opponent_card)
(make_guess current_room)
}
remove_card = function opponent_card
for card_list in cards
remove_card = |opponent_card| => {
for card_list in cards {
removed = remove card from card_list
card == opponent_card
}
if type removed == 'empty'
if (type removed) == 'empty'
output 'Card not found.'
}
make_guess = function current_room
if length suspects == 1 && length rooms == 1 && length weapons == 1
make_guess = |current_room| => {
if ((length suspects) == 1)
&& ((length rooms) == 1)
&& ((length weapons) == 1)
{
(output 'It was '
+ suspects:0
+ ' in the '
@ -24,7 +30,7 @@ make_guess = function current_room
+ ' with the '
+ weapons:0
+ '!')
else
} else {
(output 'I accuse '
+ (random suspects)
+ ' in the '
@ -32,5 +38,7 @@ make_guess = function current_room
+ ' with the '
+ (random weapons)
+ '!')
}
}
(make_guess 'Library')

View File

@ -1,4 +1,4 @@
fib = function <i> {
fib = |i| => {
if i <= 1 {
1
} else {

15
examples/select.ds Normal file
View File

@ -0,0 +1,15 @@
my_table = table |text number bool| [
["a", 1, true]
["b", 2, true]
["a", 3, true]
]
test_table = table |text bool| [
["a", true]
["b", true]
["a", true]
]
test_select = select |text bool| from my_table;
(assert_equal test_select, test_table)

View File

@ -1,31 +1,31 @@
my_table = table <text number bool> [
my_table = table |text number bool| [
["a", 1, true]
["b", 2, true]
["a", 3, true]
]
test_table = table <text bool> [
test_table = table |text bool| [
["a", true]
["b", true]
["a", true]
]
test_select = select <text bool> from my_table
test_select = select |text bool| from my_table
(assert_equal test_select, test_table)
test_table = table <text number bool> [
test_table = table |text number bool| [
[1, true]
[3, true]
]
test_select_where = select <number, bool> from my_table {
test_select_where = select |number, bool| from my_table {
text == "a"
}
(assert_equal test_select_where, test_table)
test_table = table <text number bool> [
test_table = table |text number bool| [
["a", 1, true]
["b", 2, true]
["a", 3, true]

View File

@ -1,60 +0,0 @@
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Block, Error, Map, Result, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Async {
statements: Vec<Block>,
}
impl AbstractTree for Async {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
debug_assert_eq!("async", node.kind());
let child_count = node.child_count();
let mut statements = Vec::with_capacity(child_count);
for index in 2..child_count - 1 {
let child = node.child(index).unwrap();
let statement = match child.kind() {
"statement" => Block::from_syntax_node(source, child)?,
_ => {
return Err(Error::UnexpectedSyntaxNode {
expected: "comment or statement",
actual: child.kind(),
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
})
}
};
statements.push(statement);
}
Ok(Async { statements })
}
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let statements = &self.statements;
statements
.into_par_iter()
.enumerate()
.find_map_first(|(index, statement)| {
let mut context = context.clone();
let result = statement.run(source, &mut context);
if result.is_err() {
Some(result)
} else if index == statements.len() - 1 {
Some(result)
} else {
None
}
})
.unwrap()
}
}

View File

@ -0,0 +1,53 @@
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Expression, Map, Result, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Await {
expressions: Vec<Expression>,
}
impl AbstractTree for Await {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
debug_assert_eq!("await", node.kind());
let mut expressions = Vec::new();
for index in 2..node.child_count() - 1 {
let child = node.child(index).unwrap();
if child.is_named() {
let expression = Expression::from_syntax_node(source, child)?;
expressions.push(expression);
}
}
Ok(Await { expressions })
}
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let expressions = &self.expressions;
expressions
.into_par_iter()
.find_map_first(|expression| {
let mut context = context.clone();
let value = if let Ok(value) = expression.run(source, &mut context) {
value
} else {
return None;
};
let run_result = match value {
Value::Future(block) => block.run(source, &mut context),
_ => return None,
};
Some(run_result)
})
.unwrap_or(Ok(Value::Empty))
}
}

View File

@ -94,13 +94,13 @@ impl AbstractTree for BuiltInFunction {
BuiltInFunction::AssertEqual(expressions)
}
"download" => {
let expression_node = node.child(2).unwrap();
let expression_node = node.child(1).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
BuiltInFunction::Download(expression)
}
"help" => {
let child_node = node.child(2).unwrap();
let child_node = node.child(1).unwrap();
let expression = if child_node.is_named() {
Some(Expression::from_syntax_node(source, child_node)?)
} else {
@ -110,7 +110,7 @@ impl AbstractTree for BuiltInFunction {
BuiltInFunction::Help(expression)
}
"length" => {
let expression_node = node.child(2).unwrap();
let expression_node = node.child(1).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
BuiltInFunction::Length(expression)
@ -126,7 +126,7 @@ impl AbstractTree for BuiltInFunction {
BuiltInFunction::OutputError(expressions)
}
"type" => {
let expression_node = node.child(2).unwrap();
let expression_node = node.child(1).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
BuiltInFunction::Type(expression)
@ -140,7 +140,7 @@ impl AbstractTree for BuiltInFunction {
BuiltInFunction::Append(expressions)
}
"metadata" => {
let expression_node = node.child(2).unwrap();
let expression_node = node.child(1).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
BuiltInFunction::Metadata(expression)
@ -153,13 +153,13 @@ impl AbstractTree for BuiltInFunction {
BuiltInFunction::Move(expressions)
}
"read" => {
let expression_node = node.child(2).unwrap();
let expression_node = node.child(1).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
BuiltInFunction::Read(expression)
}
"remove" => {
let expression_node = node.child(2).unwrap();
let expression_node = node.child(1).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
BuiltInFunction::Remove(expression)
@ -172,25 +172,25 @@ impl AbstractTree for BuiltInFunction {
BuiltInFunction::Write(expressions)
}
"from_json" => {
let expression_node = node.child(2).unwrap();
let expression_node = node.child(1).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
BuiltInFunction::FromJson(expression)
}
"to_json" => {
let expression_node = node.child(2).unwrap();
let expression_node = node.child(1).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
BuiltInFunction::ToJson(expression)
}
"to_string" => {
let expression_node = node.child(2).unwrap();
let expression_node = node.child(1).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
BuiltInFunction::ToString(expression)
}
"to_float" => {
let expression_node = node.child(2).unwrap();
let expression_node = node.child(1).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
BuiltInFunction::ToFloat(expression)
@ -320,11 +320,11 @@ impl AbstractTree for BuiltInFunction {
Value::Map(map) => map.len(),
Value::Table(table) => table.len(),
Value::String(string) => string.chars().count(),
Value::Function(_) => todo!(),
Value::Float(_) => todo!(),
Value::Integer(_) => todo!(),
Value::Boolean(_) => todo!(),
Value::Empty => todo!(),
_ => {
return Err(Error::ExpectedCollection {
actual: value.clone(),
});
}
};
Ok(Value::Integer(length as i64))

View File

@ -18,7 +18,7 @@ impl AbstractTree for Find {
let expression_node = node.child(3).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
let item_node = node.child(5).unwrap();
let item_node = node.child(4).unwrap();
let item = Block::from_syntax_node(source, item_node)?;
Ok(Find {

View File

@ -33,7 +33,7 @@ impl AbstractTree for For {
let expression_node = node.child(3).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
let item_node = node.child(5).unwrap();
let item_node = node.child(4).unwrap();
let item = Block::from_syntax_node(source, item_node)?;
Ok(For {

View File

@ -48,8 +48,9 @@ impl AbstractTree for FunctionCall {
}
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let mut function_context = Map::clone_from(context);
let (name, arguments) = match self {
FunctionCall::BuiltIn(function) => return function.run(source, context),
FunctionCall::BuiltIn(function) => return function.run(source, &mut function_context),
FunctionCall::ContextDefined { name, arguments } => (name, arguments),
};
@ -58,7 +59,6 @@ impl AbstractTree for FunctionCall {
} else {
return Err(Error::FunctionIdentifierNotFound(name.clone()));
};
let mut function_context = Map::clone_from(context);
if let Some(parameters) = definition.identifiers() {
let parameter_expression_pairs = parameters.iter().zip(arguments.iter());

View File

@ -7,7 +7,7 @@
//! examples.
pub mod assignment;
pub mod r#async;
pub mod r#await;
pub mod block;
pub mod built_in_function;
pub mod expression;
@ -33,8 +33,8 @@ pub mod r#while;
pub use {
assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*,
function_call::*, identifier::*, if_else::*, index::*, insert::*, logic::*, math::*,
r#async::*, r#for::*, r#match::*, r#while::*, remove::*, select::*, statement::*, sublist::*,
transform::*, value_node::*,
r#await::*, r#await::*, r#for::*, r#match::*, r#while::*, remove::*, select::*, statement::*,
sublist::*, transform::*, value_node::*,
};
use tree_sitter::Node;

View File

@ -18,7 +18,7 @@ impl AbstractTree for Remove {
let expression_node = node.child(3).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
let item_node = node.child(5).unwrap();
let item_node = node.child(4).unwrap();
let item = Block::from_syntax_node(source, item_node)?;
Ok(Remove {

View File

@ -7,49 +7,36 @@ use crate::{AbstractTree, Block, Expression, Identifier, Map, Result, Table, Val
pub struct Select {
identifiers: Vec<Identifier>,
expression: Expression,
item: Option<Block>,
block: Option<Block>,
}
impl AbstractTree for Select {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
let child_count = node.child_count();
let mut identifiers = Vec::new();
let identifier_list = node.child(1).unwrap();
for index in 2..child_count - 4 {
let node = node.child(index).unwrap();
for index in 1..identifier_list.child_count() - 1 {
let node = identifier_list.child(index).unwrap();
if node.kind() == "identifier" {
if node.is_named() {
let identifier = Identifier::from_syntax_node(source, node)?;
identifiers.push(identifier);
}
if node.kind() == ">" {
break;
}
}
let final_node = node.child(child_count - 1).unwrap();
let expression_node = node.child(3).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
let item = if final_node.kind() == "}" {
let item_node = node.child(child_count - 2).unwrap();
Some(Block::from_syntax_node(source, item_node)?)
let block = if let Some(block_node) = node.child(4) {
Some(Block::from_syntax_node(source, block_node)?)
} else {
None
};
let expression_node = if item.is_some() {
node.child(child_count - 4).unwrap()
} else {
node.child(child_count - 1).unwrap()
};
let expression = Expression::from_syntax_node(source, expression_node)?;
Ok(Select {
identifiers,
expression,
item,
block,
})
}
@ -99,7 +86,7 @@ impl AbstractTree for Select {
}
}
if let Some(where_clause) = &self.item {
if let Some(where_clause) = &self.block {
let should_include = where_clause.run(source, &mut row_context)?.as_boolean()?;
if should_include {

View File

@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
AbstractTree, Assignment, Async, Error, Expression, Filter, Find, For, IfElse, Insert, Map,
AbstractTree, Assignment, Await, Error, Expression, Filter, Find, For, IfElse, Insert, Map,
Match, Remove, Result, Select, Transform, Value, While,
};
@ -13,11 +13,12 @@ use crate::{
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum Statement {
Assignment(Box<Assignment>),
Await(Await),
Expression(Expression),
IfElse(Box<IfElse>),
Match(Match),
While(Box<While>),
Async(Box<Async>),
Async(Box<Await>),
For(Box<For>),
Transform(Box<Transform>),
Filter(Box<Filter>),
@ -37,6 +38,7 @@ impl AbstractTree for Statement {
"assignment" => Ok(Statement::Assignment(Box::new(
Assignment::from_syntax_node(source, child)?,
))),
"await" => Ok(Statement::Await(Await::from_syntax_node(source, child)?)),
"expression" => Ok(Self::Expression(Expression::from_syntax_node(
source, child,
)?)),
@ -49,7 +51,7 @@ impl AbstractTree for Statement {
"while" => Ok(Statement::While(Box::new(While::from_syntax_node(
source, child,
)?))),
"async" => Ok(Statement::Async(Box::new(Async::from_syntax_node(
"async" => Ok(Statement::Async(Box::new(Await::from_syntax_node(
source, child,
)?))),
"for" => Ok(Statement::For(Box::new(For::from_syntax_node(
@ -85,6 +87,7 @@ impl AbstractTree for Statement {
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
match self {
Statement::Assignment(assignment) => assignment.run(source, context),
Statement::Await(r#await) => r#await.run(source, context),
Statement::Expression(expression) => expression.run(source, context),
Statement::IfElse(if_else) => if_else.run(source, context),
Statement::Match(r#match) => r#match.run(source, context),

View File

@ -19,7 +19,7 @@ impl AbstractTree for Transform {
let expression_node = node.child(3).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
let item_node = node.child(5).unwrap();
let item_node = node.child(4).unwrap();
let item = Block::from_syntax_node(source, item_node)?;
Ok(Transform {

View File

@ -123,15 +123,19 @@ impl AbstractTree for ValueNode {
ValueType::Function(Function::new(parameters, body))
}
_ => {
return Err(Error::UnexpectedSyntaxNode {
expected:
"string, integer, float, boolean, list, table, map, function or empty",
actual: child.kind(),
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
})
"future" => {
let block_node = child.child(1).unwrap();
let block = Block::from_syntax_node(source, block_node)?;
ValueType::Future(block)
}
_ => return Err(Error::UnexpectedSyntaxNode {
expected:
"string, integer, float, boolean, list, table, map, function, future or empty",
actual: child.kind(),
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
}),
};
Ok(ValueNode {
@ -203,6 +207,7 @@ impl AbstractTree for ValueNode {
Value::Table(table)
}
ValueType::Function(function) => Value::Function(function.clone()),
ValueType::Future(block) => Value::Future(block.clone()),
};
Ok(value)

View File

@ -1,7 +1,7 @@
//! Types that represent runtime values.
use crate::{
error::{Error, Result},
Function, List, Map, Table, ValueType,
Block, Function, List, Map, Table, ValueType,
};
use json::JsonValue;
@ -32,14 +32,15 @@ pub mod value_type;
/// value that can be treated as any other.
#[derive(Debug, Clone, Default)]
pub enum Value {
Boolean(bool),
Float(f64),
Function(Function),
Future(Block),
Integer(i64),
List(List),
Map(Map),
Table(Table),
Function(Function),
String(String),
Float(f64),
Integer(i64),
Boolean(bool),
Table(Table),
#[default]
Empty,
}
@ -391,6 +392,8 @@ impl Ord for Value {
(Value::Table(_), _) => Ordering::Greater,
(Value::Function(left), Value::Function(right)) => left.cmp(right),
(Value::Function(_), _) => Ordering::Greater,
(Value::Future(left), Value::Future(right)) => left.cmp(right),
(Value::Future(_), _) => Ordering::Greater,
(Value::Empty, Value::Empty) => Ordering::Equal,
(Value::Empty, _) => Ordering::Less,
}
@ -421,6 +424,7 @@ impl Serialize for Value {
Value::Map(inner) => inner.serialize(serializer),
Value::Table(inner) => inner.serialize(serializer),
Value::Function(inner) => inner.serialize(serializer),
Value::Future(inner) => inner.serialize(serializer),
}
}
}
@ -443,6 +447,7 @@ impl Display for Value {
Value::Map(map) => write!(f, "{map}"),
Value::Table(table) => write!(f, "{table}"),
Value::Function(function) => write!(f, "{function}"),
Value::Future(block) => write!(f, "{block:?}"),
}
}
}

View File

@ -242,6 +242,13 @@ impl From<&Value> for Table {
.insert(vec![Value::Function(function.clone())])
.unwrap();
table
}
Value::Future(block) => {
let mut table = Table::new(vec!["future".to_string()]);
table.insert(vec![Value::Future(block.clone())]).unwrap();
table
}
}

View File

@ -5,7 +5,7 @@ use std::{
use serde::{Deserialize, Serialize};
use crate::{value_node::ValueNode, Expression, Function, Identifier, Statement, Value};
use crate::{value_node::ValueNode, Block, Expression, Function, Identifier, Statement, Value};
/// The type of a `Value`.
#[derive(Clone, Serialize, Deserialize, PartialOrd, Ord)]
@ -23,6 +23,7 @@ pub enum ValueType {
rows: Box<Expression>,
},
Function(Function),
Future(Block),
}
impl Eq for ValueType {}
@ -84,6 +85,7 @@ impl Display for ValueType {
write!(f, "table")
}
ValueType::Function(function) => write!(f, "{function}"),
ValueType::Future(_) => write!(f, "future"),
}
}
}
@ -137,6 +139,7 @@ impl From<&Value> for ValueType {
))),
},
Value::Function(function) => ValueType::Function(function.clone()),
Value::Future(block) => ValueType::Future(block.clone()),
}
}
}

View File

@ -59,6 +59,13 @@ fn remove_loop() {
evaluate(&file_contents).unwrap();
}
#[test]
fn select() {
let file_contents = read_to_string("examples/select.ds").unwrap();
evaluate(&file_contents).unwrap();
}
#[test]
fn table() {
let file_contents = read_to_string("examples/table.ds").unwrap();

View File

@ -1,75 +0,0 @@
==================
Simple Async Statements
==================
async { (output 'Whaddup') }
---
(root
(block
(statement
(async
(block
(statement
(expression
(function_call
(built_in_function
(expression
(value
(string))))))))))))
==================
Complex Async Statements
==================
async {
if 1 % 2 == 0 {
true
} else {
false
}
'foobar'
}
---
(root
(block
(statement
(async
(block
(statement
(if_else
(if
(expression
(logic
(expression
(math
(expression
(value
(integer)))
(math_operator)
(expression
(value
(integer)))))
(logic_operator)
(expression
(value
(integer)))))
(block
(statement
(expression
(value
(boolean))))))
(else
(block
(statement
(expression
(value
(boolean))))))))
(statement
(expression
(value
(string)))))))))

View File

@ -101,7 +101,7 @@ Complex Function Call
(foobar
"hi"
42
{
map {
x = 1
y = 2
}
@ -124,13 +124,20 @@ Complex Function Call
(expression
(value
(map
(identifier)
(statement
(expression
(value
(integer))))
(identifier)
(statement
(expression
(value
(integer))))))))))))
(block
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(integer))))))
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(integer)))))))))))))))

View File

@ -0,0 +1,95 @@
================================================================================
Simple Future
================================================================================
async { (output 'Whaddup') }
--------------------------------------------------------------------------------
(root
(block
(statement
(expression
(value
(future
(block
(statement
(expression
(function_call
(built_in_function
(expression
(value
(string))))))))))))))
================================================================================
Complex Future
================================================================================
async {
if 1 % 2 == 0 {
true
} else {
false
}
'foobar'
}
async { 123 }
'foo'
--------------------------------------------------------------------------------
(root
(block
(statement
(expression
(value
(future
(block
(statement
(if_else
(if
(expression
(logic
(expression
(math
(expression
(value
(integer)))
(math_operator)
(expression
(value
(integer)))))
(logic_operator)
(expression
(value
(integer)))))
(block
(statement
(expression
(value
(boolean))))))
(else
(block
(statement
(expression
(value
(boolean))))))))
(statement
(expression
(value
(string)))))))))
(statement
(expression
(value
(future
(block
(statement
(expression
(value
(integer)))))))))
(statement
(expression
(value
(string))))))

View File

@ -1,10 +1,10 @@
==================
================================================================================
Simple Map
==================
================================================================================
{ answer = 42 }
map { answer = 42 }
---
--------------------------------------------------------------------------------
(root
(block
@ -12,27 +12,31 @@ Simple Map
(expression
(value
(map
(identifier)
(statement
(expression
(value
(integer))))))))))
(block
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(integer)))))))))))))
==================
================================================================================
Nested Maps
==================
================================================================================
x = {
y = {
x = map {
y = map {
foo = 'bar'
z = {
z = map {
message = 'hiya'
}
}
f = 12
}
---
--------------------------------------------------------------------------------
(root
(block
@ -44,28 +48,46 @@ x = {
(expression
(value
(map
(identifier)
(statement
(expression
(value
(map
(identifier)
(statement
(expression
(value
(string))))
(identifier)
(statement
(expression
(value
(map
(identifier)
(block
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(map
(block
(statement
(expression
(value
(string))))))))))))
(identifier)
(statement
(expression
(value
(integer))))))))))))
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(string))))))
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(map
(block
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(string))))))))))))))))))))
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(integer)))))))))))))))

View File

@ -7,23 +7,22 @@ module.exports = grammar({
conflicts: $ => [
[$.block],
[$.map, $.assignment_operator],
],
rules: {
root: $ => repeat1($.block),
root: $ => $.block,
comment: $ => /[#][^#\n]*[#|\n]/,
block: $ => choice(
block: $ => prec.right(choice(
repeat1($.statement),
seq('{', repeat1($.statement), '}'),
),
)),
statement: $ => prec.right(seq(
choice(
$.assignment,
$.async,
$.await,
$.expression,
$.filter,
$.find,
@ -45,7 +44,7 @@ module.exports = grammar({
seq('(', $._expression_kind, ')'),
)),
_expression_kind: $ => prec.left(1, choice(
_expression_kind: $ => prec.right(1, choice(
$.function_call,
$.identifier,
$.index,
@ -67,6 +66,7 @@ module.exports = grammar({
$.function,
$.table,
$.map,
$.future,
),
integer: $ => token(prec.left(seq(
@ -92,18 +92,24 @@ module.exports = grammar({
list: $ => seq(
'[',
repeat(prec.left(seq($.expression, optional(',')))),
repeat(prec.right(seq($.expression, optional(',')))),
']',
),
map: $ => seq(
'map',
$.block,
),
future: $ => seq(
'async',
$.block,
),
await: $ => seq(
'await',
'{',
repeat(seq(
$.identifier,
"=",
$.statement,
optional(',')
)),
$._expression_list,
'}',
),
@ -265,11 +271,6 @@ module.exports = grammar({
$.expression,
)),
async: $ => seq(
'async',
$.block,
),
identifier_list: $ => prec.right(choice(
seq(
'|',

View File

@ -3,47 +3,48 @@
"word": "identifier",
"rules": {
"root": {
"type": "REPEAT1",
"content": {
"type": "SYMBOL",
"name": "block"
}
"type": "SYMBOL",
"name": "block"
},
"comment": {
"type": "PATTERN",
"value": "[#][^#\\n]*[#|\\n]"
},
"block": {
"type": "CHOICE",
"members": [
{
"type": "REPEAT1",
"content": {
"type": "SYMBOL",
"name": "statement"
}
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "{"
},
{
"type": "REPEAT1",
"content": {
"type": "SYMBOL",
"name": "statement"
}
},
{
"type": "STRING",
"value": "}"
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "CHOICE",
"members": [
{
"type": "REPEAT1",
"content": {
"type": "SYMBOL",
"name": "statement"
}
]
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "{"
},
{
"type": "REPEAT1",
"content": {
"type": "SYMBOL",
"name": "statement"
}
},
{
"type": "STRING",
"value": "}"
}
]
}
]
}
},
"statement": {
"type": "PREC_RIGHT",
@ -60,7 +61,7 @@
},
{
"type": "SYMBOL",
"name": "async"
"name": "await"
},
{
"type": "SYMBOL",
@ -158,7 +159,7 @@
}
},
"_expression_kind": {
"type": "PREC_LEFT",
"type": "PREC_RIGHT",
"value": 1,
"content": {
"type": "CHOICE",
@ -256,6 +257,10 @@
{
"type": "SYMBOL",
"name": "map"
},
{
"type": "SYMBOL",
"name": "future"
}
]
},
@ -482,7 +487,7 @@
{
"type": "REPEAT",
"content": {
"type": "PREC_LEFT",
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
@ -516,41 +521,43 @@
"map": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "map"
},
{
"type": "SYMBOL",
"name": "block"
}
]
},
"future": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "async"
},
{
"type": "SYMBOL",
"name": "block"
}
]
},
"await": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "await"
},
{
"type": "STRING",
"value": "{"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "statement"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
}
"type": "SYMBOL",
"name": "_expression_list"
},
{
"type": "STRING",
@ -1119,19 +1126,6 @@
]
}
},
"async": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "async"
},
{
"type": "SYMBOL",
"name": "block"
}
]
},
"identifier_list": {
"type": "PREC_RIGHT",
"value": 0,
@ -1434,10 +1428,6 @@
"conflicts": [
[
"block"
],
[
"map",
"assignment_operator"
]
],
"precedences": [],

View File

@ -28,15 +28,15 @@
"fields": {}
},
{
"type": "async",
"type": "await",
"named": true,
"fields": {},
"children": {
"multiple": false,
"multiple": true,
"required": true,
"types": [
{
"type": "block",
"type": "expression",
"named": true
}
]
@ -287,6 +287,21 @@
]
}
},
{
"type": "future",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "block",
"named": true
}
]
}
},
{
"type": "identifier_list",
"named": true,
@ -422,15 +437,11 @@
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"multiple": false,
"required": true,
"types": [
{
"type": "identifier",
"named": true
},
{
"type": "statement",
"type": "block",
"named": true
}
]
@ -530,7 +541,7 @@
"named": true,
"fields": {},
"children": {
"multiple": true,
"multiple": false,
"required": true,
"types": [
{
@ -576,7 +587,7 @@
"named": true
},
{
"type": "async",
"type": "await",
"named": true
},
{
@ -692,6 +703,10 @@
"type": "function",
"named": true
},
{
"type": "future",
"named": true
},
{
"type": "integer",
"named": true
@ -846,6 +861,10 @@
"type": "async",
"named": false
},
{
"type": "await",
"named": false
},
{
"type": "bash",
"named": false
@ -934,6 +953,10 @@
"type": "length",
"named": false
},
{
"type": "map",
"named": false
},
{
"type": "match",
"named": false

File diff suppressed because it is too large Load Diff