Rework parser and abstract tree
This commit is contained in:
parent
fb7675a782
commit
4179f6ebe5
@ -1,15 +1,15 @@
|
||||
use crate::{error::RuntimeError, Context};
|
||||
use crate::{error::RuntimeError, value::Value, Context};
|
||||
|
||||
use super::{AbstractTree, Identifier, Statement, Value};
|
||||
use super::{AbstractTree, Identifier, Statement};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct Assignment {
|
||||
identifier: Identifier,
|
||||
statement: Box<Statement>,
|
||||
pub struct Assignment<'src> {
|
||||
identifier: Identifier<'src>,
|
||||
statement: Box<Statement<'src>>,
|
||||
}
|
||||
|
||||
impl Assignment {
|
||||
pub fn new(identifier: Identifier, statement: Statement) -> Self {
|
||||
impl<'src> Assignment<'src> {
|
||||
pub fn new(identifier: Identifier<'src>, statement: Statement<'src>) -> Self {
|
||||
Self {
|
||||
identifier,
|
||||
statement: Box::new(statement),
|
||||
@ -17,34 +17,36 @@ impl Assignment {
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractTree for Assignment {
|
||||
fn run(self, context: &Context) -> Result<Value, RuntimeError> {
|
||||
let value = self.statement.run(context)?;
|
||||
impl<'src> AbstractTree for Assignment<'src> {
|
||||
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
|
||||
todo!()
|
||||
// let value = self.statement.run(context)?;
|
||||
|
||||
context.set(self.identifier, value)?;
|
||||
// context.set(self.identifier, value)?;
|
||||
|
||||
Ok(Value::none())
|
||||
// Ok(Value::none())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
// use super::*;
|
||||
|
||||
#[test]
|
||||
fn assign_value() {
|
||||
let context = Context::new();
|
||||
todo!()
|
||||
// let context = Context::new();
|
||||
|
||||
Assignment::new(
|
||||
Identifier::new("foobar"),
|
||||
Statement::Value(Value::integer(42)),
|
||||
)
|
||||
.run(&context)
|
||||
.unwrap();
|
||||
// Assignment::new(
|
||||
// Identifier::new("foobar"),
|
||||
// Statement::Value(Value::integer(42)),
|
||||
// )
|
||||
// .run(&context)
|
||||
// .unwrap();
|
||||
|
||||
assert_eq!(
|
||||
context.get(&Identifier::new("foobar")).unwrap(),
|
||||
Some(Value::integer(42))
|
||||
)
|
||||
// assert_eq!(
|
||||
// context.get(&Identifier::new("foobar")).unwrap(),
|
||||
// Some(Value::integer(42))
|
||||
// )
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
use crate::{context::Context, error::RuntimeError};
|
||||
use crate::{context::Context, error::RuntimeError, Value};
|
||||
|
||||
use super::{AbstractTree, Statement, Value};
|
||||
use super::{AbstractTree, Statement};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct Block {
|
||||
statements: Vec<Statement>,
|
||||
pub struct Block<'src> {
|
||||
statements: Vec<Statement<'src>>,
|
||||
}
|
||||
|
||||
impl Block {
|
||||
pub fn new(statements: Vec<Statement>) -> Self {
|
||||
impl<'src> Block<'src> {
|
||||
pub fn new(statements: Vec<Statement<'src>>) -> Self {
|
||||
Self { statements }
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractTree for Block {
|
||||
impl<'src> AbstractTree for Block<'src> {
|
||||
fn run(self, _: &Context) -> Result<Value, RuntimeError> {
|
||||
todo!()
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
use crate::{context::Context, error::RuntimeError};
|
||||
use crate::{context::Context, error::RuntimeError, Value};
|
||||
|
||||
use super::{AbstractTree, Identifier, Logic, Value};
|
||||
use super::{AbstractTree, Identifier, Logic, ValueNode};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Expression {
|
||||
Identifier(Identifier),
|
||||
Logic(Box<Logic>),
|
||||
Value(Value),
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum Expression<'src> {
|
||||
Identifier(Identifier<'src>),
|
||||
Logic(Box<Logic<'src>>),
|
||||
Value(ValueNode<'src>),
|
||||
}
|
||||
|
||||
impl AbstractTree for Expression {
|
||||
impl<'src> AbstractTree for Expression<'src> {
|
||||
fn run(self, context: &Context) -> Result<Value, RuntimeError> {
|
||||
match self {
|
||||
Expression::Identifier(identifier) => identifier.run(context),
|
||||
Expression::Logic(logic) => logic.run(context),
|
||||
Expression::Value(value) => value.run(context),
|
||||
Expression::Value(value_node) => value_node.run(context),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,21 @@
|
||||
use crate::{context::Context, error::RuntimeError};
|
||||
use crate::{context::Context, error::RuntimeError, Value};
|
||||
|
||||
use super::{AbstractTree, Value};
|
||||
use super::AbstractTree;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct Identifier(String);
|
||||
pub struct Identifier<'src>(&'src str);
|
||||
|
||||
impl Identifier {
|
||||
pub fn new<T: ToString>(string: T) -> Identifier {
|
||||
Identifier(string.to_string())
|
||||
impl<'src> Identifier<'src> {
|
||||
pub fn new(string: &'src str) -> Self {
|
||||
Identifier(string)
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractTree for Identifier {
|
||||
fn run(self, context: &Context) -> Result<Value, RuntimeError> {
|
||||
let value = context.get(&self)?.unwrap_or_else(Value::none).clone();
|
||||
impl<'src> AbstractTree for Identifier<'src> {
|
||||
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
|
||||
todo!()
|
||||
// let value = context.get(&self)?.unwrap_or_else(Value::none).clone();
|
||||
|
||||
Ok(value)
|
||||
// Ok(value)
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
use crate::{context::Context, error::RuntimeError};
|
||||
use crate::{context::Context, error::RuntimeError, Value};
|
||||
|
||||
use super::{AbstractTree, Statement, Value};
|
||||
use super::{AbstractTree, Expression};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum Logic {
|
||||
Equal(Statement, Statement),
|
||||
NotEqual(Statement, Statement),
|
||||
Greater(Statement, Statement),
|
||||
Less(Statement, Statement),
|
||||
GreaterOrEqual(Statement, Statement),
|
||||
LessOrEqual(Statement, Statement),
|
||||
And(Statement, Statement),
|
||||
Or(Statement, Statement),
|
||||
Not(Statement),
|
||||
pub enum Logic<'src> {
|
||||
Equal(Expression<'src>, Expression<'src>),
|
||||
NotEqual(Expression<'src>, Expression<'src>),
|
||||
Greater(Expression<'src>, Expression<'src>),
|
||||
Less(Expression<'src>, Expression<'src>),
|
||||
GreaterOrEqual(Expression<'src>, Expression<'src>),
|
||||
LessOrEqual(Expression<'src>, Expression<'src>),
|
||||
And(Expression<'src>, Expression<'src>),
|
||||
Or(Expression<'src>, Expression<'src>),
|
||||
Not(Expression<'src>),
|
||||
}
|
||||
|
||||
impl AbstractTree for Logic {
|
||||
impl<'src> AbstractTree for Logic<'src> {
|
||||
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
|
||||
let boolean = match self {
|
||||
Logic::Equal(left, right) => left.run(_context)? == right.run(_context)?,
|
||||
@ -39,13 +39,15 @@ impl AbstractTree for Logic {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::abstract_tree::{Expression, ValueNode};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn equal() {
|
||||
assert!(Logic::Equal(
|
||||
Statement::Value(Value::integer(42)),
|
||||
Statement::Value(Value::integer(42)),
|
||||
Expression::Value(ValueNode::Integer(42)),
|
||||
Expression::Value(ValueNode::Integer(42)),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
|
@ -1,13 +1,13 @@
|
||||
use crate::{context::Context, error::RuntimeError};
|
||||
use crate::{context::Context, error::RuntimeError, Value};
|
||||
|
||||
use super::{AbstractTree, Block, Value};
|
||||
use super::{AbstractTree, Block};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct Loop {
|
||||
block: Block,
|
||||
pub struct Loop<'src> {
|
||||
block: Block<'src>,
|
||||
}
|
||||
|
||||
impl AbstractTree for Loop {
|
||||
impl<'src> AbstractTree for Loop<'src> {
|
||||
fn run(self, _: &Context) -> Result<Value, RuntimeError> {
|
||||
todo!()
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
pub mod assignment;
|
||||
pub mod block;
|
||||
pub mod expression;
|
||||
pub mod identifier;
|
||||
pub mod logic;
|
||||
pub mod r#loop;
|
||||
pub mod statement;
|
||||
pub mod value;
|
||||
pub mod value_node;
|
||||
|
||||
pub use self::{
|
||||
assignment::Assignment, block::Block, identifier::Identifier, logic::Logic, r#loop::Loop,
|
||||
statement::Statement, value::Value,
|
||||
assignment::Assignment, block::Block, expression::Expression, identifier::Identifier,
|
||||
logic::Logic, r#loop::Loop, statement::Statement, value_node::ValueNode,
|
||||
};
|
||||
|
||||
use crate::{context::Context, error::RuntimeError};
|
||||
use crate::{context::Context, error::RuntimeError, Value};
|
||||
|
||||
pub trait AbstractTree {
|
||||
fn run(self, context: &Context) -> Result<Value, RuntimeError>;
|
||||
|
@ -1,26 +1,22 @@
|
||||
use crate::{context::Context, error::RuntimeError};
|
||||
|
||||
use super::{AbstractTree, Assignment, Block, Identifier, Logic, Loop, Value};
|
||||
use super::{AbstractTree, Assignment, Block, Expression, Loop, Value};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum Statement {
|
||||
Assignment(Assignment),
|
||||
Block(Block),
|
||||
Identifier(Identifier),
|
||||
Loop(Loop),
|
||||
Value(Value),
|
||||
Logic(Box<Logic>),
|
||||
pub enum Statement<'src> {
|
||||
Assignment(Assignment<'src>),
|
||||
Block(Block<'src>),
|
||||
Expression(Expression<'src>),
|
||||
Loop(Loop<'src>),
|
||||
}
|
||||
|
||||
impl AbstractTree for Statement {
|
||||
impl<'src> AbstractTree for Statement<'src> {
|
||||
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
|
||||
match self {
|
||||
Statement::Assignment(assignment) => assignment.run(_context),
|
||||
Statement::Block(_) => todo!(),
|
||||
Statement::Identifier(identifier) => identifier.run(_context),
|
||||
Statement::Expression(_) => todo!(),
|
||||
Statement::Loop(_) => todo!(),
|
||||
Statement::Value(value) => value.run(_context),
|
||||
Statement::Logic(_) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
72
src/abstract_tree/value_node.rs
Normal file
72
src/abstract_tree/value_node.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use std::{cmp::Ordering, collections::BTreeMap, ops::Range};
|
||||
|
||||
use crate::{context::Context, error::RuntimeError, Value};
|
||||
|
||||
use super::{AbstractTree, Expression, Identifier};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum ValueNode<'src> {
|
||||
Boolean(bool),
|
||||
Float(f64),
|
||||
Integer(i64),
|
||||
List(Vec<Expression<'src>>),
|
||||
Map(BTreeMap<Identifier<'src>, Expression<'src>>),
|
||||
Range(Range<i64>),
|
||||
String(&'src str),
|
||||
Enum(&'src str, &'src str),
|
||||
}
|
||||
|
||||
impl<'src> Eq for ValueNode<'src> {}
|
||||
|
||||
impl<'src> PartialOrd for ValueNode<'src> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'src> Ord for ValueNode<'src> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
use ValueNode::*;
|
||||
|
||||
match (self, other) {
|
||||
(Boolean(left), Boolean(right)) => left.cmp(right),
|
||||
(Boolean(_), _) => Ordering::Greater,
|
||||
(Float(left), Float(right)) => left.total_cmp(right),
|
||||
(Float(_), _) => Ordering::Greater,
|
||||
(Integer(left), Integer(right)) => left.cmp(right),
|
||||
(Integer(_), _) => Ordering::Greater,
|
||||
(List(left), List(right)) => left.cmp(right),
|
||||
(List(_), _) => Ordering::Greater,
|
||||
(Map(left), Map(right)) => left.cmp(right),
|
||||
(Map(_), _) => Ordering::Greater,
|
||||
(Range(left), Range(right)) => {
|
||||
let start_cmp = left.start.cmp(&right.start);
|
||||
|
||||
if start_cmp.is_eq() {
|
||||
left.end.cmp(&right.end)
|
||||
} else {
|
||||
start_cmp
|
||||
}
|
||||
}
|
||||
(Range(_), _) => Ordering::Greater,
|
||||
(String(left), String(right)) => left.cmp(right),
|
||||
(String(_), _) => Ordering::Greater,
|
||||
(Enum(left_name, left_variant), Enum(right_name, right_variant)) => {
|
||||
let name_cmp = left_name.cmp(right_name);
|
||||
|
||||
if name_cmp.is_eq() {
|
||||
left_variant.cmp(right_variant)
|
||||
} else {
|
||||
name_cmp
|
||||
}
|
||||
}
|
||||
(Enum(_, _), _) => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'src> AbstractTree for ValueNode<'src> {
|
||||
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
@ -3,13 +3,10 @@ use std::{
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
abstract_tree::{Identifier, Value},
|
||||
error::RwLockPoisonError,
|
||||
};
|
||||
use crate::{error::RwLockPoisonError, Value};
|
||||
|
||||
pub struct Context {
|
||||
inner: Arc<RwLock<BTreeMap<Identifier, Value>>>,
|
||||
inner: Arc<RwLock<BTreeMap<String, Value>>>,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
@ -19,20 +16,20 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_values(values: BTreeMap<Identifier, Value>) -> Self {
|
||||
pub fn with_values(values: BTreeMap<String, Value>) -> Self {
|
||||
Self {
|
||||
inner: Arc::new(RwLock::new(values)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
|
||||
let value = self.inner.read()?.get(&identifier).cloned();
|
||||
pub fn get(&self, key: &str) -> Result<Option<Value>, RwLockPoisonError> {
|
||||
let value = self.inner.read()?.get(key).cloned();
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn set(&self, identifier: Identifier, value: Value) -> Result<(), RwLockPoisonError> {
|
||||
self.inner.write()?.insert(identifier, value);
|
||||
pub fn set(&self, key: String, value: Value) -> Result<(), RwLockPoisonError> {
|
||||
self.inner.write()?.insert(key, value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -3,11 +3,13 @@ pub mod context;
|
||||
pub mod error;
|
||||
pub mod lexer;
|
||||
pub mod parser;
|
||||
pub mod value;
|
||||
|
||||
use abstract_tree::{Statement, Value};
|
||||
use abstract_tree::Statement;
|
||||
use chumsky::{prelude::*, Parser};
|
||||
use context::Context;
|
||||
use error::Error;
|
||||
pub use value::Value;
|
||||
|
||||
pub struct Interpreter<P> {
|
||||
_parser: P,
|
||||
@ -16,7 +18,7 @@ pub struct Interpreter<P> {
|
||||
|
||||
impl<'src, P> Interpreter<P>
|
||||
where
|
||||
P: Parser<'src, &'src str, Statement, extra::Err<Rich<'src, char>>>,
|
||||
P: Parser<'src, &'src str, Statement<'src>, extra::Err<Rich<'src, char>>>,
|
||||
{
|
||||
pub fn run(&self, _source: &'src str) -> Result<Value, Error<'src>> {
|
||||
todo!();
|
||||
|
246
src/parser.rs
246
src/parser.rs
@ -8,93 +8,108 @@ type ParserInput<'tokens, 'src> =
|
||||
fn parser<'tokens, 'src: 'tokens>() -> impl Parser<
|
||||
'tokens,
|
||||
ParserInput<'tokens, 'src>,
|
||||
Vec<(Statement, SimpleSpan)>,
|
||||
Vec<(Statement<'src>, SimpleSpan)>,
|
||||
extra::Err<Rich<'tokens, Token<'src>, SimpleSpan>>,
|
||||
> {
|
||||
recursive(|statement| {
|
||||
let identifier = select! {
|
||||
Token::Identifier(text) => Identifier::new(text),
|
||||
};
|
||||
|
||||
let identifier_statement = identifier.map(|identifier| Statement::Identifier(identifier));
|
||||
|
||||
let expression = recursive(|expression| {
|
||||
let basic_value = select! {
|
||||
Token::None => Value::none(),
|
||||
Token::Boolean(boolean) => Value::boolean(boolean),
|
||||
Token::Integer(integer) => Value::integer(integer),
|
||||
Token::Float(float) => Value::float(float),
|
||||
Token::String(string) => Value::string(string.to_string()),
|
||||
Token::None => ValueNode::Enum("Option", "None"),
|
||||
Token::Boolean(boolean) => ValueNode::Boolean(boolean),
|
||||
Token::Integer(integer) => ValueNode::Integer(integer),
|
||||
Token::Float(float) => ValueNode::Float(float),
|
||||
Token::String(string) => ValueNode::String(string),
|
||||
};
|
||||
|
||||
let list = statement
|
||||
let identifier_expression = identifier
|
||||
.map(|identifier| Expression::Identifier(identifier))
|
||||
.boxed();
|
||||
|
||||
let list = expression
|
||||
.clone()
|
||||
.separated_by(just(Token::Control(',')))
|
||||
.allow_trailing()
|
||||
.collect()
|
||||
.delimited_by(just(Token::Control('[')), just(Token::Control(']')))
|
||||
.map(Value::list);
|
||||
.map(ValueNode::List);
|
||||
|
||||
let value = choice((
|
||||
basic_value.map(|value| Statement::Value(value)),
|
||||
list.map(|list| Statement::Value(list)),
|
||||
basic_value.map(|value| Expression::Value(value)),
|
||||
list.map(|list| Expression::Value(list)),
|
||||
))
|
||||
.boxed();
|
||||
|
||||
let atom = choice((
|
||||
identifier_expression.clone(),
|
||||
value.clone(),
|
||||
expression
|
||||
.clone()
|
||||
.delimited_by(just(Token::Control('(')), just(Token::Control(')'))),
|
||||
));
|
||||
|
||||
let logic = atom
|
||||
.pratt((
|
||||
prefix(2, just(Token::Operator("!")), |expression| {
|
||||
Expression::Logic(Box::new(Logic::Not(expression)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("==")), |left, right| {
|
||||
Expression::Logic(Box::new(Logic::Equal(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("!=")), |left, right| {
|
||||
Expression::Logic(Box::new(Logic::NotEqual(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator(">")), |left, right| {
|
||||
Expression::Logic(Box::new(Logic::Greater(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("<")), |left, right| {
|
||||
Expression::Logic(Box::new(Logic::Less(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator(">=")), |left, right| {
|
||||
Expression::Logic(Box::new(Logic::GreaterOrEqual(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("<=")), |left, right| {
|
||||
Expression::Logic(Box::new(Logic::LessOrEqual(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("&&")), |left, right| {
|
||||
Expression::Logic(Box::new(Logic::And(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("||")), |left, right| {
|
||||
Expression::Logic(Box::new(Logic::Or(left, right)))
|
||||
}),
|
||||
))
|
||||
.boxed();
|
||||
|
||||
choice([logic, identifier_expression, value])
|
||||
});
|
||||
|
||||
let statement = recursive(|statement| {
|
||||
let expression_statement = expression
|
||||
.map(|expression| Statement::Expression(expression))
|
||||
.boxed();
|
||||
|
||||
let assignment = identifier
|
||||
.then_ignore(just(Token::Operator("=")))
|
||||
.then(statement.clone())
|
||||
.map(|(identifier, statement)| {
|
||||
Statement::Assignment(Assignment::new(identifier, statement))
|
||||
})
|
||||
.boxed();
|
||||
|
||||
choice([assignment, expression_statement])
|
||||
});
|
||||
|
||||
let atom = choice((
|
||||
identifier_statement,
|
||||
value.clone(),
|
||||
assignment.clone(),
|
||||
statement
|
||||
.clone()
|
||||
.delimited_by(just(Token::Control('(')), just(Token::Control(')'))),
|
||||
));
|
||||
|
||||
let logic = atom.pratt((
|
||||
prefix(2, just(Token::Operator("!")), |statement| {
|
||||
Statement::Logic(Box::new(Logic::Not(statement)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("==")), |left, right| {
|
||||
Statement::Logic(Box::new(Logic::Equal(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("!=")), |left, right| {
|
||||
Statement::Logic(Box::new(Logic::NotEqual(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator(">")), |left, right| {
|
||||
Statement::Logic(Box::new(Logic::Greater(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("<")), |left, right| {
|
||||
Statement::Logic(Box::new(Logic::Less(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator(">=")), |left, right| {
|
||||
Statement::Logic(Box::new(Logic::GreaterOrEqual(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("<=")), |left, right| {
|
||||
Statement::Logic(Box::new(Logic::LessOrEqual(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("&&")), |left, right| {
|
||||
Statement::Logic(Box::new(Logic::And(left, right)))
|
||||
}),
|
||||
infix(left(1), just(Token::Operator("||")), |left, right| {
|
||||
Statement::Logic(Box::new(Logic::Or(left, right)))
|
||||
}),
|
||||
));
|
||||
|
||||
choice((assignment, logic, value, identifier_statement))
|
||||
})
|
||||
.map_with(|statement, state| (statement, state.span()))
|
||||
.map_with(|item, state| (item, state.span()))
|
||||
.repeated()
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn parse<'tokens>(
|
||||
tokens: &'tokens [(Token, SimpleSpan)],
|
||||
) -> Result<Vec<(Statement, SimpleSpan)>, Error<'tokens>> {
|
||||
pub fn parse<'tokens, 'src: 'tokens>(
|
||||
tokens: &'tokens [(Token<'src>, SimpleSpan)],
|
||||
) -> Result<Vec<(Statement<'src>, SimpleSpan)>, Error<'tokens>> {
|
||||
parser()
|
||||
.parse(tokens.spanned((0..0).into()))
|
||||
.into_result()
|
||||
@ -103,10 +118,7 @@ pub fn parse<'tokens>(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
abstract_tree::{value::ValueInner, Logic},
|
||||
lexer::lex,
|
||||
};
|
||||
use crate::{abstract_tree::Logic, lexer::lex};
|
||||
|
||||
use super::*;
|
||||
|
||||
@ -114,15 +126,15 @@ mod tests {
|
||||
fn identifier() {
|
||||
assert_eq!(
|
||||
parse(&lex("x").unwrap()).unwrap()[0].0,
|
||||
Statement::Identifier(Identifier::new("x")),
|
||||
Statement::Expression(Expression::Identifier(Identifier::new("x")))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("foobar").unwrap()).unwrap()[0].0,
|
||||
Statement::Identifier(Identifier::new("foobar")),
|
||||
Statement::Expression(Expression::Identifier(Identifier::new("foobar")))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("HELLO").unwrap()).unwrap()[0].0,
|
||||
Statement::Identifier(Identifier::new("HELLO")),
|
||||
Statement::Expression(Expression::Identifier(Identifier::new("HELLO")))
|
||||
);
|
||||
}
|
||||
|
||||
@ -132,7 +144,7 @@ mod tests {
|
||||
parse(&lex("foobar = 1").unwrap()).unwrap()[0].0,
|
||||
Statement::Assignment(Assignment::new(
|
||||
Identifier::new("foobar"),
|
||||
Statement::Value(Value::integer(1))
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(1)))
|
||||
)),
|
||||
);
|
||||
}
|
||||
@ -141,10 +153,10 @@ mod tests {
|
||||
fn logic() {
|
||||
assert_eq!(
|
||||
parse(&lex("x == 1").unwrap()).unwrap()[0].0,
|
||||
Statement::Logic(Box::new(Logic::Equal(
|
||||
Statement::Identifier(Identifier::new("x")),
|
||||
Statement::Value(Value::integer(1))
|
||||
))),
|
||||
Statement::Expression(Expression::Logic(Box::new(Logic::Equal(
|
||||
Expression::Identifier(Identifier::new("x")),
|
||||
Expression::Value(ValueNode::Integer(1))
|
||||
))))
|
||||
);
|
||||
}
|
||||
|
||||
@ -152,24 +164,26 @@ mod tests {
|
||||
fn list() {
|
||||
assert_eq!(
|
||||
parse(&lex("[]").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::list(vec![])),
|
||||
Statement::Expression(Expression::Value(ValueNode::List(Vec::with_capacity(0))))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("[42]").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::list(vec![Statement::Value(Value::integer(42))])),
|
||||
Statement::Expression(Expression::Value(ValueNode::List(vec![Expression::Value(
|
||||
ValueNode::Integer(42)
|
||||
)])))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("[42, 'foo', 'bar', [1, 2, 3,]]").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::list(vec![
|
||||
Statement::Value(Value::integer(42)),
|
||||
Statement::Value(Value::string("foo")),
|
||||
Statement::Value(Value::string("bar")),
|
||||
Statement::Value(Value::list(vec![
|
||||
Statement::Value(Value::integer(1)),
|
||||
Statement::Value(Value::integer(2)),
|
||||
Statement::Value(Value::integer(3)),
|
||||
Statement::Expression(Expression::Value(ValueNode::List(vec![
|
||||
Expression::Value(ValueNode::Integer(42)),
|
||||
Expression::Value(ValueNode::String("foo")),
|
||||
Expression::Value(ValueNode::String("bar")),
|
||||
Expression::Value(ValueNode::List(vec![
|
||||
Expression::Value(ValueNode::Integer(1)),
|
||||
Expression::Value(ValueNode::Integer(2)),
|
||||
Expression::Value(ValueNode::Integer(3)),
|
||||
]))
|
||||
])),
|
||||
])),)
|
||||
);
|
||||
}
|
||||
|
||||
@ -177,7 +191,7 @@ mod tests {
|
||||
fn r#true() {
|
||||
assert_eq!(
|
||||
parse(&lex("true").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::boolean(true))
|
||||
Statement::Expression(Expression::Value(ValueNode::Boolean(true)))
|
||||
);
|
||||
}
|
||||
|
||||
@ -185,7 +199,7 @@ mod tests {
|
||||
fn r#false() {
|
||||
assert_eq!(
|
||||
parse(&lex("false").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::boolean(false))
|
||||
Statement::Expression(Expression::Value(ValueNode::Boolean(false)))
|
||||
);
|
||||
}
|
||||
|
||||
@ -193,25 +207,25 @@ mod tests {
|
||||
fn positive_float() {
|
||||
assert_eq!(
|
||||
parse(&lex("0.0").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::float(0.0))
|
||||
Statement::Expression(Expression::Value(ValueNode::Float(0.0)))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("42.0").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::float(42.0))
|
||||
Statement::Expression(Expression::Value(ValueNode::Float(42.0)))
|
||||
);
|
||||
|
||||
let max_float = f64::MAX.to_string() + ".0";
|
||||
|
||||
assert_eq!(
|
||||
parse(&lex(&max_float).unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::float(f64::MAX))
|
||||
Statement::Expression(Expression::Value(ValueNode::Float(f64::MAX)))
|
||||
);
|
||||
|
||||
let min_positive_float = f64::MIN_POSITIVE.to_string();
|
||||
|
||||
assert_eq!(
|
||||
parse(&lex(&min_positive_float).unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::float(f64::MIN_POSITIVE))
|
||||
Statement::Expression(Expression::Value(ValueNode::Float(f64::MIN_POSITIVE)))
|
||||
);
|
||||
}
|
||||
|
||||
@ -219,25 +233,25 @@ mod tests {
|
||||
fn negative_float() {
|
||||
assert_eq!(
|
||||
parse(&lex("-0.0").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::float(-0.0))
|
||||
Statement::Expression(Expression::Value(ValueNode::Float(-0.0)))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("-42.0").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::float(-42.0))
|
||||
Statement::Expression(Expression::Value(ValueNode::Float(-42.0)))
|
||||
);
|
||||
|
||||
let min_float = f64::MIN.to_string() + ".0";
|
||||
|
||||
assert_eq!(
|
||||
parse(&lex(&min_float).unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::float(f64::MIN))
|
||||
Statement::Expression(Expression::Value(ValueNode::Float(f64::MIN)))
|
||||
);
|
||||
|
||||
let max_negative_float = format!("-{}", f64::MIN_POSITIVE);
|
||||
|
||||
assert_eq!(
|
||||
parse(&lex(&max_negative_float).unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::float(-f64::MIN_POSITIVE))
|
||||
Statement::Expression(Expression::Value(ValueNode::Float(-f64::MIN_POSITIVE)))
|
||||
);
|
||||
}
|
||||
|
||||
@ -245,41 +259,44 @@ mod tests {
|
||||
fn other_float() {
|
||||
assert_eq!(
|
||||
parse(&lex("Infinity").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::float(f64::INFINITY))
|
||||
Statement::Expression(Expression::Value(ValueNode::Float(f64::INFINITY)))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("-Infinity").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::float(f64::NEG_INFINITY))
|
||||
Statement::Expression(Expression::Value(ValueNode::Float(f64::NEG_INFINITY)))
|
||||
);
|
||||
|
||||
if let Statement::Value(value) = &parse(&lex("NaN").unwrap()).unwrap()[0].0 {
|
||||
if let ValueInner::Float(float) = value.inner().as_ref() {
|
||||
return assert!(float.is_nan());
|
||||
if let Statement::Expression(Expression::Value(ValueNode::Float(float))) =
|
||||
&parse(&lex("NaN").unwrap()).unwrap()[0].0
|
||||
{
|
||||
assert!(float.is_nan());
|
||||
} else {
|
||||
panic!("Expected a float.");
|
||||
}
|
||||
}
|
||||
|
||||
panic!("Expected a float.")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn positive_integer() {
|
||||
for i in 0..10 {
|
||||
let source = i.to_string();
|
||||
let statements = parse(&lex(&source).unwrap()).unwrap();
|
||||
|
||||
assert_eq!(statements[0].0, Statement::Value(Value::integer(i)))
|
||||
assert_eq!(
|
||||
statements[0].0,
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(i)))
|
||||
)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
parse(&lex("42").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::integer(42))
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(42)))
|
||||
);
|
||||
|
||||
let maximum_integer = i64::MAX.to_string();
|
||||
|
||||
assert_eq!(
|
||||
parse(&lex(&maximum_integer).unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::integer(i64::MAX))
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(i64::MAX)))
|
||||
);
|
||||
}
|
||||
|
||||
@ -289,19 +306,22 @@ mod tests {
|
||||
let source = i.to_string();
|
||||
let statements = parse(&lex(&source).unwrap()).unwrap();
|
||||
|
||||
assert_eq!(statements[0].0, Statement::Value(Value::integer(i)))
|
||||
assert_eq!(
|
||||
statements[0].0,
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(i)))
|
||||
)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
parse(&lex("-42").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::integer(-42))
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(-42)))
|
||||
);
|
||||
|
||||
let minimum_integer = i64::MIN.to_string();
|
||||
|
||||
assert_eq!(
|
||||
parse(&lex(&minimum_integer).unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::integer(i64::MIN))
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(i64::MIN)))
|
||||
);
|
||||
}
|
||||
|
||||
@ -309,15 +329,15 @@ mod tests {
|
||||
fn double_quoted_string() {
|
||||
assert_eq!(
|
||||
parse(&lex("\"\"").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::string("".to_string()))
|
||||
Statement::Expression(Expression::Value(ValueNode::String("")))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("\"42\"").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::string("42".to_string()))
|
||||
Statement::Expression(Expression::Value(ValueNode::String("42")))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("\"foobar\"").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::string("foobar".to_string()))
|
||||
Statement::Expression(Expression::Value(ValueNode::String("foobar")))
|
||||
);
|
||||
}
|
||||
|
||||
@ -325,15 +345,15 @@ mod tests {
|
||||
fn single_quoted_string() {
|
||||
assert_eq!(
|
||||
parse(&lex("''").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::string("".to_string()))
|
||||
Statement::Expression(Expression::Value(ValueNode::String("")))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("'42'").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::string("42".to_string()))
|
||||
Statement::Expression(Expression::Value(ValueNode::String("42")))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("'foobar'").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::string("foobar".to_string()))
|
||||
Statement::Expression(Expression::Value(ValueNode::String("foobar")))
|
||||
);
|
||||
}
|
||||
|
||||
@ -341,15 +361,15 @@ mod tests {
|
||||
fn grave_quoted_string() {
|
||||
assert_eq!(
|
||||
parse(&lex("``").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::string("".to_string()))
|
||||
Statement::Expression(Expression::Value(ValueNode::String("")))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("`42`").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::string("42".to_string()))
|
||||
Statement::Expression(Expression::Value(ValueNode::String("42")))
|
||||
);
|
||||
assert_eq!(
|
||||
parse(&lex("`foobar`").unwrap()).unwrap()[0].0,
|
||||
Statement::Value(Value::string("foobar".to_string()))
|
||||
Statement::Expression(Expression::Value(ValueNode::String("foobar")))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,10 @@
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
collections::BTreeMap,
|
||||
ops::Range,
|
||||
sync::{Arc, OnceLock},
|
||||
};
|
||||
|
||||
use crate::{context::Context, error::RuntimeError};
|
||||
|
||||
use super::{AbstractTree, Identifier, Statement};
|
||||
use crate::error::RuntimeError;
|
||||
|
||||
pub static NONE: OnceLock<Value> = OnceLock::new();
|
||||
|
||||
@ -22,8 +19,8 @@ impl Value {
|
||||
pub fn none() -> Self {
|
||||
NONE.get_or_init(|| {
|
||||
Value::r#enum(EnumInstance {
|
||||
type_name: Identifier::new("Option"),
|
||||
variant: Identifier::new("None"),
|
||||
type_name: "Option".to_string(),
|
||||
variant: "None".to_string(),
|
||||
})
|
||||
})
|
||||
.clone()
|
||||
@ -41,13 +38,13 @@ impl Value {
|
||||
Value(Arc::new(ValueInner::Integer(integer)))
|
||||
}
|
||||
|
||||
pub fn list(list: Vec<Statement>) -> Self {
|
||||
pub fn list(list: Vec<Value>) -> Self {
|
||||
Value(Arc::new(ValueInner::List(list)))
|
||||
}
|
||||
|
||||
pub fn map(map: BTreeMap<Identifier, Value>) -> Self {
|
||||
Value(Arc::new(ValueInner::Map(map)))
|
||||
}
|
||||
// pub fn map(map: BTreeMap<Identifier, Value>) -> Self {
|
||||
// Value(Arc::new(ValueInner::Map(map)))
|
||||
// }
|
||||
|
||||
pub fn range(range: Range<i64>) -> Self {
|
||||
Value(Arc::new(ValueInner::Range(range)))
|
||||
@ -89,8 +86,8 @@ pub enum ValueInner {
|
||||
Boolean(bool),
|
||||
Float(f64),
|
||||
Integer(i64),
|
||||
List(Vec<Statement>),
|
||||
Map(BTreeMap<Identifier, Value>),
|
||||
List(Vec<Value>),
|
||||
// Map(BTreeMap<Identifier, Value>),
|
||||
Range(Range<i64>),
|
||||
String(String),
|
||||
Enum(EnumInstance),
|
||||
@ -117,8 +114,8 @@ impl Ord for ValueInner {
|
||||
(Integer(_), _) => Ordering::Greater,
|
||||
(List(left), List(right)) => left.cmp(right),
|
||||
(List(_), _) => Ordering::Greater,
|
||||
(Map(left), Map(right)) => left.cmp(right),
|
||||
(Map(_), _) => Ordering::Greater,
|
||||
// (Map(left), Map(right)) => left.cmp(right),
|
||||
// (Map(_), _) => Ordering::Greater,
|
||||
(Range(left), Range(right)) => {
|
||||
let start_cmp = left.start.cmp(&right.start);
|
||||
|
||||
@ -139,12 +136,6 @@ impl Ord for ValueInner {
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct EnumInstance {
|
||||
type_name: Identifier,
|
||||
variant: Identifier,
|
||||
}
|
||||
|
||||
impl AbstractTree for Value {
|
||||
fn run(self, _: &Context) -> Result<Value, RuntimeError> {
|
||||
Ok(self)
|
||||
}
|
||||
type_name: String,
|
||||
variant: String,
|
||||
}
|
Loading…
Reference in New Issue
Block a user