Add index expressions to fix parsing bug
This commit is contained in:
parent
346ff1c0da
commit
2f0ec91c08
@ -30,10 +30,6 @@ impl AbstractTree for Identifier {
|
||||
|
||||
let text = &source[node.byte_range()];
|
||||
|
||||
if text.is_empty() {
|
||||
println!("{node:?}");
|
||||
}
|
||||
|
||||
debug_assert!(!text.is_empty());
|
||||
|
||||
Ok(Identifier(text.to_string()))
|
||||
|
@ -1,16 +1,16 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tree_sitter::Node;
|
||||
|
||||
use crate::{AbstractTree, Error, Expression, List, Map, Result, Type, Value};
|
||||
use crate::{AbstractTree, Error, IndexExpression, List, Map, Result, Type, Value};
|
||||
|
||||
/// Abstract representation of an index expression.
|
||||
///
|
||||
/// An index is a means of accessing values stored in list, maps and strings.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct Index {
|
||||
pub collection: Expression,
|
||||
pub index: Expression,
|
||||
pub index_end: Option<Expression>,
|
||||
pub collection: IndexExpression,
|
||||
pub index: IndexExpression,
|
||||
pub index_end: Option<IndexExpression>,
|
||||
}
|
||||
|
||||
impl AbstractTree for Index {
|
||||
@ -18,14 +18,14 @@ impl AbstractTree for Index {
|
||||
Error::expect_syntax_node(source, "index", node)?;
|
||||
|
||||
let collection_node = node.child(0).unwrap();
|
||||
let collection = Expression::from_syntax_node(source, collection_node, context)?;
|
||||
let collection = IndexExpression::from_syntax_node(source, collection_node, context)?;
|
||||
|
||||
let index_node = node.child(2).unwrap();
|
||||
let index = Expression::from_syntax_node(source, index_node, context)?;
|
||||
let index = IndexExpression::from_syntax_node(source, index_node, context)?;
|
||||
|
||||
let index_end_node = node.child(4);
|
||||
let index_end = if let Some(index_end_node) = index_end_node {
|
||||
Some(Expression::from_syntax_node(
|
||||
Some(IndexExpression::from_syntax_node(
|
||||
source,
|
||||
index_end_node,
|
||||
context,
|
||||
@ -60,7 +60,7 @@ impl AbstractTree for Index {
|
||||
Ok(item)
|
||||
}
|
||||
Value::Map(map) => {
|
||||
let value = if let Expression::Identifier(identifier) = &self.index {
|
||||
let value = if let IndexExpression::Identifier(identifier) = &self.index {
|
||||
let key = identifier.inner();
|
||||
|
||||
map.variables()?
|
||||
|
@ -1,7 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tree_sitter::Node;
|
||||
|
||||
use crate::{AbstractTree, Error, Index, Map, Result, Statement, Type, Value};
|
||||
use crate::{AbstractTree, Error, Index, IndexExpression, Map, Result, Statement, Type, Value};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct IndexAssignment {
|
||||
@ -52,7 +52,7 @@ impl AbstractTree for IndexAssignment {
|
||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
||||
let index_collection = self.index.collection.run(source, context)?;
|
||||
let index_context = index_collection.as_map().unwrap_or(context);
|
||||
let index_key = if let crate::Expression::Identifier(identifier) = &self.index.index {
|
||||
let index_key = if let IndexExpression::Identifier(identifier) = &self.index.index {
|
||||
identifier.inner()
|
||||
} else {
|
||||
return Err(Error::VariableIdentifierNotFound(
|
||||
|
68
src/abstract_tree/index_expression.rs
Normal file
68
src/abstract_tree/index_expression.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
value_node::ValueNode, AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type,
|
||||
Value,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum IndexExpression {
|
||||
Value(ValueNode),
|
||||
Identifier(Identifier),
|
||||
Index(Box<Index>),
|
||||
FunctionCall(Box<FunctionCall>),
|
||||
}
|
||||
|
||||
impl AbstractTree for IndexExpression {
|
||||
fn from_syntax_node(source: &str, node: tree_sitter::Node, context: &Map) -> Result<Self> {
|
||||
Error::expect_syntax_node(source, "index_expression", node)?;
|
||||
|
||||
let first_child = node.child(0).unwrap();
|
||||
let child = if first_child.is_named() {
|
||||
first_child
|
||||
} else {
|
||||
node.child(1).unwrap()
|
||||
};
|
||||
|
||||
let abstract_node = match child.kind() {
|
||||
"value" => IndexExpression::Value(ValueNode::from_syntax_node(source, child, context)?),
|
||||
"identifier" => {
|
||||
IndexExpression::Identifier(Identifier::from_syntax_node(source, child, context)?)
|
||||
}
|
||||
"index" => {
|
||||
IndexExpression::Index(Box::new(Index::from_syntax_node(source, child, context)?))
|
||||
}
|
||||
"function_call" => IndexExpression::FunctionCall(Box::new(
|
||||
FunctionCall::from_syntax_node(source, child, context)?,
|
||||
)),
|
||||
_ => {
|
||||
return Err(Error::UnexpectedSyntaxNode {
|
||||
expected: "value, identifier, index or function call".to_string(),
|
||||
actual: child.kind().to_string(),
|
||||
location: child.start_position(),
|
||||
relevant_source: source[child.byte_range()].to_string(),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
Ok(abstract_node)
|
||||
}
|
||||
|
||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
||||
match self {
|
||||
IndexExpression::Value(value_node) => value_node.run(source, context),
|
||||
IndexExpression::Identifier(identifier) => identifier.run(source, context),
|
||||
IndexExpression::Index(index) => index.run(source, context),
|
||||
IndexExpression::FunctionCall(function_call) => function_call.run(source, context),
|
||||
}
|
||||
}
|
||||
|
||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
||||
match self {
|
||||
IndexExpression::Value(value_node) => value_node.expected_type(context),
|
||||
IndexExpression::Identifier(identifier) => identifier.expected_type(context),
|
||||
IndexExpression::Index(index) => index.expected_type(context),
|
||||
IndexExpression::FunctionCall(function_call) => function_call.expected_type(context),
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ pub mod identifier;
|
||||
pub mod if_else;
|
||||
pub mod index;
|
||||
pub mod index_assignment;
|
||||
pub mod index_expression;
|
||||
pub mod logic;
|
||||
pub mod r#match;
|
||||
pub mod math;
|
||||
@ -27,8 +28,9 @@ pub mod r#yield;
|
||||
|
||||
pub use {
|
||||
assignment::*, block::*, expression::*, function_call::*, function_expression::*,
|
||||
identifier::*, if_else::*, index::*, index_assignment::IndexAssignment, logic::*, math::*,
|
||||
r#for::*, r#match::*, r#while::*, r#yield::*, statement::*, type_definition::*, value_node::*,
|
||||
identifier::*, if_else::*, index::*, index_assignment::IndexAssignment, index_expression::*,
|
||||
logic::*, math::*, r#for::*, r#match::*, r#while::*, r#yield::*, statement::*,
|
||||
type_definition::*, value_node::*,
|
||||
};
|
||||
|
||||
use tree_sitter::Node;
|
||||
|
@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
|
||||
use tree_sitter::Node;
|
||||
|
||||
use crate::{
|
||||
AbstractTree, Block, Error, Expression, Function, Identifier, List, Map, Result, Statement,
|
||||
Type, TypeDefinition, Value,
|
||||
value::BuiltInValue, AbstractTree, Block, Error, Expression, Function, Identifier, List, Map,
|
||||
Result, Statement, Type, TypeDefinition, Value,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
@ -18,6 +18,7 @@ pub enum ValueNode {
|
||||
List(Vec<Expression>),
|
||||
Option(Option<Box<Expression>>),
|
||||
Map(BTreeMap<String, (Statement, Option<Type>)>),
|
||||
BuiltInValue(BuiltInValue),
|
||||
}
|
||||
|
||||
impl AbstractTree for ValueNode {
|
||||
@ -150,6 +151,15 @@ impl AbstractTree for ValueNode {
|
||||
ValueNode::Option(Some(Box::new(expression)))
|
||||
}
|
||||
}
|
||||
"built_in_value" => {
|
||||
let built_in_value_node = child.child(0).unwrap();
|
||||
|
||||
ValueNode::BuiltInValue(BuiltInValue::from_syntax_node(
|
||||
source,
|
||||
built_in_value_node,
|
||||
context,
|
||||
)?)
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::UnexpectedSyntaxNode {
|
||||
expected: "string, integer, float, boolean, list, map, or option".to_string(),
|
||||
@ -203,6 +213,7 @@ impl AbstractTree for ValueNode {
|
||||
|
||||
Value::Map(map)
|
||||
}
|
||||
ValueNode::BuiltInValue(built_in_value) => built_in_value.run(source, context)?,
|
||||
};
|
||||
|
||||
Ok(value)
|
||||
@ -244,6 +255,7 @@ impl AbstractTree for ValueNode {
|
||||
}
|
||||
}
|
||||
ValueNode::Map(_) => Type::Map,
|
||||
ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?,
|
||||
};
|
||||
|
||||
Ok(r#type)
|
||||
|
@ -223,5 +223,6 @@ fn display_value(value: &Value, ui: &mut egui::Ui) {
|
||||
ui.label("none");
|
||||
}
|
||||
},
|
||||
Value::BuiltIn(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
@ -11,14 +11,13 @@ mod option;
|
||||
mod output;
|
||||
mod packages;
|
||||
mod random;
|
||||
mod std;
|
||||
mod r#type;
|
||||
|
||||
/// All built-in functions recognized by the interpreter.
|
||||
///
|
||||
/// This is the public interface to access built-in functions by iterating over
|
||||
/// the references it holds.
|
||||
pub const BUILT_IN_FUNCTIONS: [&dyn BuiltInFunction; 22] = [
|
||||
pub const BUILT_IN_FUNCTIONS: [&dyn BuiltInFunction; 21] = [
|
||||
&assert::Assert,
|
||||
&assert::AssertEqual,
|
||||
&collections::Length,
|
||||
@ -39,7 +38,6 @@ pub const BUILT_IN_FUNCTIONS: [&dyn BuiltInFunction; 22] = [
|
||||
&random::RandomBoolean,
|
||||
&random::RandomFloat,
|
||||
&random::RandomInteger,
|
||||
&std::Std,
|
||||
&r#type::TypeFunction,
|
||||
];
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use crate::{interpret_with_context, BuiltInFunction, Error, Map, Result, Type, Value};
|
||||
|
||||
static STD: OnceLock<Map> = OnceLock::new();
|
||||
|
||||
pub struct Std;
|
||||
|
||||
impl BuiltInFunction for Std {
|
||||
fn name(&self) -> &'static str {
|
||||
"std"
|
||||
}
|
||||
|
||||
fn run(&self, arguments: &[Value], _context: &Map) -> Result<Value> {
|
||||
Error::expect_argument_amount(self, 0, arguments.len())?;
|
||||
|
||||
let std_context = STD.get_or_init(|| {
|
||||
let std_source = "say_hi = () <none> { output('hi') }";
|
||||
let std_context = Map::new();
|
||||
|
||||
interpret_with_context(std_source, std_context.clone()).unwrap();
|
||||
|
||||
std_context
|
||||
});
|
||||
|
||||
Ok(Value::Map(std_context.clone()))
|
||||
}
|
||||
|
||||
fn r#type(&self) -> Type {
|
||||
Type::Function {
|
||||
parameter_types: vec![],
|
||||
return_type: Box::new(Type::Map),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
//! Types that represent runtime values.
|
||||
use crate::{
|
||||
error::{Error, Result},
|
||||
Function, List, Map, Type,
|
||||
interpret_with_context, AbstractTree, Function, List, Map, Type,
|
||||
};
|
||||
|
||||
use serde::{
|
||||
@ -9,6 +9,7 @@ use serde::{
|
||||
ser::SerializeTuple,
|
||||
Deserialize, Serialize, Serializer,
|
||||
};
|
||||
use tree_sitter::Node;
|
||||
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
@ -16,12 +17,60 @@ use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
marker::PhantomData,
|
||||
ops::{Add, AddAssign, Div, Mul, Rem, Sub, SubAssign},
|
||||
sync::OnceLock,
|
||||
};
|
||||
|
||||
pub mod function;
|
||||
pub mod list;
|
||||
pub mod map;
|
||||
|
||||
static STD: OnceLock<Value> = OnceLock::new();
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub enum BuiltInValue {
|
||||
Std,
|
||||
}
|
||||
|
||||
impl BuiltInValue {
|
||||
fn r#type(&self) -> Type {
|
||||
match self {
|
||||
BuiltInValue::Std => Type::Map,
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self) -> &Value {
|
||||
STD.get_or_init(|| {
|
||||
let std_source = "foobar = () <str> { 'foobar' }";
|
||||
let std_context = Map::new();
|
||||
|
||||
interpret_with_context(std_source, std_context.clone()).unwrap();
|
||||
|
||||
Value::Map(std_context)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractTree for BuiltInValue {
|
||||
fn from_syntax_node(_source: &str, node: Node, _context: &Map) -> Result<Self> {
|
||||
let built_in_value = match node.kind() {
|
||||
"std" => BuiltInValue::Std,
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
Ok(built_in_value)
|
||||
}
|
||||
|
||||
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
|
||||
Ok(self.get().clone())
|
||||
}
|
||||
|
||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
||||
match self {
|
||||
BuiltInValue::Std => Ok(Type::Map),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dust value representation.
|
||||
///
|
||||
/// Every dust variable has a key and a Value. Variables are represented by
|
||||
@ -37,6 +86,7 @@ pub enum Value {
|
||||
Integer(i64),
|
||||
Boolean(bool),
|
||||
Option(Option<Box<Value>>),
|
||||
BuiltIn(BuiltInValue),
|
||||
}
|
||||
|
||||
impl Default for Value {
|
||||
@ -82,6 +132,7 @@ impl Value {
|
||||
Type::None
|
||||
}
|
||||
}
|
||||
Value::BuiltIn(built_in_value) => built_in_value.r#type(),
|
||||
};
|
||||
|
||||
r#type
|
||||
@ -420,6 +471,8 @@ impl PartialOrd for Value {
|
||||
impl Ord for Value {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
match (self, other) {
|
||||
(Value::BuiltIn(left), Value::BuiltIn(right)) => left.cmp(right),
|
||||
(Value::BuiltIn(_), _) => Ordering::Greater,
|
||||
(Value::String(left), Value::String(right)) => left.cmp(right),
|
||||
(Value::String(_), _) => Ordering::Greater,
|
||||
(Value::Float(left), Value::Float(right)) => left.total_cmp(right),
|
||||
@ -471,6 +524,7 @@ impl Serialize for Value {
|
||||
Value::Option(inner) => inner.serialize(serializer),
|
||||
Value::Map(inner) => inner.serialize(serializer),
|
||||
Value::Function(inner) => inner.serialize(serializer),
|
||||
Value::BuiltIn(inner) => inner.serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -498,6 +552,7 @@ impl Display for Value {
|
||||
}
|
||||
Value::Map(map) => write!(f, "{map}"),
|
||||
Value::Function(function) => write!(f, "{function}"),
|
||||
Value::BuiltIn(_) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ mod index {
|
||||
"
|
||||
x = [1 2 3]
|
||||
y = () <int> { 2 }
|
||||
x:y()
|
||||
x:(y())
|
||||
",
|
||||
),
|
||||
Ok(Value::Integer(3))
|
||||
@ -356,7 +356,7 @@ mod index {
|
||||
x = {
|
||||
y = () <int> { 2 }
|
||||
}
|
||||
(x:y)()
|
||||
x:y()
|
||||
",
|
||||
),
|
||||
Ok(Value::Integer(2))
|
||||
|
@ -46,9 +46,9 @@ x:y = 1
|
||||
(statement
|
||||
(index_assignment
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(identifier))
|
||||
(expression
|
||||
(index_expression
|
||||
(identifier)))
|
||||
(assignment_operator)
|
||||
(statement
|
||||
@ -68,9 +68,9 @@ x:9 = 'foobar'
|
||||
(statement
|
||||
(index_assignment
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(identifier))
|
||||
(expression
|
||||
(index_expression
|
||||
(value
|
||||
(integer))))
|
||||
(assignment_operator)
|
||||
|
@ -84,17 +84,17 @@ foo:bar("Hiya")
|
||||
|
||||
(root
|
||||
(statement
|
||||
(expression
|
||||
(index
|
||||
(expression
|
||||
(identifier))
|
||||
(expression
|
||||
(function_call
|
||||
(function_expression
|
||||
(index
|
||||
(index_expression
|
||||
(identifier))
|
||||
(index_expression
|
||||
(identifier))))
|
||||
(expression
|
||||
(value
|
||||
(string)))))))))
|
||||
(string)))))))
|
||||
|
||||
================================================================================
|
||||
Double Function Call
|
||||
|
@ -14,33 +14,33 @@ foobar:1:42
|
||||
(statement
|
||||
(expression
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(identifier))
|
||||
(expression
|
||||
(index_expression
|
||||
(value
|
||||
(integer)))))
|
||||
(expression
|
||||
(index_expression
|
||||
(identifier)))))
|
||||
(statement
|
||||
(expression
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(identifier))
|
||||
(expression
|
||||
(index_expression
|
||||
(identifier)))))
|
||||
(statement
|
||||
(expression
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(identifier))
|
||||
(expression
|
||||
(index_expression
|
||||
(value
|
||||
(integer)))))
|
||||
(expression
|
||||
(index_expression
|
||||
(value
|
||||
(integer)))))))
|
||||
|
||||
@ -56,11 +56,11 @@ Nested Indexes
|
||||
(statement
|
||||
(expression
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(value
|
||||
(list
|
||||
(expression
|
||||
@ -78,13 +78,13 @@ Nested Indexes
|
||||
(expression
|
||||
(value
|
||||
(integer))))))
|
||||
(expression
|
||||
(index_expression
|
||||
(value
|
||||
(integer)))))
|
||||
(expression
|
||||
(index_expression
|
||||
(value
|
||||
(integer)))))
|
||||
(expression
|
||||
(index_expression
|
||||
(value
|
||||
(integer)))
|
||||
(expression
|
||||
@ -95,7 +95,7 @@ Nested Indexes
|
||||
Function Call Index
|
||||
================================================================================
|
||||
|
||||
x:y():0
|
||||
x:(y()):0
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -103,14 +103,14 @@ x:y():0
|
||||
(statement
|
||||
(expression
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(index
|
||||
(expression
|
||||
(index_expression
|
||||
(identifier))
|
||||
(expression
|
||||
(index_expression
|
||||
(function_call
|
||||
(function_expression
|
||||
(identifier))))))
|
||||
(expression
|
||||
(index_expression
|
||||
(value
|
||||
(integer)))))))
|
||||
|
@ -89,6 +89,7 @@ module.exports = grammar({
|
||||
$.list,
|
||||
$.map,
|
||||
$.option,
|
||||
$.built_in_value,
|
||||
),
|
||||
|
||||
integer: $ =>
|
||||
@ -202,15 +203,30 @@ module.exports = grammar({
|
||||
prec.left(
|
||||
1,
|
||||
seq(
|
||||
$.expression,
|
||||
$.index_expression,
|
||||
':',
|
||||
$.expression,
|
||||
$.index_expression,
|
||||
optional(
|
||||
seq('..', $.expression),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
index_expression: $ =>
|
||||
prec(
|
||||
1,
|
||||
choice(
|
||||
seq(
|
||||
'(',
|
||||
$.function_call,
|
||||
')',
|
||||
),
|
||||
$.identifier,
|
||||
$.index,
|
||||
$.value,
|
||||
),
|
||||
),
|
||||
|
||||
math: $ =>
|
||||
prec.left(
|
||||
seq(
|
||||
@ -388,8 +404,9 @@ module.exports = grammar({
|
||||
|
||||
_function_expression_kind: $ =>
|
||||
prec(
|
||||
1,
|
||||
2,
|
||||
choice(
|
||||
$.built_in_value,
|
||||
$.function,
|
||||
$.function_call,
|
||||
$.identifier,
|
||||
@ -397,6 +414,7 @@ module.exports = grammar({
|
||||
$.yield,
|
||||
),
|
||||
),
|
||||
|
||||
function_call: $ =>
|
||||
prec.right(
|
||||
seq(
|
||||
@ -447,5 +465,7 @@ module.exports = grammar({
|
||||
'to_json',
|
||||
'write',
|
||||
),
|
||||
|
||||
built_in_value: $ => choice('std'),
|
||||
},
|
||||
});
|
||||
|
@ -253,6 +253,10 @@
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "option"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "built_in_value"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -605,7 +609,7 @@
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expression"
|
||||
"name": "index_expression"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
@ -613,7 +617,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expression"
|
||||
"name": "index_expression"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
@ -639,6 +643,44 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"index_expression": {
|
||||
"type": "PREC",
|
||||
"value": 1,
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "("
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "function_call"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ")"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "index"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"math": {
|
||||
"type": "PREC_LEFT",
|
||||
"value": 0,
|
||||
@ -1258,10 +1300,14 @@
|
||||
},
|
||||
"_function_expression_kind": {
|
||||
"type": "PREC",
|
||||
"value": 1,
|
||||
"value": 2,
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "built_in_value"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "function"
|
||||
@ -1448,6 +1494,15 @@
|
||||
"value": "write"
|
||||
}
|
||||
]
|
||||
},
|
||||
"built_in_value": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "std"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"extras": [
|
||||
|
@ -56,6 +56,11 @@
|
||||
"named": true,
|
||||
"fields": {}
|
||||
},
|
||||
{
|
||||
"type": "built_in_value",
|
||||
"named": true,
|
||||
"fields": {}
|
||||
},
|
||||
{
|
||||
"type": "else",
|
||||
"named": true,
|
||||
@ -202,6 +207,10 @@
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "built_in_value",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"named": true
|
||||
@ -293,6 +302,10 @@
|
||||
{
|
||||
"type": "expression",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "index_expression",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -320,6 +333,33 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "index_expression",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "function_call",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "index",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "value",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"named": true,
|
||||
@ -559,6 +599,10 @@
|
||||
"type": "boolean",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "built_in_value",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "float",
|
||||
"named": true
|
||||
@ -884,6 +928,10 @@
|
||||
"type": "some",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "std",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "str",
|
||||
"named": false
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user