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() {
let a anerit;
}

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

View File

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

View File

@@ -1,37 +1,16 @@
use std::fmt::{Debug, Write};
use super::{
token::{Keyword, Symbol, Token},
Node, Parsable, ParserErrors,
token::Symbol, MaybeResolved, Node, NodeParsable, Parsable, ParserError, ParserErrors,
Resolvable, Resolved, Statement, TokenCursor, Unresolved,
};
use crate::util::Padder;
use super::{Expr, ParserError, TokenCursor};
#[derive(Clone)]
pub struct Body {
statements: Vec<Node<Statement>>,
pub struct Body<R: MaybeResolved> {
statements: Vec<Node<Statement<R>, R>>,
}
#[derive(Clone)]
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 {
impl Parsable for Body<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> {
let mut statements = Vec::new();
let statement_end = &[Symbol::Semicolon, Symbol::CloseCurly];
@@ -57,7 +36,7 @@ impl Parsable for Body {
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;
if statement.is_err() || statement.as_ref().is_ok_and(|s| s.ended_with_error()) {
let res = cursor
@@ -69,51 +48,19 @@ impl Parsable for Body {
}
}
impl Parsable for Statement {
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<Body<Resolved>> for Body<Unresolved> {
fn resolve(self) -> Result<Body<Resolved>, ()> {
Ok(Body {
statements: self
.statements
.into_iter()
.map(|s| s.resolve())
.collect::<Result<_, _>>()?,
})
}
}
impl Debug for Statement {
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 {
impl Debug for Body<Unresolved> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.statements.first().is_some() {
f.write_str("{\n ")?;

View File

@@ -1,33 +1,23 @@
use std::fmt::{Debug, Write};
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 {
Lit(Node<Literal>),
pub enum Expr<R: MaybeResolved> {
Lit(Node<Literal, R>),
Ident(String),
BinaryOp(Operator, ExprNode, ExprNode),
Block(Node<Body>),
Call(ExprNode, Vec<Node<Expr>>),
Group(ExprNode),
BinaryOp(Operator, BoxNode<R>, BoxNode<R>),
Block(Node<Body<R>, R>),
Call(BoxNode<R>, Vec<Node<Expr<R>, R>>),
Group(BoxNode<R>),
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Operator {
Add,
Sub,
Mul,
Div,
LessThan,
GreaterThan,
Access,
Assign,
}
impl Expr {
impl Expr<Unresolved> {
pub fn ended_with_error(&self) -> bool {
match self {
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> {
let start = cursor.next_pos();
let next = cursor.expect_peek()?;
@@ -48,7 +38,7 @@ impl Parsable for Expr {
cursor.next();
if cursor.expect_peek()?.is_symbol(Symbol::CloseParen) {
cursor.next();
return Ok(Expr::Lit(Node::new(
return Ok(Expr::Lit(Node::new_unres(
Literal::Unit,
cursor.next_pos().char_span(),
)));
@@ -84,7 +74,7 @@ impl Parsable for Expr {
let inner = Node::parse(cursor, errors);
cursor.expect_sym(Symbol::CloseParen)?;
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 {
return Ok(e1);
};
@@ -93,16 +83,17 @@ impl Parsable for Expr {
let end = cursor.prev_end();
Ok(if let Some(mut op) = Operator::from_token(&next.token) {
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();
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() {
n1 = Node::new(
Box::new(Self::BinaryOp(op, n1, n21.clone())),
start.to(n21.span.end),
);
op = *op2;
n2 = n22.clone();
let Ok(box Self::BinaryOp(op2, n21, n22)) = n2.inner else {
unreachable!();
};
let end = n21.span.end;
n1 = Node::new_unres(Self::BinaryOp(op, n1, n21), start.to(end)).bx();
op = op2;
n2 = n22;
}
}
Self::BinaryOp(op, n1, n2)
@@ -112,64 +103,25 @@ impl Parsable for Expr {
}
}
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;
}
impl Resolvable<Expr<Resolved>> for Expr<Unresolved> {
fn resolve(self) -> Result<Expr<Resolved>, ()> {
Ok(match self {
Expr::Lit(l) => Expr::Lit(l.resolve()?),
Expr::Ident(n) => Expr::Ident(n),
Expr::BinaryOp(o, e1, e2) => Expr::BinaryOp(o, e1.resolve()?, e2.resolve()?),
Expr::Block(b) => Expr::Block(b.resolve()?),
Expr::Call(f, args) => Expr::Call(
f.resolve()?,
args.into_iter()
.map(|arg| arg.resolve())
.collect::<Result<_, ()>>()?,
),
Expr::Group(e) => Expr::Group(e.resolve()?),
})
}
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 {
match self {
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 module;
mod node;
mod op;
mod token;
mod val;
mod statement;
mod func;
pub use body::*;
pub use cursor::*;
@@ -15,15 +18,17 @@ pub use error::*;
pub use expr::*;
pub use module::*;
pub use node::*;
pub use val::*;
pub use op::*;
use token::*;
pub use val::*;
pub use statement::*;
pub fn parse_file(file: &str) {
let mut errors = ParserErrors::new();
let node = Node::<Module>::parse(&mut TokenCursor::from(file), &mut errors);
if let Ok(module) = node.as_ref() {
println!("{module:#?}");
};
let node = Module::parse_node(&mut TokenCursor::from(file), &mut errors);
if errors.errs.is_empty() {
let module = node.resolve().expect("what");
}
let out = &mut stdout();
for err in errors.errs {
err.write_for(out, file).unwrap();
@@ -35,7 +40,7 @@ pub fn run_stdin() {
let mut errors = ParserErrors::new();
let str = &line.expect("failed to read line");
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);
}
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 super::{token::*, Body, Node, Parsable, ParserError, ParserErrors, TokenCursor};
#[derive(Debug)]
pub struct Module {
functions: Vec<Node<Function>>,
pub struct Module<R: MaybeResolved> {
pub functions: Vec<Node<Function<R>, R>>,
}
#[derive(Clone)]
pub struct Function {
pub name: String,
pub body: Node<Body>,
}
impl Parsable for Module {
impl Parsable for Module<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> {
let mut functions = Vec::new();
loop {
@@ -23,30 +18,27 @@ impl Parsable for Module {
if next.is_keyword(Keyword::Fn) {
functions.push(Node::parse(cursor, errors));
} else {
return Err(ParserError::unexpected_token(next, "fn"));
errors.add(ParserError::unexpected_token(next, "fn"));
cursor.next();
}
}
}
}
impl Parsable for Function {
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 {
impl Debug for Module<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(())
self.functions.fmt(f)
}
}
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};
#[derive(Clone)]
pub struct Node<T> {
pub inner: Result<T, ()>,
pub trait MaybeResolved {
type Inner<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,
}
@@ -22,7 +35,7 @@ pub trait MaybeParsable: Sized {
) -> 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 {
let start = cursor.next_pos();
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> {
let start = cursor.next_pos();
let inner = match T::maybe_parse(cursor, errors) {
@@ -52,14 +65,28 @@ impl<T: MaybeParsable> Node<T> {
}
}
impl<T> Node<T> {
pub fn new(inner: T, span: FileSpan) -> Self {
pub trait NodeParsable {
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 {
inner: Ok(inner),
span,
}
}
pub fn bx(self) -> Node<Box<T>> {
pub fn bx(self) -> Node<Box<T>, Unresolved> {
Node {
inner: self.inner.map(|v| Box::new(v)),
span: self.span,
@@ -67,28 +94,20 @@ impl<T> Node<T> {
}
}
impl<T> Node<Box<T>> {
pub fn unbx(self) -> Node<T> {
Node {
inner: self.inner.map(|v| *v),
span: self.span,
}
}
}
impl<T> Deref for Node<T> {
type Target = Result<T, ()>;
impl<T, R: MaybeResolved> Deref for Node<T, R> {
type Target = <R as MaybeResolved>::Inner<T>;
fn deref(&self) -> &Self::Target {
&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 {
&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 {
match &self.inner {
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;
#[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 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {