Fix parser

This commit is contained in:
Jeff 2024-03-17 06:26:12 -04:00
parent 46419956bd
commit 0e2d1021cb
10 changed files with 279 additions and 244 deletions

View File

@ -3,15 +3,15 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractTree, Action, Statement, Type}; use super::{AbstractTree, Action, Positioned, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Block { pub struct Block {
statements: Vec<Statement>, statements: Vec<Positioned<Statement>>,
} }
impl Block { impl Block {
pub fn new(statements: Vec<Statement>) -> Self { pub fn new(statements: Vec<Positioned<Statement>>) -> Self {
Self { statements } Self { statements }
} }
} }
@ -19,7 +19,7 @@ impl Block {
impl AbstractTree for Block { impl AbstractTree for Block {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> { fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
if let Some(statement) = self.statements.last() { if let Some(statement) = self.statements.last() {
statement.expected_type(_context) statement.node.expected_type(_context)
} else { } else {
Ok(Type::None) Ok(Type::None)
} }
@ -27,7 +27,7 @@ impl AbstractTree for Block {
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
for statement in &self.statements { for statement in &self.statements {
statement.validate(_context)?; statement.node.validate(_context)?;
} }
Ok(()) Ok(())
@ -37,7 +37,7 @@ impl AbstractTree for Block {
let mut previous = Action::None; let mut previous = Action::None;
for statement in self.statements { for statement in self.statements {
let action = statement.run(_context)?; let action = statement.node.run(_context)?;
previous = match action { previous = match action {
Action::Return(value) => Action::Return(value), Action::Return(value) => Action::Return(value),
Action::None => Action::None, Action::None => Action::None,
@ -62,14 +62,17 @@ mod tests {
fn run_returns_value_of_final_statement() { fn run_returns_value_of_final_statement() {
let block = Block::new(vec![ let block = Block::new(vec![
Statement::Expression( Statement::Expression(
Expression::Value(ValueNode::Integer(1)).positioned((0..1).into()), Expression::Value(ValueNode::Integer(1)).positioned((0..0).into()),
), )
.positioned((0..0).into()),
Statement::Expression( Statement::Expression(
Expression::Value(ValueNode::Integer(2)).positioned((0..1).into()), Expression::Value(ValueNode::Integer(2)).positioned((0..0).into()),
), )
.positioned((0..0).into()),
Statement::Expression( Statement::Expression(
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()), Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
), )
.positioned((0..0).into()),
]); ]);
assert_eq!( assert_eq!(
@ -83,10 +86,12 @@ mod tests {
let block = Block::new(vec![ let block = Block::new(vec![
Statement::Expression( Statement::Expression(
Expression::Value(ValueNode::String("42".to_string())).positioned((0..0).into()), Expression::Value(ValueNode::String("42".to_string())).positioned((0..0).into()),
), )
.positioned((0..0).into()),
Statement::Expression( Statement::Expression(
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()), Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
), )
.positioned((0..0).into()),
]); ]);
assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer)) assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer))

View File

@ -3,16 +3,16 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractTree, Action, Expression, Type}; use super::{AbstractTree, Action, Expression, Positioned, Type};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct FunctionCall { pub struct FunctionCall {
function: Box<Expression>, function: Box<Positioned<Expression>>,
arguments: Vec<Expression>, arguments: Vec<Positioned<Expression>>,
} }
impl FunctionCall { impl FunctionCall {
pub fn new(function: Expression, arguments: Vec<Expression>) -> Self { pub fn new(function: Positioned<Expression>, arguments: Vec<Positioned<Expression>>) -> Self {
FunctionCall { FunctionCall {
function: Box::new(function), function: Box::new(function),
arguments, arguments,
@ -22,7 +22,7 @@ impl FunctionCall {
impl AbstractTree for FunctionCall { impl AbstractTree for FunctionCall {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> { fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
if let Type::Function { return_type, .. } = self.function.expected_type(_context)? { if let Type::Function { return_type, .. } = self.function.node.expected_type(_context)? {
Ok(*return_type) Ok(*return_type)
} else { } else {
Err(ValidationError::ExpectedFunction) Err(ValidationError::ExpectedFunction)
@ -30,7 +30,7 @@ impl AbstractTree for FunctionCall {
} }
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
if let Type::Function { .. } = self.function.expected_type(_context)? { if let Type::Function { .. } = self.function.node.expected_type(_context)? {
Ok(()) Ok(())
} else { } else {
Err(ValidationError::ExpectedFunction) Err(ValidationError::ExpectedFunction)
@ -38,12 +38,12 @@ impl AbstractTree for FunctionCall {
} }
fn run(self, context: &Context) -> Result<Action, RuntimeError> { fn run(self, context: &Context) -> Result<Action, RuntimeError> {
let value = self.function.run(context)?.as_return_value()?; let value = self.function.node.run(context)?.as_return_value()?;
let function = value.as_function()?; let function = value.as_function()?;
let mut arguments = Vec::with_capacity(self.arguments.len()); let mut arguments = Vec::with_capacity(self.arguments.len());
for expression in self.arguments { for expression in self.arguments {
let value = expression.run(context)?.as_return_value()?; let value = expression.node.run(context)?.as_return_value()?;
arguments.push(value); arguments.push(value);
} }

View File

@ -87,7 +87,8 @@ mod tests {
Block::new(vec![Statement::Expression( Block::new(vec![Statement::Expression(
Expression::Value(ValueNode::String("foo".to_string())) Expression::Value(ValueNode::String("foo".to_string()))
.positioned((0..0).into()) .positioned((0..0).into())
)]) )
.positioned((0..0).into())])
.positioned((0..0).into()), .positioned((0..0).into()),
None None
) )
@ -104,13 +105,15 @@ mod tests {
Block::new(vec![Statement::Expression( Block::new(vec![Statement::Expression(
Expression::Value(ValueNode::String("foo".to_string())) Expression::Value(ValueNode::String("foo".to_string()))
.positioned((0..0).into()) .positioned((0..0).into())
)]) )
.positioned((0..0).into())])
.positioned((0..0).into()), .positioned((0..0).into()),
Some( Some(
Block::new(vec![Statement::Expression( Block::new(vec![Statement::Expression(
Expression::Value(ValueNode::String("bar".to_string())) Expression::Value(ValueNode::String("bar".to_string()))
.positioned((0..0).into()) .positioned((0..0).into())
)]) )
.positioned((0..0).into())])
.positioned((0..0).into()) .positioned((0..0).into())
) )
) )

View File

@ -3,28 +3,28 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractTree, Action, Expression, Type, ValueNode}; use super::{AbstractTree, Action, Expression, Positioned, Type, ValueNode};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Index { pub struct Index {
left: Expression, left: Positioned<Expression>,
right: Expression, right: Positioned<Expression>,
} }
impl Index { impl Index {
pub fn new(left: Expression, right: Expression) -> Self { pub fn new(left: Positioned<Expression>, right: Positioned<Expression>) -> Self {
Self { left, right } Self { left, right }
} }
} }
impl AbstractTree for Index { impl AbstractTree for Index {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> { fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
let left_type = self.left.expected_type(_context)?; let left_type = self.left.node.expected_type(_context)?;
if let ( if let (
Expression::Value(ValueNode::List(expression_list)), Expression::Value(ValueNode::List(expression_list)),
Expression::Value(ValueNode::Integer(index)), Expression::Value(ValueNode::Integer(index)),
) = (&self.left, &self.right) ) = (&self.left.node, &self.right.node)
{ {
let expression = if let Some(expression) = expression_list.get(*index as usize) { let expression = if let Some(expression) = expression_list.get(*index as usize) {
expression expression
@ -32,20 +32,20 @@ impl AbstractTree for Index {
return Ok(Type::None); return Ok(Type::None);
}; };
expression.expected_type(_context) expression.node.expected_type(_context)
} else { } else {
Err(ValidationError::CannotIndex(left_type)) Err(ValidationError::CannotIndex(left_type))
} }
} }
fn validate(&self, context: &Context) -> Result<(), ValidationError> { fn validate(&self, context: &Context) -> Result<(), ValidationError> {
let left_type = self.left.expected_type(context)?; let left_type = self.left.node.expected_type(context)?;
match left_type { match left_type {
Type::List => todo!(), Type::List => todo!(),
Type::ListOf(_) => todo!(), Type::ListOf(_) => todo!(),
Type::ListExact(_) => { Type::ListExact(_) => {
let right_type = self.right.expected_type(context)?; let right_type = self.right.node.expected_type(context)?;
if let Type::Integer = right_type { if let Type::Integer = right_type {
Ok(()) Ok(())
@ -58,8 +58,8 @@ impl AbstractTree for Index {
} }
fn run(self, _context: &Context) -> Result<Action, RuntimeError> { fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
let left_value = self.left.run(_context)?.as_return_value()?; let left_value = self.left.node.run(_context)?.as_return_value()?;
let right_value = self.right.run(_context)?.as_return_value()?; let right_value = self.right.node.run(_context)?.as_return_value()?;
if let (Some(list), Some(index)) = (left_value.as_list(), right_value.as_integer()) { if let (Some(list), Some(index)) = (left_value.as_list(), right_value.as_integer()) {
let found_item = list.get(index as usize); let found_item = list.get(index as usize);

View File

@ -3,15 +3,15 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractTree, Action, Statement, Type}; use super::{AbstractTree, Action, Positioned, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Loop { pub struct Loop {
statements: Vec<Statement>, statements: Vec<Positioned<Statement>>,
} }
impl Loop { impl Loop {
pub fn new(statements: Vec<Statement>) -> Self { pub fn new(statements: Vec<Positioned<Statement>>) -> Self {
Self { statements } Self { statements }
} }
} }
@ -23,7 +23,7 @@ impl AbstractTree for Loop {
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
for statement in &self.statements { for statement in &self.statements {
statement.validate(_context)?; statement.node.validate(_context)?;
} }
Ok(()) Ok(())
@ -40,7 +40,7 @@ impl AbstractTree for Loop {
} }
let statement = self.statements[index].clone(); let statement = self.statements[index].clone();
let action = statement.run(_context)?; let action = statement.node.run(_context)?;
match action { match action {
Action::Return(_) => {} Action::Return(_) => {}
@ -58,7 +58,7 @@ mod tests {
#[test] #[test]
fn basic_loop() { fn basic_loop() {
let result = Loop { let result = Loop {
statements: vec![Statement::Break], statements: vec![Statement::Break.positioned((0..0).into())],
} }
.run(&Context::new()); .run(&Context::new());

View File

@ -5,15 +5,15 @@ use crate::{
Value, Value,
}; };
use super::{AbstractTree, Action, Expression, Type}; use super::{AbstractTree, Action, Expression, Positioned, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Math { pub enum Math {
Add(Expression, Expression), Add(Positioned<Expression>, Positioned<Expression>),
Subtract(Expression, Expression), Subtract(Positioned<Expression>, Positioned<Expression>),
Multiply(Expression, Expression), Multiply(Positioned<Expression>, Positioned<Expression>),
Divide(Expression, Expression), Divide(Positioned<Expression>, Positioned<Expression>),
Modulo(Expression, Expression), Modulo(Positioned<Expression>, Positioned<Expression>),
} }
impl AbstractTree for Math { impl AbstractTree for Math {
@ -23,7 +23,7 @@ impl AbstractTree for Math {
| Math::Subtract(left, _) | Math::Subtract(left, _)
| Math::Multiply(left, _) | Math::Multiply(left, _)
| Math::Divide(left, _) | Math::Divide(left, _)
| Math::Modulo(left, _) => left.expected_type(_context), | Math::Modulo(left, _) => left.node.expected_type(_context),
} }
} }
@ -34,8 +34,8 @@ impl AbstractTree for Math {
| Math::Multiply(left, right) | Math::Multiply(left, right)
| Math::Divide(left, right) | Math::Divide(left, right)
| Math::Modulo(left, right) => { | Math::Modulo(left, right) => {
let left_type = left.expected_type(context)?; let left_type = left.node.expected_type(context)?;
let right_type = right.expected_type(context)?; let right_type = right.node.expected_type(context)?;
match (left_type, right_type) { match (left_type, right_type) {
(Type::Integer, Type::Integer) (Type::Integer, Type::Integer)
@ -51,20 +51,20 @@ impl AbstractTree for Math {
fn run(self, _context: &Context) -> Result<Action, RuntimeError> { fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
let value = match self { let value = match self {
Math::Add(left, right) => { Math::Add(left, right) => {
let left_value = left.run(_context)?.as_return_value()?; let left_value = left.node.run(_context)?.as_return_value()?;
let right_value = right.run(_context)?.as_return_value()?; let right_value = right.node.run(_context)?.as_return_value()?;
left_value.add(&right_value)? left_value.add(&right_value)?
} }
Math::Subtract(left, right) => { Math::Subtract(left, right) => {
let left_value = left.run(_context)?.as_return_value()?; let left_value = left.node.run(_context)?.as_return_value()?;
let right_value = right.run(_context)?.as_return_value()?; let right_value = right.node.run(_context)?.as_return_value()?;
left_value.subtract(&right_value)? left_value.subtract(&right_value)?
} }
Math::Multiply(left, right) => { Math::Multiply(left, right) => {
let left_value = left.run(_context)?.as_return_value()?; let left_value = left.node.run(_context)?.as_return_value()?;
let right_value = right.run(_context)?.as_return_value()?; let right_value = right.node.run(_context)?.as_return_value()?;
if let (ValueInner::Integer(left), ValueInner::Integer(right)) = if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
(left_value.inner().as_ref(), right_value.inner().as_ref()) (left_value.inner().as_ref(), right_value.inner().as_ref())
@ -77,8 +77,8 @@ impl AbstractTree for Math {
} }
} }
Math::Divide(left, right) => { Math::Divide(left, right) => {
let left_value = left.run(_context)?.as_return_value()?; let left_value = left.node.run(_context)?.as_return_value()?;
let right_value = right.run(_context)?.as_return_value()?; let right_value = right.node.run(_context)?.as_return_value()?;
if let (ValueInner::Integer(left), ValueInner::Integer(right)) = if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
(left_value.inner().as_ref(), right_value.inner().as_ref()) (left_value.inner().as_ref(), right_value.inner().as_ref())
@ -91,8 +91,8 @@ impl AbstractTree for Math {
} }
} }
Math::Modulo(left, right) => { Math::Modulo(left, right) => {
let left_value = left.run(_context)?.as_return_value()?; let left_value = left.node.run(_context)?.as_return_value()?;
let right_value = right.run(_context)?.as_return_value()?; let right_value = right.node.run(_context)?.as_return_value()?;
if let (ValueInner::Integer(left), ValueInner::Integer(right)) = if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
(left_value.inner().as_ref(), right_value.inner().as_ref()) (left_value.inner().as_ref(), right_value.inner().as_ref())

View File

@ -2,7 +2,7 @@ use std::{cmp::Ordering, collections::BTreeMap, ops::Range};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, TypeConflict, ValidationError}, error::{RuntimeError, ValidationError},
Value, Value,
}; };
@ -13,12 +13,12 @@ pub enum ValueNode {
Boolean(bool), Boolean(bool),
Float(f64), Float(f64),
Integer(i64), Integer(i64),
List(Vec<Expression>), List(Vec<Positioned<Expression>>),
Map(Vec<(Identifier, Option<Positioned<Type>>, Positioned<Expression>)>), Map(Vec<(Identifier, Option<Positioned<Type>>, Positioned<Expression>)>),
Range(Range<i64>), Range(Range<i64>),
String(String), String(String),
Function { Function {
parameters: Vec<(Identifier, Type)>, parameters: Vec<(Identifier, Positioned<Type>)>,
return_type: Positioned<Type>, return_type: Positioned<Type>,
body: Positioned<Block>, body: Positioned<Block>,
}, },
@ -34,7 +34,7 @@ impl AbstractTree for ValueNode {
let mut item_types = Vec::with_capacity(items.len()); let mut item_types = Vec::with_capacity(items.len());
for expression in items { for expression in items {
item_types.push(expression.expected_type(_context)?); item_types.push(expression.node.expected_type(_context)?);
} }
Type::ListExact(item_types) Type::ListExact(item_types)
@ -49,8 +49,7 @@ impl AbstractTree for ValueNode {
} => Type::Function { } => Type::Function {
parameter_types: parameters parameter_types: parameters
.into_iter() .into_iter()
.map(|(_, r#type)| r#type) .map(|(_, r#type)| r#type.node.clone())
.cloned()
.collect(), .collect(),
return_type: Box::new(return_type.node.clone()), return_type: Box::new(return_type.node.clone()),
}, },
@ -85,7 +84,7 @@ impl AbstractTree for ValueNode {
let function_context = Context::inherit_types_from(context)?; let function_context = Context::inherit_types_from(context)?;
for (identifier, r#type) in parameters { for (identifier, r#type) in parameters {
function_context.set_type(identifier.clone(), r#type.clone())?; function_context.set_type(identifier.clone(), r#type.node.clone())?;
} }
body.node.validate(&function_context)?; body.node.validate(&function_context)?;
@ -114,7 +113,7 @@ impl AbstractTree for ValueNode {
let mut value_list = Vec::with_capacity(expression_list.len()); let mut value_list = Vec::with_capacity(expression_list.len());
for expression in expression_list { for expression in expression_list {
let value = expression.run(_context)?.as_return_value()?; let value = expression.node.run(_context)?.as_return_value()?;
value_list.push(value); value_list.push(value);
} }

View File

@ -3,16 +3,16 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractTree, Action, Block, Expression, Type}; use super::{AbstractTree, Action, Block, Expression, Positioned, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct While { pub struct While {
expression: Expression, expression: Positioned<Expression>,
block: Block, block: Block,
} }
impl While { impl While {
pub fn new(expression: Expression, block: Block) -> Self { pub fn new(expression: Positioned<Expression>, block: Block) -> Self {
Self { expression, block } Self { expression, block }
} }
} }
@ -23,13 +23,14 @@ impl AbstractTree for While {
} }
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
self.expression.validate(_context)?; self.expression.node.validate(_context)?;
self.block.validate(_context) self.block.validate(_context)
} }
fn run(self, context: &Context) -> Result<Action, RuntimeError> { fn run(self, context: &Context) -> Result<Action, RuntimeError> {
while self while self
.expression .expression
.node
.clone() .clone()
.run(context)? .run(context)?
.as_return_value()? .as_return_value()?

View File

@ -1,6 +1,7 @@
use std::{cell::RefCell, collections::HashMap}; use std::{cell::RefCell, collections::HashMap};
use chumsky::{input::SpannedInput, pratt::*, prelude::*}; use chumsky::{input::SpannedInput, pratt::*, prelude::*};
use clap::builder::TypedValueParser;
use crate::{ use crate::{
abstract_tree::*, abstract_tree::*,
@ -53,12 +54,12 @@ pub fn parser<'src>() -> DustParser<'src> {
Token::Float(float) => ValueNode::Float(float), Token::Float(float) => ValueNode::Float(float),
Token::String(string) => ValueNode::String(string.to_string()), Token::String(string) => ValueNode::String(string.to_string()),
} }
.map(|value| Expression::Value(value)) .map_with(|value, state| Expression::Value(value).positioned(state.span()))
.boxed(); .boxed();
let type_specification = recursive(|type_specification| { let r#type = recursive(|r#type| {
let r#type = recursive(|r#type| { let type_specification = recursive(|r#type| {
let function_type = type_specification let function_type = r#type
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Control(Control::Comma)))
.collect() .collect()
@ -108,11 +109,9 @@ pub fn parser<'src>() -> DustParser<'src> {
)) ))
}); });
just(Token::Control(Control::Colon)).ignore_then(r#type) just(Token::Control(Control::Colon)).ignore_then(type_specification)
}); })
.map_with(|r#type, state| r#type.positioned(state.span()));
let positioned_type =
type_specification.map_with(|r#type, state| r#type.positioned(state.span()));
let statement = recursive(|statement| { let statement = recursive(|statement| {
let block = statement let block = statement
@ -130,10 +129,9 @@ pub fn parser<'src>() -> DustParser<'src> {
.map_with(|block, state| block.positioned(state.span())); .map_with(|block, state| block.positioned(state.span()));
let expression = recursive(|expression| { let expression = recursive(|expression| {
let identifier_expression = identifier let identifier_expression = identifier.clone().map_with(|identifier, state| {
.clone() Expression::Identifier(identifier).positioned(state.span())
.map(|identifier| Expression::Identifier(identifier)) });
.boxed();
let range = { let range = {
let raw_integer = select! { let raw_integer = select! {
@ -144,7 +142,9 @@ pub fn parser<'src>() -> DustParser<'src> {
.clone() .clone()
.then_ignore(just(Token::Control(Control::DoubleDot))) .then_ignore(just(Token::Control(Control::DoubleDot)))
.then(raw_integer) .then(raw_integer)
.map(|(start, end)| Expression::Value(ValueNode::Range(start..end))) .map_with(|(start, end), state| {
Expression::Value(ValueNode::Range(start..end)).positioned(state.span())
})
}; };
let list = expression let list = expression
@ -156,22 +156,16 @@ pub fn parser<'src>() -> DustParser<'src> {
just(Token::Control(Control::SquareOpen)), just(Token::Control(Control::SquareOpen)),
just(Token::Control(Control::SquareClose)), just(Token::Control(Control::SquareClose)),
) )
.map(|list| Expression::Value(ValueNode::List(list))) .map_with(|list, state| {
.boxed(); Expression::Value(ValueNode::List(list)).positioned(state.span())
});
let map_assignment = identifier let map_assignment = identifier
.clone() .clone()
.then( .then(r#type.clone().or_not())
type_specification
.map_with(|r#type, state| r#type.positioned(state.span()))
.clone()
.or_not(),
)
.then_ignore(just(Token::Operator(Operator::Assign))) .then_ignore(just(Token::Operator(Operator::Assign)))
.then(expression.clone()) .then(expression.clone())
.map_with(|((identifier, r#type), expression), state| { .map(|((identifier, r#type), expression)| (identifier, r#type, expression));
(identifier, r#type, expression.positioned(state.span()))
});
let map = map_assignment let map = map_assignment
.separated_by(just(Token::Control(Control::Comma)).or_not()) .separated_by(just(Token::Control(Control::Comma)).or_not())
@ -181,27 +175,29 @@ pub fn parser<'src>() -> DustParser<'src> {
just(Token::Control(Control::CurlyOpen)), just(Token::Control(Control::CurlyOpen)),
just(Token::Control(Control::CurlyClose)), just(Token::Control(Control::CurlyClose)),
) )
.map(|map_assigment_list| Expression::Value(ValueNode::Map(map_assigment_list))); .map_with(|map_assigment_list, state| {
Expression::Value(ValueNode::Map(map_assigment_list)).positioned(state.span())
});
let function = identifier let function = identifier
.clone() .clone()
.then(type_specification.clone()) .then(r#type.clone())
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Control(Control::Comma)))
.collect::<Vec<(Identifier, Type)>>() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::ParenOpen)), just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)), just(Token::Control(Control::ParenClose)),
) )
.then(type_specification.clone()) .then(r#type.clone())
.then(block.clone()) .then(block.clone())
.map_with(|((parameters, return_type), body), state| { .map_with(|((parameters, return_type), body), state| {
Expression::Value(ValueNode::Function { Expression::Value(ValueNode::Function {
parameters, parameters,
return_type: return_type.positioned(state.span()), return_type,
body: body.positioned(state.span()), body: body.positioned(state.span()),
}) })
}) .positioned(state.span())
.boxed(); });
let function_expression = choice((identifier_expression.clone(), function.clone())); let function_expression = choice((identifier_expression.clone(), function.clone()));
@ -216,13 +212,13 @@ pub fn parser<'src>() -> DustParser<'src> {
just(Token::Control(Control::ParenClose)), just(Token::Control(Control::ParenClose)),
), ),
) )
.map(|(function, arguments)| { .map_with(|(function, arguments), state| {
Expression::FunctionCall(FunctionCall::new(function, arguments)) Expression::FunctionCall(FunctionCall::new(function, arguments))
}) .positioned(state.span())
.boxed(); });
let atom = choice(( let atom = choice((
function_call, function_call.clone(),
identifier_expression.clone(), identifier_expression.clone(),
basic_value.clone(), basic_value.clone(),
list.clone(), list.clone(),
@ -230,68 +226,115 @@ pub fn parser<'src>() -> DustParser<'src> {
just(Token::Control(Control::ParenOpen)), just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)), just(Token::Control(Control::ParenClose)),
), ),
)) ));
.map_with(|expression, state| expression.positioned(state.span()));
use Operator::*; use Operator::*;
let logic_math_and_index = atom let logic_math_and_index = atom.pratt((
.pratt(( prefix(2, just(Token::Operator(Not)), |_, expression, span| {
prefix(2, just(Token::Operator(Not)), |expression| { Expression::Logic(Box::new(Logic::Not(expression))).positioned(span)
Expression::Logic(Box::new(Logic::Not(expression))) }),
}), infix(
infix(left(1), just(Token::Operator(Equal)), |left, right| { left(3),
Expression::Logic(Box::new(Logic::Equal(left, right))) just(Token::Control(Control::Dot)),
}), |left, _, right, span| {
infix(left(1), just(Token::Operator(NotEqual)), |left, right| { Expression::Index(Box::new(Index::new(left, right))).positioned(span)
Expression::Logic(Box::new(Logic::NotEqual(left, right))) },
}), ),
infix(left(1), just(Token::Operator(Greater)), |left, right| { infix(
Expression::Logic(Box::new(Logic::Greater(left, right))) left(1),
}), just(Token::Operator(Equal)),
infix(left(1), just(Token::Operator(Less)), |left, right| { |left, _, right, span| {
Expression::Logic(Box::new(Logic::Less(left, right))) Expression::Logic(Box::new(Logic::Equal(left, right))).positioned(span)
}), },
infix( ),
left(1), infix(
just(Token::Operator(GreaterOrEqual)), left(1),
|left, right| { just(Token::Operator(NotEqual)),
Expression::Logic(Box::new(Logic::GreaterOrEqual(left, right))) |left, _, right, span| {
}, Expression::Logic(Box::new(Logic::NotEqual(left, right))).positioned(span)
), },
infix( ),
left(1), infix(
just(Token::Operator(LessOrEqual)), left(1),
|left, right| Expression::Logic(Box::new(Logic::LessOrEqual(left, right))), just(Token::Operator(Greater)),
), |left, _, right, span| {
infix(left(1), just(Token::Operator(And)), |left, right| { Expression::Logic(Box::new(Logic::Greater(left, right))).positioned(span)
Expression::Logic(Box::new(Logic::And(left, right))) },
}), ),
infix(left(1), just(Token::Operator(Or)), |left, right| { infix(
Expression::Logic(Box::new(Logic::Or(left, right))) left(1),
}), just(Token::Operator(Less)),
infix(left(1), just(Token::Operator(Add)), |left, right| { |left, _, right, span| {
Expression::Math(Box::new(Math::Add(left, right))) Expression::Logic(Box::new(Logic::Less(left, right))).positioned(span)
}), },
infix(left(1), just(Token::Operator(Subtract)), |left, right| { ),
Expression::Math(Box::new(Math::Subtract(left, right))) infix(
}), left(1),
infix(left(2), just(Token::Operator(Multiply)), |left, right| { just(Token::Operator(GreaterOrEqual)),
Expression::Math(Box::new(Math::Multiply(left, right))) |left, _, right, span| {
}), Expression::Logic(Box::new(Logic::GreaterOrEqual(left, right)))
infix(left(2), just(Token::Operator(Divide)), |left, right| { .positioned(span)
Expression::Math(Box::new(Math::Divide(left, right))) },
}), ),
infix(left(1), just(Token::Operator(Modulo)), |left, right| { infix(
Expression::Math(Box::new(Math::Modulo(left, right))) left(1),
}), just(Token::Operator(LessOrEqual)),
infix( |left, _, right, span| {
left(3), Expression::Logic(Box::new(Logic::LessOrEqual(left, right)))
just(Token::Control(Control::Dot)), .positioned(span)
|left, right| Expression::Index(Box::new(Index::new(left, right))), },
), ),
)) infix(
.boxed(); left(1),
just(Token::Operator(And)),
|left, _, right, span| {
Expression::Logic(Box::new(Logic::And(left, right))).positioned(span)
},
),
infix(
left(1),
just(Token::Operator(Or)),
|left, _, right, span| {
Expression::Logic(Box::new(Logic::Or(left, right))).positioned(span)
},
),
infix(
left(1),
just(Token::Operator(Add)),
|left, _, right, span| {
Expression::Math(Box::new(Math::Add(left, right))).positioned(span)
},
),
infix(
left(1),
just(Token::Operator(Subtract)),
|left, _, right, span| {
Expression::Math(Box::new(Math::Subtract(left, right))).positioned(span)
},
),
infix(
left(2),
just(Token::Operator(Multiply)),
|left, _, right, span| {
Expression::Math(Box::new(Math::Multiply(left, right))).positioned(span)
},
),
infix(
left(2),
just(Token::Operator(Divide)),
|left, _, right, span| {
Expression::Math(Box::new(Math::Divide(left, right))).positioned(span)
},
),
infix(
left(1),
just(Token::Operator(Modulo)),
|left, _, right, span| {
Expression::Math(Box::new(Math::Modulo(left, right))).positioned(span)
},
),
));
choice(( choice((
function, function,
@ -303,25 +346,18 @@ pub fn parser<'src>() -> DustParser<'src> {
map, map,
basic_value, basic_value,
)) ))
.boxed()
}); });
let positioned_expression = expression let expression_statement = expression.clone().map_with(|expression, state| {
.clone() Statement::Expression(expression).positioned(state.span())
.map_with(|expression, state| expression.positioned(state.span())); });
let expression_statement = expression let r#break = just(Token::Keyword("break"))
.clone() .map_with(|_, state| Statement::Break.positioned(state.span()));
.map_with(|expression, state| {
Statement::Expression(expression.positioned(state.span()))
})
.boxed();
let r#break = just(Token::Keyword("break")).to(Statement::Break);
let assignment = identifier let assignment = identifier
.clone() .clone()
.then(positioned_type.clone().or_not()) .then(r#type.clone().or_not())
.then(choice(( .then(choice((
just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign), just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign),
just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign), just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign),
@ -329,18 +365,13 @@ pub fn parser<'src>() -> DustParser<'src> {
))) )))
.then(statement.clone()) .then(statement.clone())
.map_with(|(((identifier, r#type), operator), statement), state| { .map_with(|(((identifier, r#type), operator), statement), state| {
Statement::Assignment(Assignment::new( Statement::Assignment(Assignment::new(identifier, r#type, operator, statement))
identifier, .positioned(state.span())
r#type, });
operator,
statement.positioned(state.span()),
))
})
.boxed();
let block_statement = block let block_statement = block
.clone() .clone()
.map_with(|block, state| Statement::Block(block)); .map_with(|block, state| Statement::Block(block).positioned(state.span()));
let r#loop = statement let r#loop = statement
.clone() .clone()
@ -351,16 +382,19 @@ pub fn parser<'src>() -> DustParser<'src> {
just(Token::Keyword("loop")).then(just(Token::Control(Control::CurlyOpen))), just(Token::Keyword("loop")).then(just(Token::Control(Control::CurlyOpen))),
just(Token::Control(Control::CurlyClose)), just(Token::Control(Control::CurlyClose)),
) )
.map_with(|statements, state| Statement::Loop(Loop::new(statements))) .map_with(|statements, state| {
.boxed(); Statement::Loop(Loop::new(statements)).positioned(state.span())
});
let r#while = just(Token::Keyword("while")) let r#while = just(Token::Keyword("while"))
.ignore_then(expression.clone()) .ignore_then(expression.clone())
.then(block.clone()) .then(block.clone())
.map_with(|(expression, block), state| Statement::While(While::new(expression, block))); .map_with(|(expression, block), state| {
Statement::While(While::new(expression, block)).positioned(state.span())
});
let if_else = just(Token::Keyword("if")) let if_else = just(Token::Keyword("if"))
.ignore_then(positioned_expression.clone()) .ignore_then(expression.clone())
.then(positioned_block.clone()) .then(positioned_block.clone())
.then( .then(
just(Token::Keyword("else")) just(Token::Keyword("else"))
@ -369,8 +403,8 @@ pub fn parser<'src>() -> DustParser<'src> {
) )
.map_with(|((if_expression, if_block), else_block), state| { .map_with(|((if_expression, if_block), else_block), state| {
Statement::IfElse(IfElse::new(if_expression, if_block, else_block)) Statement::IfElse(IfElse::new(if_expression, if_block, else_block))
}) .positioned(state.span())
.boxed(); });
choice(( choice((
if_else, if_else,
@ -382,14 +416,9 @@ pub fn parser<'src>() -> DustParser<'src> {
r#while, r#while,
)) ))
.then_ignore(just(Token::Control(Control::Semicolon)).or_not()) .then_ignore(just(Token::Control(Control::Semicolon)).or_not())
.boxed()
}); });
statement statement.repeated().collect().boxed()
.map_with(|statement, state| statement.positioned(state.span()))
.repeated()
.collect()
.boxed()
} }
#[cfg(test)] #[cfg(test)]
@ -402,19 +431,19 @@ mod tests {
fn r#while() { fn r#while() {
assert_eq!( assert_eq!(
parse(&lex("while true { output('hi') }").unwrap()).unwrap()[0], parse(&lex("while true { output('hi') }").unwrap()).unwrap()[0],
Statement::r#while( Statement::While(While::new(
While::new( Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()),
Expression::Value(ValueNode::Boolean(true)), Block::new(vec![Statement::Expression(
Block::new(vec![Statement::expression( Expression::FunctionCall(FunctionCall::new(
Expression::FunctionCall(FunctionCall::new( Expression::Identifier(Identifier::new("output")).positioned((0..0).into()),
Expression::Identifier(Identifier::new("output")), vec![Expression::Value(ValueNode::String("hi".to_string()))
vec![Expression::Value(ValueNode::String("hi".to_string()))] .positioned((0..0).into())]
)), ))
(0..0).into() .positioned((0..0).into())
)]) )
), .positioned((0..0).into())])
(0..0).into() ))
) .positioned((0..0).into())
) )
} }
@ -422,35 +451,33 @@ mod tests {
fn types() { fn types() {
assert_eq!( assert_eq!(
parse(&lex("foobar : bool = true").unwrap()).unwrap()[0], parse(&lex("foobar : bool = true").unwrap()).unwrap()[0],
Statement::assignment( Statement::Assignment(Assignment::new(
Assignment::new( Identifier::new("foobar"),
Identifier::new("foobar"), Some(Type::Boolean.positioned((0..0).into())),
Some(Type::Boolean), AssignmentOperator::Assign,
AssignmentOperator::Assign, Statement::Expression(
Statement::expression( Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into())
Expression::Value(ValueNode::Boolean(true)), )
(0..0).into() .positioned((0..0).into())
) ),)
), .positioned((0..0).into())
(0..0).into()
)
); );
assert_eq!( assert_eq!(
parse(&lex("foobar : list(bool) = [true]").unwrap()).unwrap()[0], parse(&lex("foobar : list(bool) = [true]").unwrap()).unwrap()[0],
Statement::assignment( Statement::Assignment(Assignment::new(
Assignment::new( Identifier::new("foobar"),
Identifier::new("foobar"), Some(Type::ListOf(Box::new(Type::Boolean)).positioned((0..0).into())),
Some(Type::ListOf(Box::new(Type::Boolean))), AssignmentOperator::Assign,
AssignmentOperator::Assign, Statement::Expression(
Statement::expression( Expression::Value(ValueNode::List(vec![Expression::Value(
Expression::Value(ValueNode::List(vec![Expression::Value( ValueNode::Boolean(true)
ValueNode::Boolean(true)
)])),
(0..0).into()
) )
), .positioned((0..0).into())]))
(0..0).into() .positioned((0..0).into())
) )
.positioned((0..0).into())
))
.positioned((0..0).into())
); );
assert_eq!( assert_eq!(
parse(&lex("foobar : [bool, str] = [true, '42']").unwrap()).unwrap()[0], parse(&lex("foobar : [bool, str] = [true, '42']").unwrap()).unwrap()[0],

View File

@ -55,7 +55,7 @@ impl Value {
} }
pub fn function( pub fn function(
parameters: Vec<(Identifier, Type)>, parameters: Vec<(Identifier, Positioned<Type>)>,
return_type: Positioned<Type>, return_type: Positioned<Type>,
body: Positioned<Block>, body: Positioned<Block>,
) -> Self { ) -> Self {
@ -224,7 +224,7 @@ impl Display for Value {
write!(f, "(")?; write!(f, "(")?;
for (identifier, r#type) in parameters { for (identifier, r#type) in parameters {
write!(f, "{identifier}: {}", r#type)?; write!(f, "{identifier}: {}", r#type.node)?;
} }
write!(f, "): {} {:?}", return_type.node, body.node) write!(f, "): {} {:?}", return_type.node, body.node)
@ -330,7 +330,7 @@ impl Function {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct ParsedFunction { pub struct ParsedFunction {
parameters: Vec<(Identifier, Type)>, parameters: Vec<(Identifier, Positioned<Type>)>,
return_type: Positioned<Type>, return_type: Positioned<Type>,
body: Positioned<Block>, body: Positioned<Block>,
} }