can now resolve AST nodes
This commit is contained in:
@@ -27,5 +27,5 @@ fn test() {
|
||||
}
|
||||
|
||||
fn test2() {
|
||||
|
||||
let a anerit;
|
||||
}
|
||||
|
||||
0
src/ir/mod.rs
Normal file
0
src/ir/mod.rs
Normal file
@@ -2,8 +2,10 @@
|
||||
|
||||
mod util;
|
||||
mod compiler;
|
||||
mod ir;
|
||||
mod parser;
|
||||
|
||||
fn main() {
|
||||
compiler::main();
|
||||
parser::main();
|
||||
// compiler::main();
|
||||
}
|
||||
|
||||
@@ -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 ")?;
|
||||
|
||||
@@ -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
39
src/parser/v1/func.rs
Normal 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()?
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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<_, _>>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
71
src/parser/v1/op.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
76
src/parser/v1/statement.rs
Normal file
76
src/parser/v1/statement.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user