added unary ops and control flow for parser

This commit is contained in:
2024-10-14 00:54:27 -04:00
parent d67e612ff9
commit e33420e91f
19 changed files with 433 additions and 237 deletions

View File

@@ -29,3 +29,6 @@ fn test() {
fn test2() { fn test2() {
let a anerit; let a anerit;
} }
fn test3() {
let x = 3

View File

@@ -1,4 +1,4 @@
fn main() { fn main() {
let x = 3; let x = &"Hello World!";
print(x); print(x);
} }

View File

@@ -0,0 +1,2 @@
pub enum IRInstruction {
}

View File

@@ -1,4 +1,5 @@
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(try_trait_v2)]
mod util; mod util;
mod compiler; mod compiler;

View File

@@ -1,33 +1,25 @@
use std::io::{stdout, BufRead, BufReader}; use std::io::{stdout, BufRead, BufReader};
mod body;
mod cursor; mod cursor;
mod error; mod error;
mod expr;
mod module;
mod node; mod node;
mod op; mod nodes;
mod parse;
mod token; mod token;
mod val;
mod statement;
mod func;
pub use body::*;
pub use cursor::*; pub use cursor::*;
pub use error::*; pub use error::*;
pub use expr::*;
pub use module::*;
pub use node::*; pub use node::*;
pub use op::*; pub use nodes::*;
pub use parse::*;
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 = Module::parse_node(&mut TokenCursor::from(file), &mut errors); let res = Module::parse_node(&mut TokenCursor::from(file), &mut errors);
println!("{:?}", res.node);
if errors.errs.is_empty() { if errors.errs.is_empty() {
let module = node.resolve().expect("what"); let module = res.node.resolve().expect("what");
} }
let out = &mut stdout(); let out = &mut stdout();
for err in errors.errs { for err in errors.errs {
@@ -40,8 +32,12 @@ 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) = Statement::parse_node(&mut cursor, &mut errors).as_ref() { if let Ok(expr) = Statement::parse_node(&mut cursor, &mut errors).node.as_ref() {
println!("{:?}", expr); if cursor.next().is_none() {
println!("{:?}", expr);
} else {
println!("uhhhh ehehe");
}
} }
let out = &mut stdout(); let out = &mut stdout();
for err in errors.errs { for err in errors.errs {

View File

@@ -3,7 +3,7 @@ use std::{
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
}; };
use super::{FileSpan, ParserError, ParserErrors, TokenCursor}; use super::FileSpan;
pub trait MaybeResolved { pub trait MaybeResolved {
type Inner<T>; type Inner<T>;
@@ -24,63 +24,8 @@ pub struct Node<T, R: MaybeResolved> {
pub span: FileSpan, pub span: FileSpan,
} }
pub trait Parsable: Sized {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError>;
}
pub trait MaybeParsable: Sized {
fn maybe_parse(
cursor: &mut TokenCursor,
errors: &mut ParserErrors,
) -> Result<Option<Self>, ParserError>;
}
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));
let end = cursor.prev_end();
Self {
inner,
span: start.to(end),
}
}
}
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) {
Ok(v) => Ok(v?),
Err(e) => {
errors.add(e);
Err(())
}
};
let end = cursor.prev_end();
Some(Self {
inner,
span: start.to(end),
})
}
}
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> { impl<T> Node<T, Unresolved> {
pub fn new_unres(inner: T, span: FileSpan) -> Self { pub fn new(inner: T, span: FileSpan) -> Self {
Self { Self {
inner: Ok(inner), inner: Ok(inner),
span, span,

View File

@@ -1,8 +1,8 @@
use std::fmt::{Debug, Write}; use std::fmt::{Debug, Write};
use super::{ use super::{
token::Symbol, MaybeResolved, Node, NodeParsable, Parsable, ParserError, ParserErrors, token::Symbol, MaybeResolved, Node, NodeParsable, Parsable, ParseResult, ParserError,
Resolvable, Resolved, Statement, TokenCursor, Unresolved, ParserErrors, Resolvable, Resolved, Statement, TokenCursor, Unresolved,
}; };
use crate::util::Padder; use crate::util::Padder;
@@ -11,20 +11,25 @@ pub struct Body<R: MaybeResolved> {
} }
impl Parsable for Body<Unresolved> { impl Parsable for Body<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
let mut statements = Vec::new(); let mut statements = Vec::new();
let statement_end = &[Symbol::Semicolon, Symbol::CloseCurly]; let statement_end = &[Symbol::Semicolon, Symbol::CloseCurly];
cursor.expect_sym(Symbol::OpenCurly)?; cursor.expect_sym(Symbol::OpenCurly)?;
if cursor.expect_peek()?.is_symbol(Symbol::CloseCurly) { if cursor.expect_peek()?.is_symbol(Symbol::CloseCurly) {
cursor.next(); cursor.next();
return Ok(Self { statements }); return ParseResult::Ok(Self { statements });
} }
let mut expect_semi = false; let mut expect_semi = false;
let mut recover = false;
loop { loop {
let next = cursor.expect_peek()?; let Some(next) = cursor.peek() else {
recover = true;
errors.add(ParserError::unexpected_end());
break;
};
if next.is_symbol(Symbol::CloseCurly) { if next.is_symbol(Symbol::CloseCurly) {
cursor.next(); cursor.next();
return Ok(Self { statements }); break;
} }
if next.is_symbol(Symbol::Semicolon) { if next.is_symbol(Symbol::Semicolon) {
cursor.next(); cursor.next();
@@ -36,15 +41,19 @@ impl Parsable for Body<Unresolved> {
spans: vec![cursor.next_pos().char_span()], spans: vec![cursor.next_pos().char_span()],
}); });
} }
let statement = Statement::parse_node(cursor, errors); let res = Statement::parse_node(cursor, errors);
statements.push(res.node);
expect_semi = true; expect_semi = true;
if statement.is_err() || statement.as_ref().is_ok_and(|s| s.ended_with_error()) { if res.recover
let res = cursor && cursor
.seek(|t| t.is_symbol_and(|s| statement_end.contains(&s))) .seek(|t| t.is_symbol_and(|s| statement_end.contains(&s)))
.ok_or(ParserError::unexpected_end())?; .is_none()
{
recover = true;
break;
} }
statements.push(statement);
} }
ParseResult::from_recover(Self { statements }, recover)
} }
} }

View File

@@ -2,8 +2,8 @@ use std::fmt::{Debug, Write};
use super::token::{Symbol, Token}; use super::token::{Symbol, Token};
use super::{ use super::{
Body, Literal, MaybeResolved, Node, Operator, Parsable, ParserError, ParserErrors, Resolvable, BinaryOperator, Body, Literal, MaybeResolved, Node, NodeParsable, Parsable, ParseResult,
Resolved, TokenCursor, Unresolved, ParserError, ParserErrors, Resolvable, Resolved, TokenCursor, UnaryOperator, Unresolved,
}; };
type BoxNode<R> = Node<Box<Expr<R>>, R>; type BoxNode<R> = Node<Box<Expr<R>>, R>;
@@ -11,46 +11,45 @@ type BoxNode<R> = Node<Box<Expr<R>>, R>;
pub enum Expr<R: MaybeResolved> { pub enum Expr<R: MaybeResolved> {
Lit(Node<Literal, R>), Lit(Node<Literal, R>),
Ident(String), Ident(String),
BinaryOp(Operator, BoxNode<R>, BoxNode<R>), BinaryOp(BinaryOperator, BoxNode<R>, BoxNode<R>),
UnaryOp(UnaryOperator, BoxNode<R>),
Block(Node<Body<R>, R>), Block(Node<Body<R>, R>),
Call(BoxNode<R>, Vec<Node<Expr<R>, R>>), Call(BoxNode<R>, Vec<Node<Expr<R>, R>>),
Group(BoxNode<R>), Group(BoxNode<R>),
} }
impl Expr<Unresolved> {
pub fn ended_with_error(&self) -> bool {
match self {
Expr::Lit(_) => false,
Expr::Ident(_) => false,
Expr::BinaryOp(_, _, e) => e.is_err() || e.as_ref().is_ok_and(|e| e.ended_with_error()),
Expr::Block(b) => b.is_err(),
Expr::Call(_, _) => false,
Expr::Group(_) => false,
}
}
}
impl Parsable for Expr<Unresolved> { impl Parsable for Expr<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
let start = cursor.next_pos(); let start = cursor.next_pos();
let next = cursor.expect_peek()?; let next = cursor.expect_peek()?;
let mut e1 = if next.is_symbol(Symbol::OpenParen) { let mut e1 = if next.is_symbol(Symbol::OpenParen) {
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_unres( return ParseResult::Ok(Expr::Lit(Node::new(
Literal::Unit, Literal::Unit,
cursor.next_pos().char_span(), cursor.next_pos().char_span(),
))); )));
} }
let expr = Node::parse(cursor, errors).bx(); let res = Node::parse(cursor, errors);
if expr.is_err() { if res.recover {
cursor.seek_sym(Symbol::CloseParen); cursor.seek_sym(Symbol::CloseParen);
} }
cursor.expect_sym(Symbol::CloseParen)?; cursor.expect_sym(Symbol::CloseParen)?;
Self::Group(expr) Self::Group(res.node.bx())
} else if next.is_symbol(Symbol::OpenCurly) { } else if next.is_symbol(Symbol::OpenCurly) {
Self::Block(Node::parse(cursor, errors)) Self::Block(Body::parse_node(cursor, errors)?)
} else if let Some(op) = UnaryOperator::from_token(next) {
cursor.next();
return Node::parse(cursor, errors).map(|n| {
let n = n.bx();
if let Ok(box Self::BinaryOp(op2, n1, n2)) = n.inner {
let span = start.to(n1.span.end);
Self::BinaryOp(op2, Node::new(Self::UnaryOp(op, n1), span).bx(), n2)
} else {
Self::UnaryOp(op, n)
}
});
} else if let Some(val) = Node::maybe_parse(cursor, errors) { } else if let Some(val) = Node::maybe_parse(cursor, errors) {
Self::Lit(val) Self::Lit(val)
} else { } else {
@@ -62,36 +61,47 @@ impl Parsable for Expr<Unresolved> {
Self::Ident(name) Self::Ident(name)
} }
_ => { _ => {
return Err(ParserError::unexpected_token(next, "an expression")); return ParseResult::Err(ParserError::unexpected_token(next, "an expression"));
} }
} }
}; };
let Some(mut next) = cursor.peek() else { let Some(mut next) = cursor.peek() else {
return Ok(e1); return ParseResult::Ok(e1);
}; };
while next.is_symbol(Symbol::OpenParen) { while next.is_symbol(Symbol::OpenParen) {
cursor.next(); cursor.next();
let inner = Node::parse(cursor, errors); let mut args = Vec::new();
while !cursor.expect_peek()?.is_symbol(Symbol::CloseParen) {
let res = Node::<Expr<Unresolved>, Unresolved>::parse(cursor, errors);
args.push(res.node);
if res.recover {
cursor.seek_sym(Symbol::CloseParen);
break;
}
}
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_unres(Box::new(e1), start.to(end)), vec![inner]); e1 = Self::Call(Node::new(Box::new(e1), start.to(end)), args);
let Some(next2) = cursor.peek() else { let Some(next2) = cursor.peek() else {
return Ok(e1); return ParseResult::Ok(e1);
}; };
next = next2 next = next2
} }
let end = cursor.prev_end(); let end = cursor.prev_end();
Ok(if let Some(mut op) = Operator::from_token(&next.token) { let mut recover = false;
let res = if let Some(mut op) = BinaryOperator::from_token(&next.token) {
cursor.next(); cursor.next();
let mut n1 = Node::new_unres(e1, start.to(end)).bx(); let mut n1 = Node::new(e1, start.to(end)).bx();
let mut n2 = Node::parse(cursor, errors).bx(); let res = Node::parse(cursor, errors);
let mut n2 = res.node.bx();
recover = res.recover;
if let Ok(box Self::BinaryOp(op2, _, _)) = n2.as_ref() { if let Ok(box Self::BinaryOp(op2, _, _)) = n2.as_ref() {
if op.presedence() > op2.presedence() { if op.presedence() > op2.presedence() {
let Ok(box Self::BinaryOp(op2, n21, n22)) = n2.inner else { let Ok(box Self::BinaryOp(op2, n21, n22)) = n2.inner else {
unreachable!(); unreachable!();
}; };
let end = n21.span.end; let end = n21.span.end;
n1 = Node::new_unres(Self::BinaryOp(op, n1, n21), start.to(end)).bx(); n1 = Node::new(Self::BinaryOp(op, n1, n21), start.to(end)).bx();
op = op2; op = op2;
n2 = n22; n2 = n22;
} }
@@ -99,7 +109,8 @@ impl Parsable for Expr<Unresolved> {
Self::BinaryOp(op, n1, n2) Self::BinaryOp(op, n1, n2)
} else { } else {
e1 e1
}) };
ParseResult::from_recover(res, recover)
} }
} }
@@ -109,6 +120,7 @@ impl Resolvable<Expr<Resolved>> for Expr<Unresolved> {
Expr::Lit(l) => Expr::Lit(l.resolve()?), Expr::Lit(l) => Expr::Lit(l.resolve()?),
Expr::Ident(n) => Expr::Ident(n), Expr::Ident(n) => Expr::Ident(n),
Expr::BinaryOp(o, e1, e2) => Expr::BinaryOp(o, e1.resolve()?, e2.resolve()?), Expr::BinaryOp(o, e1, e2) => Expr::BinaryOp(o, e1.resolve()?, e2.resolve()?),
Expr::UnaryOp(o, e) => Expr::UnaryOp(o, e.resolve()?),
Expr::Block(b) => Expr::Block(b.resolve()?), Expr::Block(b) => Expr::Block(b.resolve()?),
Expr::Call(f, args) => Expr::Call( Expr::Call(f, args) => Expr::Call(
f.resolve()?, f.resolve()?,
@@ -148,6 +160,11 @@ impl Debug for Expr<Unresolved> {
} }
f.write_char(')')?; f.write_char(')')?;
} }
Expr::UnaryOp(op, e) => {
write!(f, "(")?;
write!(f, "{}", op.str())?;
write!(f, "{:?})", *e)?;
}
Expr::Group(inner) => inner.fmt(f)?, Expr::Group(inner) => inner.fmt(f)?,
} }
Ok(()) Ok(())

View File

@@ -1,5 +1,6 @@
use super::{ use super::{
Body, Keyword, MaybeResolved, Node, Parsable, ParserError, ParserErrors, Resolvable, Resolved, Symbol, TokenCursor, Unresolved Body, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable, Resolved,
Symbol, TokenCursor, Unresolved,
}; };
use std::fmt::Debug; use std::fmt::Debug;
@@ -9,13 +10,12 @@ pub struct Function<R: MaybeResolved> {
} }
impl Parsable for Function<Unresolved> { impl Parsable for Function<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
cursor.expect_kw(Keyword::Fn)?; cursor.expect_kw(Keyword::Fn)?;
let name = cursor.expect_ident()?; let name = cursor.expect_ident()?;
cursor.expect_sym(Symbol::OpenParen)?; cursor.expect_sym(Symbol::OpenParen)?;
cursor.expect_sym(Symbol::CloseParen)?; cursor.expect_sym(Symbol::CloseParen)?;
let body = Node::parse(cursor, errors); Node::parse(cursor, errors).map(|body| Self {name, body})
Ok(Self { name, body })
} }
} }
@@ -33,7 +33,7 @@ impl Resolvable<Function<Resolved>> for Function<Unresolved> {
fn resolve(self) -> Result<Function<Resolved>, ()> { fn resolve(self) -> Result<Function<Resolved>, ()> {
Ok(Function { Ok(Function {
name: self.name, name: self.name,
body: self.body.resolve()? body: self.body.resolve()?,
}) })
} }
} }

View File

@@ -0,0 +1,17 @@
mod body;
mod expr;
mod func;
mod module;
mod op;
mod statement;
mod val;
pub use body::*;
pub use expr::*;
pub use func::*;
pub use module::*;
pub use op::*;
pub use statement::*;
pub use val::*;
use super::*;

View File

@@ -1,6 +1,6 @@
use super::{ use super::{
func::Function, Keyword, MaybeResolved, Node, Parsable, ParserError, ParserErrors, Resolvable, Function, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserError, ParserErrors,
Resolved, TokenCursor, Unresolved, Resolvable, Resolved, TokenCursor, Unresolved,
}; };
use std::fmt::Debug; use std::fmt::Debug;
@@ -9,14 +9,18 @@ pub struct Module<R: MaybeResolved> {
} }
impl Parsable for Module<Unresolved> { impl Parsable for Module<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
let mut functions = Vec::new(); let mut functions = Vec::new();
loop { loop {
let Some(next) = cursor.peek() else { let Some(next) = cursor.peek() else {
return Ok(Self { functions }); return ParseResult::Ok(Self { functions });
}; };
if next.is_keyword(Keyword::Fn) { if next.is_keyword(Keyword::Fn) {
functions.push(Node::parse(cursor, errors)); let res = Node::parse(cursor, errors);
functions.push(res.node);
if res.recover {
return ParseResult::Recover(Self { functions });
}
} else { } else {
errors.add(ParserError::unexpected_token(next, "fn")); errors.add(ParserError::unexpected_token(next, "fn"));
cursor.next(); cursor.next();

96
src/parser/v1/nodes/op.rs Normal file
View File

@@ -0,0 +1,96 @@
use super::{Symbol, Token};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum BinaryOperator {
Add,
Sub,
Mul,
Div,
LessThan,
GreaterThan,
Access,
Assign,
}
impl BinaryOperator {
pub fn presedence(&self) -> u32 {
match self {
Self::Assign => 0,
Self::LessThan => 1,
Self::GreaterThan => 1,
Self::Add => 2,
Self::Sub => 3,
Self::Mul => 4,
Self::Div => 5,
Self::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 => Self::LessThan,
Symbol::CloseAngle => Self::GreaterThan,
Symbol::Plus => Self::Add,
Symbol::Minus => Self::Sub,
Symbol::Asterisk => Self::Mul,
Symbol::Slash => Self::Div,
Symbol::Dot => Self::Access,
Symbol::Equals => Self::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,
}
}
}
pub enum UnaryOperator {
Not,
Ref,
}
impl UnaryOperator {
pub fn str(&self) -> &str {
match self {
Self::Not => "!",
Self::Ref => "&",
}
}
pub fn from_token(token: &Token) -> Option<Self> {
let Token::Symbol(symbol) = token else {
return None;
};
Some(match symbol {
Symbol::Ampersand => Self::Ref,
Symbol::Bang => Self::Not,
_ => {
return None;
}
})
}
}

View File

@@ -1,7 +1,6 @@
use std::fmt::{Debug, Write}; use std::fmt::{Debug, Write};
use super::{ use super::{
Expr, Keyword, MaybeResolved, Node, Parsable, ParserError, ParserErrors, Resolvable, Resolved, Expr, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable, Resolved, Symbol, Token, TokenCursor, Unresolved
Symbol, Token, TokenCursor, Unresolved,
}; };
pub enum Statement<R: MaybeResolved> { pub enum Statement<R: MaybeResolved> {
@@ -10,34 +9,22 @@ pub enum Statement<R: MaybeResolved> {
Expr(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> { impl Parsable for Statement<Unresolved> {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
let next = cursor.expect_peek()?; let next = cursor.expect_peek()?;
Ok(match next.token { match next.token {
Token::Keyword(Keyword::Let) => { Token::Keyword(Keyword::Let) => {
cursor.next(); cursor.next();
let name = cursor.expect_ident()?; let name = cursor.expect_ident()?;
cursor.expect_sym(Symbol::Equals)?; cursor.expect_sym(Symbol::Equals)?;
let expr = Node::parse(cursor, errors); Node::parse(cursor, errors).map(|expr| Self::Let(name, expr))
Self::Let(name, expr)
} }
Token::Keyword(Keyword::Return) => { Token::Keyword(Keyword::Return) => {
cursor.next(); cursor.next();
Self::Return(Node::parse(cursor, errors)) Node::parse(cursor, errors).map(Self::Return)
} }
_ => Self::Expr(Node::parse(cursor, errors)), _ => Node::parse(cursor, errors).map(Self::Expr),
}) }
} }
} }

View File

@@ -1,71 +0,0 @@
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,
}
}
}

189
src/parser/v1/parse.rs Normal file
View File

@@ -0,0 +1,189 @@
use std::{
convert::Infallible,
ops::{ControlFlow, FromResidual, Try},
};
use super::{Node, ParserError, ParserErrors, TokenCursor, Unresolved};
pub enum ParseResult<T> {
Ok(T),
Recover(T),
Err(ParserError),
SubErr,
}
impl<T> ParseResult<T> {
pub fn from_recover(data: T, recover: bool) -> Self {
if recover {
Self::Recover(data)
} else {
Self::Ok(data)
}
}
}
impl<T> Try for ParseResult<T> {
type Output = Result<T, T>;
type Residual = Option<ParserError>;
fn from_output(output: Self::Output) -> Self {
match output {
Ok(v) => Self::Ok(v),
Err(v) => Self::Recover(v),
}
}
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
match self {
ParseResult::Ok(v) => ControlFlow::Continue(Ok(v)),
ParseResult::Recover(v) => ControlFlow::Continue(Err(v)),
ParseResult::Err(e) => ControlFlow::Break(Some(e)),
ParseResult::SubErr => ControlFlow::Break(None),
}
}
}
impl<T> FromResidual for ParseResult<T> {
fn from_residual(residual: <Self as Try>::Residual) -> Self {
match residual {
Some(err) => Self::Err(err),
None => Self::SubErr,
}
}
}
impl<T> FromResidual<Result<Infallible, ParserError>> for ParseResult<T> {
fn from_residual(residual: Result<Infallible, ParserError>) -> Self {
match residual {
Err(e) => Self::Err(e),
}
}
}
impl<T, U> FromResidual<ParseResult<T>> for ParseResult<U> {
fn from_residual(residual: ParseResult<T>) -> Self {
match residual {
ParseResult::Err(e) => Self::Err(e),
ParseResult::SubErr => Self::SubErr,
_ => unreachable!()
}
}
}
impl<T> ParseResult<T> {
pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> ParseResult<U> {
match self {
Self::Ok(v) => ParseResult::Ok(op(v)),
Self::Recover(v) => ParseResult::Recover(op(v)),
Self::Err(e) => ParseResult::Err(e),
Self::SubErr => ParseResult::SubErr,
}
}
}
pub struct NodeParseResult<T> {
pub node: Node<T, Unresolved>,
pub recover: bool,
}
impl<T> NodeParseResult<T> {
pub fn map<F: FnOnce(Node<T, Unresolved>) -> U, U>(self, op: F) -> ParseResult<U> {
let res = op(self.node);
if self.recover {
ParseResult::Recover(res)
} else {
ParseResult::Ok(res)
}
}
}
impl<T> Try for NodeParseResult<T> {
type Output = Node<T, Unresolved>;
type Residual = ParseResult<T>;
fn from_output(output: Self::Output) -> Self {
Self {
node: output,
recover: false,
}
}
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
if self.recover {
ControlFlow::Break(ParseResult::SubErr)
} else {
ControlFlow::Continue(self.node)
}
}
}
impl<T> FromResidual for NodeParseResult<T> {
fn from_residual(residual: <Self as Try>::Residual) -> Self {
// ???
unreachable!()
}
}
pub trait Parsable: Sized {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self>;
}
pub trait MaybeParsable: Sized {
fn maybe_parse(
cursor: &mut TokenCursor,
errors: &mut ParserErrors,
) -> Result<Option<Self>, ParserError>;
}
impl<T: Parsable> Node<T, Unresolved> {
pub fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> NodeParseResult<T> {
let start = cursor.next_pos();
let (inner, recover) = match T::parse(cursor, errors) {
ParseResult::Ok(v) => (Ok(v), false),
ParseResult::Recover(v) => (Ok(v), true),
ParseResult::Err(e) => {
errors.add(e);
(Err(()), true)
}
ParseResult::SubErr => (Err(()), true),
};
let end = cursor.prev_end();
NodeParseResult {
node: Self {
inner,
span: start.to(end),
},
recover,
}
}
}
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) {
Ok(v) => Ok(v?),
Err(e) => {
errors.add(e);
Err(())
}
};
let end = cursor.prev_end();
Some(Self {
inner,
span: start.to(end),
})
}
}
pub trait NodeParsable {
fn parse_node(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> NodeParseResult<Self>
where
Self: Sized;
}
impl<T: Parsable> NodeParsable for T {
fn parse_node(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> NodeParseResult<Self>
where
Self: Sized,
{
Node::<Self, Unresolved>::parse(cursor, errors)
}
}

View File

@@ -46,15 +46,6 @@ impl CharCursor<'_> {
self.next_pos.col += 1; self.next_pos.col += 1;
} }
} }
pub fn advance_if(&mut self, c: char) -> bool {
if let Some(c2) = self.peek() {
if c2 == c {
self.advance();
return true;
}
}
false
}
pub fn expect_next(&mut self) -> Result<char, ParserError> { pub fn expect_next(&mut self) -> Result<char, ParserError> {
self.next().ok_or(ParserError::unexpected_end()) self.next().ok_or(ParserError::unexpected_end())
} }

View File

@@ -16,12 +16,4 @@ impl Keyword {
_ => return None, _ => return None,
}) })
} }
pub const fn str(&self) -> &str {
match self {
Keyword::Fn => "fn",
Keyword::Let => "let",
Keyword::If => "if",
Keyword::Return => "return",
}
}
} }

View File

@@ -28,6 +28,10 @@ pub enum Symbol {
SingleQuote, SingleQuote,
DoubleQuote, DoubleQuote,
Bang, Bang,
Ampersand,
DoubleAmpersand,
Pipe,
DoublePipe,
} }
impl Symbol { impl Symbol {
@@ -59,6 +63,8 @@ impl Symbol {
'\'' => Self::SingleQuote, '\'' => Self::SingleQuote,
'"' => Self::DoubleQuote, '"' => Self::DoubleQuote,
'!' => Self::Bang, '!' => Self::Bang,
'&' => Self::Ampersand,
'|' => Self::Pipe,
_ => return None, _ => return None,
}) })
} }
@@ -79,10 +85,18 @@ impl Symbol {
'=' => Self::DoubleEquals, '=' => Self::DoubleEquals,
'>' => Self::DoubleArrow, '>' => Self::DoubleArrow,
_ => return, _ => return,
} },
Self::Slash => match next { Self::Slash => match next {
'/' => Self::DoubleSlash, '/' => Self::DoubleSlash,
_ => return, _ => return,
},
Self::Ampersand => match next {
'&' => Self::DoubleAmpersand,
_ => return,
}
Self::Pipe => match next {
'&' => Self::DoublePipe,
_ => return,
} }
_ => return, _ => return,
}; };
@@ -114,6 +128,10 @@ impl Symbol {
Self::SingleQuote => "'", Self::SingleQuote => "'",
Self::DoubleQuote => "\"", Self::DoubleQuote => "\"",
Self::Bang => "!", Self::Bang => "!",
Self::Ampersand => "&",
Self::DoubleAmpersand => "&&",
Self::Pipe => "|",
Self::DoublePipe => "||",
} }
} }
} }