1
0

Refine abstract tree; Improve parsing and lexing

This commit is contained in:
Jeff 2024-02-28 17:49:46 -05:00
parent 4137a1a693
commit 65ee472a4a
7 changed files with 96 additions and 40 deletions

View File

@ -4,12 +4,12 @@ use super::{AbstractTree, Identifier, Statement};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Assignment<'src> { pub struct Assignment<'src> {
identifier: Identifier<'src>, identifier: Identifier,
statement: Box<Statement<'src>>, statement: Box<Statement<'src>>,
} }
impl<'src> Assignment<'src> { impl<'src> Assignment<'src> {
pub fn new(identifier: Identifier<'src>, statement: Statement<'src>) -> Self { pub fn new(identifier: Identifier, statement: Statement<'src>) -> Self {
Self { Self {
identifier, identifier,
statement: Box::new(statement), statement: Box::new(statement),

View File

@ -4,7 +4,7 @@ use super::{AbstractTree, Identifier, Logic, ValueNode};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Expression<'src> { pub enum Expression<'src> {
Identifier(Identifier<'src>), Identifier(Identifier),
Logic(Box<Logic<'src>>), Logic(Box<Logic<'src>>),
Value(ValueNode<'src>), Value(ValueNode<'src>),
} }

View File

@ -1,17 +1,19 @@
use std::sync::Arc;
use crate::{context::Context, error::RuntimeError, Value}; use crate::{context::Context, error::RuntimeError, Value};
use super::AbstractTree; use super::AbstractTree;
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Identifier<'src>(&'src str); pub struct Identifier(Arc<String>);
impl<'src> Identifier<'src> { impl Identifier {
pub fn new(string: &'src str) -> Self { pub fn new<T: ToString>(string: T) -> Self {
Identifier(string) Identifier(Arc::new(string.to_string()))
} }
} }
impl<'src> AbstractTree for Identifier<'src> { impl AbstractTree for Identifier {
fn run(self, _context: &Context) -> Result<Value, RuntimeError> { fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
todo!() todo!()
// let value = context.get(&self)?.unwrap_or_else(Value::none).clone(); // let value = context.get(&self)?.unwrap_or_else(Value::none).clone();

View File

@ -10,10 +10,27 @@ pub enum ValueNode<'src> {
Float(f64), Float(f64),
Integer(i64), Integer(i64),
List(Vec<Expression<'src>>), List(Vec<Expression<'src>>),
Map(BTreeMap<Identifier<'src>, Expression<'src>>), Map(BTreeMap<Identifier, Expression<'src>>),
Range(Range<i64>), Range(Range<i64>),
String(&'src str), String(&'src str),
Enum(&'src str, &'src str), Enum(Identifier, Identifier),
}
impl<'src> AbstractTree for ValueNode<'src> {
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
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> {} 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<Value, RuntimeError> {
todo!()
}
}

View File

@ -3,10 +3,10 @@ use std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
use crate::{error::RwLockPoisonError, Value}; use crate::{abstract_tree::Identifier, error::RwLockPoisonError, Value};
pub struct Context { pub struct Context {
inner: Arc<RwLock<BTreeMap<String, Value>>>, inner: Arc<RwLock<BTreeMap<Identifier, Value>>>,
} }
impl Context { impl Context {
@ -16,20 +16,20 @@ impl Context {
} }
} }
pub fn with_values(values: BTreeMap<String, Value>) -> Self { pub fn with_values(values: BTreeMap<Identifier, Value>) -> Self {
Self { Self {
inner: Arc::new(RwLock::new(values)), inner: Arc::new(RwLock::new(values)),
} }
} }
pub fn get(&self, key: &str) -> Result<Option<Value>, RwLockPoisonError> { pub fn get(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
let value = self.inner.read()?.get(key).cloned(); let value = self.inner.read()?.get(identifier).cloned();
Ok(value) Ok(value)
} }
pub fn set(&self, key: String, value: Value) -> Result<(), RwLockPoisonError> { pub fn set(&self, identifier: Identifier, value: Value) -> Result<(), RwLockPoisonError> {
self.inner.write()?.insert(key, value); self.inner.write()?.insert(identifier, value);
Ok(()) Ok(())
} }

View File

@ -4,14 +4,13 @@ use crate::error::Error;
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum Token<'src> { pub enum Token<'src> {
None,
Boolean(bool), Boolean(bool),
Integer(i64), Integer(i64),
Float(f64), Float(f64),
String(&'src str), String(&'src str),
Identifier(&'src str), Identifier(&'src str),
Operator(&'src str), Operator(&'src str),
Control(char), Control(&'src str),
} }
pub fn lex<'src>(source: &'src str) -> Result<Vec<(Token, SimpleSpan)>, Error<'src>> { pub fn lex<'src>(source: &'src str) -> Result<Vec<(Token, SimpleSpan)>, Error<'src>> {
@ -84,7 +83,18 @@ pub fn lexer<'src>() -> impl Parser<
)) ))
.map(Token::Operator); .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(( choice((
boolean, float, integer, string, identifier, operator, control, boolean, float, integer, string, identifier, operator, control,

View File

@ -1,3 +1,5 @@
use std::{cell::RefCell, collections::HashMap};
use chumsky::{input::SpannedInput, pratt::*, prelude::*}; use chumsky::{input::SpannedInput, pratt::*, prelude::*};
use crate::{abstract_tree::*, error::Error, lexer::Token}; use crate::{abstract_tree::*, error::Error, lexer::Token};
@ -11,43 +13,63 @@ fn parser<'tokens, 'src: 'tokens>() -> impl Parser<
Vec<(Statement<'src>, SimpleSpan)>, Vec<(Statement<'src>, SimpleSpan)>,
extra::Err<Rich<'tokens, Token<'src>, SimpleSpan>>, extra::Err<Rich<'tokens, Token<'src>, SimpleSpan>>,
> { > {
let identifiers: RefCell<HashMap<&str, Identifier>> = RefCell::new(HashMap::new());
let identifier = select! { 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 expression = recursive(|expression| {
let basic_value = select! { let basic_value = select! {
Token::None => ValueNode::Enum("Option", "None"),
Token::Boolean(boolean) => ValueNode::Boolean(boolean), Token::Boolean(boolean) => ValueNode::Boolean(boolean),
Token::Integer(integer) => ValueNode::Integer(integer), Token::Integer(integer) => ValueNode::Integer(integer),
Token::Float(float) => ValueNode::Float(float), Token::Float(float) => ValueNode::Float(float),
Token::String(string) => ValueNode::String(string), Token::String(string) => ValueNode::String(string),
}; }
.map(|value| Expression::Value(value))
.boxed();
let identifier_expression = identifier let identifier_expression = identifier
.clone()
.map(|identifier| Expression::Identifier(identifier)) .map(|identifier| Expression::Identifier(identifier))
.boxed(); .boxed();
let list = expression 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(ValueNode::List); .map(|list| Expression::Value(ValueNode::List(list)))
.boxed();
let value = choice(( let r#enum = identifier
basic_value.map(|value| Expression::Value(value)), .clone()
list.map(|list| Expression::Value(list)), .then_ignore(just(Token::Control("::")))
)) .then(identifier.clone())
.boxed(); .map(|(name, variant)| Expression::Value(ValueNode::Enum(name, variant)))
.boxed();
let atom = choice(( let atom = choice((
identifier_expression.clone(), identifier_expression.clone(),
value.clone(), basic_value.clone(),
list.clone(),
r#enum.clone(),
expression expression
.clone() .clone()
.delimited_by(just(Token::Control('(')), just(Token::Control(')'))), .delimited_by(just(Token::Control("(")), just(Token::Control(")"))),
)); ));
let logic = atom let logic = atom
@ -82,7 +104,7 @@ fn parser<'tokens, 'src: 'tokens>() -> impl Parser<
)) ))
.boxed(); .boxed();
choice([logic, identifier_expression, value]) choice([r#enum, logic, identifier_expression, list, basic_value])
}); });
let statement = recursive(|statement| { 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] #[test]
fn list() { fn list() {
assert_eq!( assert_eq!(