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)]
|
#[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),
|
||||||
|
@ -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>),
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
16
src/lexer.rs
16
src/lexer.rs
@ -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,
|
||||||
|
@ -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!(
|
||||||
|
Loading…
Reference in New Issue
Block a user