diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index c4fcdf4..71f3720 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -4,12 +4,12 @@ use super::{AbstractTree, Identifier, Statement}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Assignment<'src> { - identifier: Identifier<'src>, + identifier: Identifier, statement: Box>, } impl<'src> Assignment<'src> { - pub fn new(identifier: Identifier<'src>, statement: Statement<'src>) -> Self { + pub fn new(identifier: Identifier, statement: Statement<'src>) -> Self { Self { identifier, statement: Box::new(statement), diff --git a/src/abstract_tree/expression.rs b/src/abstract_tree/expression.rs index d19e81a..01adb2a 100644 --- a/src/abstract_tree/expression.rs +++ b/src/abstract_tree/expression.rs @@ -4,7 +4,7 @@ use super::{AbstractTree, Identifier, Logic, ValueNode}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Expression<'src> { - Identifier(Identifier<'src>), + Identifier(Identifier), Logic(Box>), Value(ValueNode<'src>), } diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index 3f545c7..2bdaf32 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -1,17 +1,19 @@ +use std::sync::Arc; + use crate::{context::Context, error::RuntimeError, Value}; use super::AbstractTree; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct Identifier<'src>(&'src str); +pub struct Identifier(Arc); -impl<'src> Identifier<'src> { - pub fn new(string: &'src str) -> Self { - Identifier(string) +impl Identifier { + pub fn new(string: T) -> Self { + Identifier(Arc::new(string.to_string())) } } -impl<'src> AbstractTree for Identifier<'src> { +impl AbstractTree for Identifier { fn run(self, _context: &Context) -> Result { todo!() // let value = context.get(&self)?.unwrap_or_else(Value::none).clone(); diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index 898663c..030f96f 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -10,10 +10,27 @@ pub enum ValueNode<'src> { Float(f64), Integer(i64), List(Vec>), - Map(BTreeMap, Expression<'src>>), + Map(BTreeMap>), Range(Range), String(&'src str), - Enum(&'src str, &'src str), + Enum(Identifier, Identifier), +} + +impl<'src> AbstractTree for ValueNode<'src> { + fn run(self, _context: &Context) -> Result { + let value = match self { + ValueNode::Boolean(boolean) => Value::boolean(boolean), + ValueNode::Float(float) => todo!(), + ValueNode::Integer(integer) => todo!(), + ValueNode::List(expression_list) => todo!(), + ValueNode::Map(property_list) => todo!(), + ValueNode::Range(range) => todo!(), + ValueNode::String(string) => todo!(), + ValueNode::Enum(name, variant) => todo!(), + }; + + Ok(value) + } } impl<'src> Eq for ValueNode<'src> {} @@ -64,9 +81,3 @@ impl<'src> Ord for ValueNode<'src> { } } } - -impl<'src> AbstractTree for ValueNode<'src> { - fn run(self, _context: &Context) -> Result { - todo!() - } -} diff --git a/src/context.rs b/src/context.rs index 9859894..d3f7349 100644 --- a/src/context.rs +++ b/src/context.rs @@ -3,10 +3,10 @@ use std::{ sync::{Arc, RwLock}, }; -use crate::{error::RwLockPoisonError, Value}; +use crate::{abstract_tree::Identifier, error::RwLockPoisonError, Value}; pub struct Context { - inner: Arc>>, + inner: Arc>>, } impl Context { @@ -16,20 +16,20 @@ impl Context { } } - pub fn with_values(values: BTreeMap) -> Self { + pub fn with_values(values: BTreeMap) -> Self { Self { inner: Arc::new(RwLock::new(values)), } } - pub fn get(&self, key: &str) -> Result, RwLockPoisonError> { - let value = self.inner.read()?.get(key).cloned(); + pub fn get(&self, identifier: &Identifier) -> Result, RwLockPoisonError> { + let value = self.inner.read()?.get(identifier).cloned(); Ok(value) } - pub fn set(&self, key: String, value: Value) -> Result<(), RwLockPoisonError> { - self.inner.write()?.insert(key, value); + pub fn set(&self, identifier: Identifier, value: Value) -> Result<(), RwLockPoisonError> { + self.inner.write()?.insert(identifier, value); Ok(()) } diff --git a/src/lexer.rs b/src/lexer.rs index fc1814c..361fd16 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -4,14 +4,13 @@ use crate::error::Error; #[derive(Clone, Debug, PartialEq)] pub enum Token<'src> { - None, Boolean(bool), Integer(i64), Float(f64), String(&'src str), Identifier(&'src str), Operator(&'src str), - Control(char), + Control(&'src str), } pub fn lex<'src>(source: &'src str) -> Result, Error<'src>> { @@ -84,7 +83,18 @@ pub fn lexer<'src>() -> impl Parser< )) .map(Token::Operator); - let control = one_of("[](){},;'").map(Token::Control); + let control = choice(( + just("[").padded(), + just("]").padded(), + just("(").padded(), + just(")").padded(), + just("{").padded(), + just("}").padded(), + just(",").padded(), + just(";").padded(), + just("::").padded(), + )) + .map(Token::Control); choice(( boolean, float, integer, string, identifier, operator, control, diff --git a/src/parser.rs b/src/parser.rs index 57db169..4101d4f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,3 +1,5 @@ +use std::{cell::RefCell, collections::HashMap}; + use chumsky::{input::SpannedInput, pratt::*, prelude::*}; use crate::{abstract_tree::*, error::Error, lexer::Token}; @@ -11,43 +13,63 @@ fn parser<'tokens, 'src: 'tokens>() -> impl Parser< Vec<(Statement<'src>, SimpleSpan)>, extra::Err, SimpleSpan>>, > { + let identifiers: RefCell> = RefCell::new(HashMap::new()); + let identifier = select! { - Token::Identifier(text) => Identifier::new(text), + Token::Identifier(text) => { + let mut identifiers = identifiers.borrow_mut(); + + if let Some(identifier) = identifiers.get(&text) { + identifier.clone() + } else { + let new = Identifier::new(text); + + identifiers.insert(text, new.clone()); + + new + } + } }; let expression = recursive(|expression| { let basic_value = select! { - 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), - }; + } + .map(|value| Expression::Value(value)) + .boxed(); let identifier_expression = identifier + .clone() .map(|identifier| Expression::Identifier(identifier)) .boxed(); let list = expression .clone() - .separated_by(just(Token::Control(','))) + .separated_by(just(Token::Control(","))) .allow_trailing() .collect() - .delimited_by(just(Token::Control('[')), just(Token::Control(']'))) - .map(ValueNode::List); + .delimited_by(just(Token::Control("[")), just(Token::Control("]"))) + .map(|list| Expression::Value(ValueNode::List(list))) + .boxed(); - let value = choice(( - basic_value.map(|value| Expression::Value(value)), - list.map(|list| Expression::Value(list)), - )) - .boxed(); + let r#enum = identifier + .clone() + .then_ignore(just(Token::Control("::"))) + .then(identifier.clone()) + .map(|(name, variant)| Expression::Value(ValueNode::Enum(name, variant))) + .boxed(); let atom = choice(( identifier_expression.clone(), - value.clone(), + basic_value.clone(), + list.clone(), + r#enum.clone(), expression .clone() - .delimited_by(just(Token::Control('(')), just(Token::Control(')'))), + .delimited_by(just(Token::Control("(")), just(Token::Control(")"))), )); let logic = atom @@ -82,7 +104,7 @@ fn parser<'tokens, 'src: 'tokens>() -> impl Parser< )) .boxed(); - choice([logic, identifier_expression, value]) + choice([r#enum, logic, identifier_expression, list, basic_value]) }); let statement = recursive(|statement| { @@ -191,6 +213,17 @@ mod tests { ); } + #[test] + fn r#enum() { + assert_eq!( + parse(&lex("Option::None").unwrap()).unwrap()[0].0, + Statement::Expression(Expression::Value(ValueNode::Enum( + Identifier::new("Option"), + Identifier::new("None") + ))) + ); + } + #[test] fn list() { assert_eq!(