can now resolve AST nodes

This commit is contained in:
2024-10-13 19:07:49 -04:00
parent 77735953a5
commit d67e612ff9
12 changed files with 351 additions and 214 deletions

View File

@@ -27,5 +27,5 @@ fn test() {
} }
fn test2() { fn test2() {
let a anerit;
} }

0
src/ir/mod.rs Normal file
View File

View File

@@ -2,8 +2,10 @@
mod util; mod util;
mod compiler; mod compiler;
mod ir;
mod parser; mod parser;
fn main() { fn main() {
compiler::main(); parser::main();
// compiler::main();
} }

View File

@@ -1,37 +1,16 @@
use std::fmt::{Debug, Write}; use std::fmt::{Debug, Write};
use super::{ use super::{
token::{Keyword, Symbol, Token}, token::Symbol, MaybeResolved, Node, NodeParsable, Parsable, ParserError, ParserErrors,
Node, Parsable, ParserErrors, Resolvable, Resolved, Statement, TokenCursor, Unresolved,
}; };
use crate::util::Padder; use crate::util::Padder;
use super::{Expr, ParserError, TokenCursor}; pub struct Body<R: MaybeResolved> {
statements: Vec<Node<Statement<R>, R>>,
#[derive(Clone)]
pub struct Body {
statements: Vec<Node<Statement>>,
} }
#[derive(Clone)] impl Parsable for Body<Unresolved> {
pub enum Statement {
Let(String, Node<Expr>),
Return(Node<Expr>),
Expr(Node<Expr>),
}
impl Statement {
pub fn ended_with_error(&self) -> bool {
let expr = match self {
Statement::Let(_, e) => e,
Statement::Return(e) => e,
Statement::Expr(e) => e,
};
expr.is_err() || expr.as_ref().is_ok_and(|e| e.ended_with_error())
}
}
impl Parsable for Body {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> {
let mut statements = Vec::new(); let mut statements = Vec::new();
let statement_end = &[Symbol::Semicolon, Symbol::CloseCurly]; let statement_end = &[Symbol::Semicolon, Symbol::CloseCurly];
@@ -57,7 +36,7 @@ impl Parsable for Body {
spans: vec![cursor.next_pos().char_span()], spans: vec![cursor.next_pos().char_span()],
}); });
} }
let statement: Node<Statement> = Node::parse(cursor, errors); let statement = Statement::parse_node(cursor, errors);
expect_semi = true; expect_semi = true;
if statement.is_err() || statement.as_ref().is_ok_and(|s| s.ended_with_error()) { if statement.is_err() || statement.as_ref().is_ok_and(|s| s.ended_with_error()) {
let res = cursor let res = cursor
@@ -69,51 +48,19 @@ impl Parsable for Body {
} }
} }
impl Parsable for Statement { impl Resolvable<Body<Resolved>> for Body<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> { fn resolve(self) -> Result<Body<Resolved>, ()> {
let next = cursor.expect_peek()?; Ok(Body {
Ok(match next.token { statements: self
Token::Keyword(Keyword::Let) => { .statements
cursor.next(); .into_iter()
let name = cursor.expect_ident()?; .map(|s| s.resolve())
cursor.expect_sym(Symbol::Equals)?; .collect::<Result<_, _>>()?,
let expr = Node::parse(cursor, errors);
Self::Let(name, expr)
}
Token::Keyword(Keyword::Return) => {
cursor.next();
Self::Return(Node::parse(cursor, errors))
}
_ => Self::Expr(Node::parse(cursor, errors)),
}) })
} }
} }
impl Debug for Statement { impl Debug for Body<Unresolved> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Statement::Let(n, e) => {
f.write_str("let ")?;
f.write_str(n)?;
f.write_str(" = ")?;
e.fmt(f)?;
f.write_char(';')?;
}
Statement::Return(e) => {
f.write_str("return ")?;
e.fmt(f)?;
f.write_char(';')?;
}
Statement::Expr(e) => {
e.fmt(f)?;
f.write_char(';')?;
}
}
Ok(())
}
}
impl Debug for Body {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.statements.first().is_some() { if self.statements.first().is_some() {
f.write_str("{\n ")?; f.write_str("{\n ")?;

View File

@@ -1,33 +1,23 @@
use std::fmt::{Debug, Write}; use std::fmt::{Debug, Write};
use super::token::{Symbol, Token}; use super::token::{Symbol, Token};
use super::{Body, Node, Parsable, ParserError, ParserErrors, TokenCursor, Literal}; use super::{
Body, Literal, MaybeResolved, Node, Operator, Parsable, ParserError, ParserErrors, Resolvable,
Resolved, TokenCursor, Unresolved,
};
pub type ExprNode = Node<Box<Expr>>; type BoxNode<R> = Node<Box<Expr<R>>, R>;
#[derive(Clone)] pub enum Expr<R: MaybeResolved> {
pub enum Expr { Lit(Node<Literal, R>),
Lit(Node<Literal>),
Ident(String), Ident(String),
BinaryOp(Operator, ExprNode, ExprNode), BinaryOp(Operator, BoxNode<R>, BoxNode<R>),
Block(Node<Body>), Block(Node<Body<R>, R>),
Call(ExprNode, Vec<Node<Expr>>), Call(BoxNode<R>, Vec<Node<Expr<R>, R>>),
Group(ExprNode), Group(BoxNode<R>),
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)] impl Expr<Unresolved> {
pub enum Operator {
Add,
Sub,
Mul,
Div,
LessThan,
GreaterThan,
Access,
Assign,
}
impl Expr {
pub fn ended_with_error(&self) -> bool { pub fn ended_with_error(&self) -> bool {
match self { match self {
Expr::Lit(_) => false, Expr::Lit(_) => false,
@@ -40,7 +30,7 @@ impl Expr {
} }
} }
impl Parsable for Expr { impl Parsable for Expr<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> {
let start = cursor.next_pos(); let start = cursor.next_pos();
let next = cursor.expect_peek()?; let next = cursor.expect_peek()?;
@@ -48,7 +38,7 @@ impl Parsable for Expr {
cursor.next(); cursor.next();
if cursor.expect_peek()?.is_symbol(Symbol::CloseParen) { if cursor.expect_peek()?.is_symbol(Symbol::CloseParen) {
cursor.next(); cursor.next();
return Ok(Expr::Lit(Node::new( return Ok(Expr::Lit(Node::new_unres(
Literal::Unit, Literal::Unit,
cursor.next_pos().char_span(), cursor.next_pos().char_span(),
))); )));
@@ -84,7 +74,7 @@ impl Parsable for Expr {
let inner = Node::parse(cursor, errors); let inner = Node::parse(cursor, errors);
cursor.expect_sym(Symbol::CloseParen)?; cursor.expect_sym(Symbol::CloseParen)?;
let end = cursor.prev_end(); let end = cursor.prev_end();
e1 = Self::Call(Node::new(Box::new(e1), start.to(end)), vec![inner]); e1 = Self::Call(Node::new_unres(Box::new(e1), start.to(end)), vec![inner]);
let Some(next2) = cursor.peek() else { let Some(next2) = cursor.peek() else {
return Ok(e1); return Ok(e1);
}; };
@@ -93,16 +83,17 @@ impl Parsable for Expr {
let end = cursor.prev_end(); let end = cursor.prev_end();
Ok(if let Some(mut op) = Operator::from_token(&next.token) { Ok(if let Some(mut op) = Operator::from_token(&next.token) {
cursor.next(); cursor.next();
let mut n1 = Node::new(Box::new(e1), start.to(end)); let mut n1 = Node::new_unres(e1, start.to(end)).bx();
let mut n2 = Node::parse(cursor, errors).bx(); let mut n2 = Node::parse(cursor, errors).bx();
if let Ok(box Self::BinaryOp(op2, n21, n22)) = n2.as_ref() { if let Ok(box Self::BinaryOp(op2, _, _)) = n2.as_ref() {
if op.presedence() > op2.presedence() { if op.presedence() > op2.presedence() {
n1 = Node::new( let Ok(box Self::BinaryOp(op2, n21, n22)) = n2.inner else {
Box::new(Self::BinaryOp(op, n1, n21.clone())), unreachable!();
start.to(n21.span.end), };
); let end = n21.span.end;
op = *op2; n1 = Node::new_unres(Self::BinaryOp(op, n1, n21), start.to(end)).bx();
n2 = n22.clone(); op = op2;
n2 = n22;
} }
} }
Self::BinaryOp(op, n1, n2) Self::BinaryOp(op, n1, n2)
@@ -112,64 +103,25 @@ impl Parsable for Expr {
} }
} }
impl Operator { impl Resolvable<Expr<Resolved>> for Expr<Unresolved> {
pub fn presedence(&self) -> u32 { fn resolve(self) -> Result<Expr<Resolved>, ()> {
match self { Ok(match self {
Operator::Assign => 0, Expr::Lit(l) => Expr::Lit(l.resolve()?),
Operator::LessThan => 1, Expr::Ident(n) => Expr::Ident(n),
Operator::GreaterThan => 1, Expr::BinaryOp(o, e1, e2) => Expr::BinaryOp(o, e1.resolve()?, e2.resolve()?),
Operator::Add => 2, Expr::Block(b) => Expr::Block(b.resolve()?),
Operator::Sub => 3, Expr::Call(f, args) => Expr::Call(
Operator::Mul => 4, f.resolve()?,
Operator::Div => 5, args.into_iter()
Operator::Access => 6, .map(|arg| arg.resolve())
} .collect::<Result<_, ()>>()?,
} ),
pub fn str(&self) -> &str { Expr::Group(e) => Expr::Group(e.resolve()?),
match self {
Self::Add => "+",
Self::Sub => "-",
Self::Mul => "*",
Self::Div => "/",
Self::LessThan => "<",
Self::GreaterThan => ">",
Self::Access => ".",
Self::Assign => "=",
}
}
pub fn from_token(token: &Token) -> Option<Self> {
let Token::Symbol(symbol) = token else {
return None;
};
Some(match symbol {
Symbol::OpenAngle => Operator::LessThan,
Symbol::CloseAngle => Operator::GreaterThan,
Symbol::Plus => Operator::Add,
Symbol::Minus => Operator::Sub,
Symbol::Asterisk => Operator::Mul,
Symbol::Slash => Operator::Div,
Symbol::Dot => Operator::Access,
Symbol::Equals => Operator::Assign,
_ => {
return None;
}
}) })
} }
pub fn pad(&self) -> bool {
match self {
Self::Add => true,
Self::Sub => true,
Self::Mul => true,
Self::Div => true,
Self::LessThan => true,
Self::GreaterThan => true,
Self::Access => false,
Self::Assign => true,
}
}
} }
impl Debug for Expr { impl Debug for Expr<Unresolved> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Expr::Lit(c) => c.fmt(f)?, Expr::Lit(c) => c.fmt(f)?,

39
src/parser/v1/func.rs Normal file
View File

@@ -0,0 +1,39 @@
use super::{
Body, Keyword, MaybeResolved, Node, Parsable, ParserError, ParserErrors, Resolvable, Resolved, Symbol, TokenCursor, Unresolved
};
use std::fmt::Debug;
pub struct Function<R: MaybeResolved> {
pub name: String,
pub body: Node<Body<R>, R>,
}
impl Parsable for Function<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> {
cursor.expect_kw(Keyword::Fn)?;
let name = cursor.expect_ident()?;
cursor.expect_sym(Symbol::OpenParen)?;
cursor.expect_sym(Symbol::CloseParen)?;
let body = Node::parse(cursor, errors);
Ok(Self { name, body })
}
}
impl Debug for Function<Unresolved> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("fn ")?;
f.write_str(&self.name)?;
f.write_str("() ")?;
self.body.fmt(f)?;
Ok(())
}
}
impl Resolvable<Function<Resolved>> for Function<Unresolved> {
fn resolve(self) -> Result<Function<Resolved>, ()> {
Ok(Function {
name: self.name,
body: self.body.resolve()?
})
}
}

View File

@@ -6,8 +6,11 @@ mod error;
mod expr; mod expr;
mod module; mod module;
mod node; mod node;
mod op;
mod token; mod token;
mod val; mod val;
mod statement;
mod func;
pub use body::*; pub use body::*;
pub use cursor::*; pub use cursor::*;
@@ -15,15 +18,17 @@ pub use error::*;
pub use expr::*; pub use expr::*;
pub use module::*; pub use module::*;
pub use node::*; pub use node::*;
pub use val::*; pub use op::*;
use token::*; use token::*;
pub use val::*;
pub use statement::*;
pub fn parse_file(file: &str) { pub fn parse_file(file: &str) {
let mut errors = ParserErrors::new(); let mut errors = ParserErrors::new();
let node = Node::<Module>::parse(&mut TokenCursor::from(file), &mut errors); let node = Module::parse_node(&mut TokenCursor::from(file), &mut errors);
if let Ok(module) = node.as_ref() { if errors.errs.is_empty() {
println!("{module:#?}"); let module = node.resolve().expect("what");
}; }
let out = &mut stdout(); let out = &mut stdout();
for err in errors.errs { for err in errors.errs {
err.write_for(out, file).unwrap(); err.write_for(out, file).unwrap();
@@ -35,7 +40,7 @@ pub fn run_stdin() {
let mut errors = ParserErrors::new(); let mut errors = ParserErrors::new();
let str = &line.expect("failed to read line"); let str = &line.expect("failed to read line");
let mut cursor = TokenCursor::from(&str[..]); let mut cursor = TokenCursor::from(&str[..]);
if let Ok(expr) = Node::<Statement>::parse(&mut cursor, &mut errors).as_ref() { if let Ok(expr) = Statement::parse_node(&mut cursor, &mut errors).as_ref() {
println!("{:?}", expr); println!("{:?}", expr);
} }
let out = &mut stdout(); let out = &mut stdout();

View File

@@ -1,19 +1,14 @@
use super::{
func::Function, Keyword, MaybeResolved, Node, Parsable, ParserError, ParserErrors, Resolvable,
Resolved, TokenCursor, Unresolved,
};
use std::fmt::Debug; use std::fmt::Debug;
use super::{token::*, Body, Node, Parsable, ParserError, ParserErrors, TokenCursor}; pub struct Module<R: MaybeResolved> {
pub functions: Vec<Node<Function<R>, R>>,
#[derive(Debug)]
pub struct Module {
functions: Vec<Node<Function>>,
} }
#[derive(Clone)] impl Parsable for Module<Unresolved> {
pub struct Function {
pub name: String,
pub body: Node<Body>,
}
impl Parsable for Module {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> {
let mut functions = Vec::new(); let mut functions = Vec::new();
loop { loop {
@@ -23,30 +18,27 @@ impl Parsable for Module {
if next.is_keyword(Keyword::Fn) { if next.is_keyword(Keyword::Fn) {
functions.push(Node::parse(cursor, errors)); functions.push(Node::parse(cursor, errors));
} else { } else {
return Err(ParserError::unexpected_token(next, "fn")); errors.add(ParserError::unexpected_token(next, "fn"));
cursor.next();
} }
} }
} }
} }
impl Parsable for Function { impl Debug for Module<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> {
cursor.expect_kw(Keyword::Fn)?;
let name = cursor.expect_ident()?;
cursor.expect_sym(Symbol::OpenParen)?;
cursor.expect_sym(Symbol::CloseParen)?;
let body = Node::parse(cursor, errors);
Ok(Self { name, body })
}
}
impl Debug for Function {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("fn ")?; self.functions.fmt(f)
f.write_str(&self.name)?;
f.write_str("() ")?;
self.body.fmt(f)?;
Ok(())
} }
} }
impl Resolvable<Module<Resolved>> for Module<Unresolved> {
fn resolve(self) -> Result<Module<Resolved>, ()> {
Ok(Module {
functions: self
.functions
.into_iter()
.map(|f| f.resolve())
.collect::<Result<_, _>>()?,
})
}
}

View File

@@ -5,9 +5,22 @@ use std::{
use super::{FileSpan, ParserError, ParserErrors, TokenCursor}; use super::{FileSpan, ParserError, ParserErrors, TokenCursor};
#[derive(Clone)] pub trait MaybeResolved {
pub struct Node<T> { type Inner<T>;
pub inner: Result<T, ()>, }
pub struct Resolved;
impl MaybeResolved for Resolved {
type Inner<T> = T;
}
pub struct Unresolved;
impl MaybeResolved for Unresolved {
type Inner<T> = Result<T, ()>;
}
pub struct Node<T, R: MaybeResolved> {
pub inner: <R as MaybeResolved>::Inner<T>,
pub span: FileSpan, pub span: FileSpan,
} }
@@ -22,7 +35,7 @@ pub trait MaybeParsable: Sized {
) -> Result<Option<Self>, ParserError>; ) -> Result<Option<Self>, ParserError>;
} }
impl<T: Parsable> Node<T> { impl<T: Parsable> Node<T, Unresolved> {
pub fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Self { pub fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Self {
let start = cursor.next_pos(); let start = cursor.next_pos();
let inner = T::parse(cursor, errors).map_err(|e| errors.add(e)); let inner = T::parse(cursor, errors).map_err(|e| errors.add(e));
@@ -34,7 +47,7 @@ impl<T: Parsable> Node<T> {
} }
} }
impl<T: MaybeParsable> Node<T> { impl<T: MaybeParsable> Node<T, Unresolved> {
pub fn maybe_parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Option<Self> { pub fn maybe_parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Option<Self> {
let start = cursor.next_pos(); let start = cursor.next_pos();
let inner = match T::maybe_parse(cursor, errors) { let inner = match T::maybe_parse(cursor, errors) {
@@ -52,14 +65,28 @@ impl<T: MaybeParsable> Node<T> {
} }
} }
impl<T> Node<T> { pub trait NodeParsable {
pub fn new(inner: T, span: FileSpan) -> Self { fn parse_node(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Node<Self, Unresolved>
where
Self: Sized;
}
impl<T: Parsable> NodeParsable for T {
fn parse_node(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Node<Self, Unresolved>
where
Self: Sized,
{
Node::<Self, Unresolved>::parse(cursor, errors)
}
}
impl<T> Node<T, Unresolved> {
pub fn new_unres(inner: T, span: FileSpan) -> Self {
Self { Self {
inner: Ok(inner), inner: Ok(inner),
span, span,
} }
} }
pub fn bx(self) -> Node<Box<T>> { pub fn bx(self) -> Node<Box<T>, Unresolved> {
Node { Node {
inner: self.inner.map(|v| Box::new(v)), inner: self.inner.map(|v| Box::new(v)),
span: self.span, span: self.span,
@@ -67,28 +94,20 @@ impl<T> Node<T> {
} }
} }
impl<T> Node<Box<T>> { impl<T, R: MaybeResolved> Deref for Node<T, R> {
pub fn unbx(self) -> Node<T> { type Target = <R as MaybeResolved>::Inner<T>;
Node {
inner: self.inner.map(|v| *v),
span: self.span,
}
}
}
impl<T> Deref for Node<T> {
type Target = Result<T, ()>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.inner &self.inner
} }
} }
impl<T> DerefMut for Node<T> { impl<T, R: MaybeResolved> DerefMut for Node<T, R> {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner &mut self.inner
} }
} }
impl<T: Debug> Debug for Node<T> { impl<T: Debug> Debug for Node<T, Unresolved> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.inner { match &self.inner {
Ok(v) => v.fmt(f), Ok(v) => v.fmt(f),
@@ -96,3 +115,31 @@ impl<T: Debug> Debug for Node<T> {
} }
} }
} }
impl<T: Debug> Debug for Node<T, Resolved> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.inner.fmt(f)
}
}
pub trait Resolvable<Res> {
fn resolve(self) -> Result<Res, ()>;
}
impl<T: Resolvable<Res>, Res> Resolvable<Node<Res, Resolved>> for Node<T, Unresolved> {
fn resolve(self) -> Result<Node<Res, Resolved>, ()> {
if let Ok(inner) = self.inner {
return Ok(Node {
inner: inner.resolve()?,
span: self.span,
});
}
Err(())
}
}
impl<T: Resolvable<Res>, Res> Resolvable<Box<Res>> for Box<T> {
fn resolve(self) -> Result<Box<Res>, ()> {
Ok(Box::new((*self).resolve()?))
}
}

71
src/parser/v1/op.rs Normal file
View File

@@ -0,0 +1,71 @@
use super::{Symbol, Token};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Operator {
Add,
Sub,
Mul,
Div,
LessThan,
GreaterThan,
Access,
Assign,
}
impl Operator {
pub fn presedence(&self) -> u32 {
match self {
Operator::Assign => 0,
Operator::LessThan => 1,
Operator::GreaterThan => 1,
Operator::Add => 2,
Operator::Sub => 3,
Operator::Mul => 4,
Operator::Div => 5,
Operator::Access => 6,
}
}
pub fn str(&self) -> &str {
match self {
Self::Add => "+",
Self::Sub => "-",
Self::Mul => "*",
Self::Div => "/",
Self::LessThan => "<",
Self::GreaterThan => ">",
Self::Access => ".",
Self::Assign => "=",
}
}
pub fn from_token(token: &Token) -> Option<Self> {
let Token::Symbol(symbol) = token else {
return None;
};
Some(match symbol {
Symbol::OpenAngle => Operator::LessThan,
Symbol::CloseAngle => Operator::GreaterThan,
Symbol::Plus => Operator::Add,
Symbol::Minus => Operator::Sub,
Symbol::Asterisk => Operator::Mul,
Symbol::Slash => Operator::Div,
Symbol::Dot => Operator::Access,
Symbol::Equals => Operator::Assign,
_ => {
return None;
}
})
}
pub fn pad(&self) -> bool {
match self {
Self::Add => true,
Self::Sub => true,
Self::Mul => true,
Self::Div => true,
Self::LessThan => true,
Self::GreaterThan => true,
Self::Access => false,
Self::Assign => true,
}
}
}

View File

@@ -0,0 +1,76 @@
use std::fmt::{Debug, Write};
use super::{
Expr, Keyword, MaybeResolved, Node, Parsable, ParserError, ParserErrors, Resolvable, Resolved,
Symbol, Token, TokenCursor, Unresolved,
};
pub enum Statement<R: MaybeResolved> {
Let(String, Node<Expr<R>, R>),
Return(Node<Expr<R>, R>),
Expr(Node<Expr<R>, R>),
}
impl Statement<Unresolved> {
pub fn ended_with_error(&self) -> bool {
let expr = match self {
Statement::Let(_, e) => e,
Statement::Return(e) => e,
Statement::Expr(e) => e,
};
expr.is_err() || expr.as_ref().is_ok_and(|e| e.ended_with_error())
}
}
impl Parsable for Statement<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> {
let next = cursor.expect_peek()?;
Ok(match next.token {
Token::Keyword(Keyword::Let) => {
cursor.next();
let name = cursor.expect_ident()?;
cursor.expect_sym(Symbol::Equals)?;
let expr = Node::parse(cursor, errors);
Self::Let(name, expr)
}
Token::Keyword(Keyword::Return) => {
cursor.next();
Self::Return(Node::parse(cursor, errors))
}
_ => Self::Expr(Node::parse(cursor, errors)),
})
}
}
impl Resolvable<Statement<Resolved>> for Statement<Unresolved> {
fn resolve(self) -> Result<Statement<Resolved>, ()> {
Ok(match self {
Self::Let(i, e) => Statement::Let(i, e.resolve()?),
Self::Return(e) => Statement::Return(e.resolve()?),
Self::Expr(e) => Statement::Expr(e.resolve()?),
})
}
}
impl Debug for Statement<Unresolved> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Statement::Let(n, e) => {
f.write_str("let ")?;
f.write_str(n)?;
f.write_str(" = ")?;
e.fmt(f)?;
f.write_char(';')?;
}
Statement::Return(e) => {
f.write_str("return ")?;
e.fmt(f)?;
f.write_char(';')?;
}
Statement::Expr(e) => {
e.fmt(f)?;
f.write_char(';')?;
}
}
Ok(())
}
}

View File

@@ -1,4 +1,4 @@
use super::{CharCursor, MaybeParsable, ParserError, ParserErrors, Symbol, Token, TokenCursor}; use super::{CharCursor, MaybeParsable, ParserError, ParserErrors, Resolvable, Symbol, Token, TokenCursor};
use std::fmt::Debug; use std::fmt::Debug;
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
@@ -85,6 +85,12 @@ pub fn string_from(cursor: &mut CharCursor) -> Result<String, ParserError> {
} }
} }
impl Resolvable<Literal> for Literal {
fn resolve(self) -> Result<Literal, ()> {
Ok(self)
}
}
impl Debug for Literal { impl Debug for Literal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {