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)]
pub struct Assignment<'src> {
identifier: Identifier<'src>,
identifier: Identifier,
statement: Box<Statement<'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 {
identifier,
statement: Box::new(statement),

View File

@ -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<Logic<'src>>),
Value(ValueNode<'src>),
}

View File

@ -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<String>);
impl<'src> Identifier<'src> {
pub fn new(string: &'src str) -> Self {
Identifier(string)
impl Identifier {
pub fn new<T: ToString>(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<Value, RuntimeError> {
todo!()
// let value = context.get(&self)?.unwrap_or_else(Value::none).clone();

View File

@ -10,10 +10,27 @@ pub enum ValueNode<'src> {
Float(f64),
Integer(i64),
List(Vec<Expression<'src>>),
Map(BTreeMap<Identifier<'src>, Expression<'src>>),
Map(BTreeMap<Identifier, Expression<'src>>),
Range(Range<i64>),
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> {}
@ -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},
};
use crate::{error::RwLockPoisonError, Value};
use crate::{abstract_tree::Identifier, error::RwLockPoisonError, Value};
pub struct Context {
inner: Arc<RwLock<BTreeMap<String, Value>>>,
inner: Arc<RwLock<BTreeMap<Identifier, Value>>>,
}
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 {
inner: Arc::new(RwLock::new(values)),
}
}
pub fn get(&self, key: &str) -> Result<Option<Value>, RwLockPoisonError> {
let value = self.inner.read()?.get(key).cloned();
pub fn get(&self, identifier: &Identifier) -> Result<Option<Value>, 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(())
}

View File

@ -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<Vec<(Token, SimpleSpan)>, 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,

View File

@ -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<Rich<'tokens, Token<'src>, SimpleSpan>>,
> {
let identifiers: RefCell<HashMap<&str, Identifier>> = 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)),
))
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!(