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