Refine abstract tree; Improve parsing and lexing
This commit is contained in:
parent
4137a1a693
commit
65ee472a4a
@ -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),
|
||||
|
@ -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>),
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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!()
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
|
16
src/lexer.rs
16
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<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,
|
||||
|
@ -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)),
|
||||
))
|
||||
.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!(
|
||||
|
Loading…
Reference in New Issue
Block a user