added unary ops and control flow for parser
This commit is contained in:
@@ -29,3 +29,6 @@ fn test() {
|
||||
fn test2() {
|
||||
let a anerit;
|
||||
}
|
||||
|
||||
fn test3() {
|
||||
let x = 3
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
fn main() {
|
||||
let x = 3;
|
||||
let x = &"Hello World!";
|
||||
print(x);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
pub enum IRInstruction {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#![feature(box_patterns)]
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
mod util;
|
||||
mod compiler;
|
||||
|
||||
@@ -1,33 +1,25 @@
|
||||
use std::io::{stdout, BufRead, BufReader};
|
||||
|
||||
mod body;
|
||||
mod cursor;
|
||||
mod error;
|
||||
mod expr;
|
||||
mod module;
|
||||
mod node;
|
||||
mod op;
|
||||
mod nodes;
|
||||
mod parse;
|
||||
mod token;
|
||||
mod val;
|
||||
mod statement;
|
||||
mod func;
|
||||
|
||||
pub use body::*;
|
||||
pub use cursor::*;
|
||||
pub use error::*;
|
||||
pub use expr::*;
|
||||
pub use module::*;
|
||||
pub use node::*;
|
||||
pub use op::*;
|
||||
pub use nodes::*;
|
||||
pub use parse::*;
|
||||
use token::*;
|
||||
pub use val::*;
|
||||
pub use statement::*;
|
||||
|
||||
pub fn parse_file(file: &str) {
|
||||
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() {
|
||||
let module = node.resolve().expect("what");
|
||||
let module = res.node.resolve().expect("what");
|
||||
}
|
||||
let out = &mut stdout();
|
||||
for err in errors.errs {
|
||||
@@ -40,8 +32,12 @@ 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) = Statement::parse_node(&mut cursor, &mut errors).as_ref() {
|
||||
if let Ok(expr) = Statement::parse_node(&mut cursor, &mut errors).node.as_ref() {
|
||||
if cursor.next().is_none() {
|
||||
println!("{:?}", expr);
|
||||
} else {
|
||||
println!("uhhhh ehehe");
|
||||
}
|
||||
}
|
||||
let out = &mut stdout();
|
||||
for err in errors.errs {
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use super::{FileSpan, ParserError, ParserErrors, TokenCursor};
|
||||
use super::FileSpan;
|
||||
|
||||
pub trait MaybeResolved {
|
||||
type Inner<T>;
|
||||
@@ -24,63 +24,8 @@ pub struct Node<T, R: MaybeResolved> {
|
||||
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> {
|
||||
pub fn new_unres(inner: T, span: FileSpan) -> Self {
|
||||
pub fn new(inner: T, span: FileSpan) -> Self {
|
||||
Self {
|
||||
inner: Ok(inner),
|
||||
span,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
|
||||
use super::{
|
||||
token::Symbol, MaybeResolved, Node, NodeParsable, Parsable, ParserError, ParserErrors,
|
||||
Resolvable, Resolved, Statement, TokenCursor, Unresolved,
|
||||
token::Symbol, MaybeResolved, Node, NodeParsable, Parsable, ParseResult, ParserError,
|
||||
ParserErrors, Resolvable, Resolved, Statement, TokenCursor, Unresolved,
|
||||
};
|
||||
use crate::util::Padder;
|
||||
|
||||
@@ -11,20 +11,25 @@ pub struct Body<R: MaybeResolved> {
|
||||
}
|
||||
|
||||
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 statement_end = &[Symbol::Semicolon, Symbol::CloseCurly];
|
||||
cursor.expect_sym(Symbol::OpenCurly)?;
|
||||
if cursor.expect_peek()?.is_symbol(Symbol::CloseCurly) {
|
||||
cursor.next();
|
||||
return Ok(Self { statements });
|
||||
return ParseResult::Ok(Self { statements });
|
||||
}
|
||||
let mut expect_semi = false;
|
||||
let mut recover = false;
|
||||
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) {
|
||||
cursor.next();
|
||||
return Ok(Self { statements });
|
||||
break;
|
||||
}
|
||||
if next.is_symbol(Symbol::Semicolon) {
|
||||
cursor.next();
|
||||
@@ -36,15 +41,19 @@ impl Parsable for Body<Unresolved> {
|
||||
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;
|
||||
if statement.is_err() || statement.as_ref().is_ok_and(|s| s.ended_with_error()) {
|
||||
let res = cursor
|
||||
if res.recover
|
||||
&& cursor
|
||||
.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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::fmt::{Debug, Write};
|
||||
|
||||
use super::token::{Symbol, Token};
|
||||
use super::{
|
||||
Body, Literal, MaybeResolved, Node, Operator, Parsable, ParserError, ParserErrors, Resolvable,
|
||||
Resolved, TokenCursor, Unresolved,
|
||||
BinaryOperator, Body, Literal, MaybeResolved, Node, NodeParsable, Parsable, ParseResult,
|
||||
ParserError, ParserErrors, Resolvable, Resolved, TokenCursor, UnaryOperator, Unresolved,
|
||||
};
|
||||
|
||||
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> {
|
||||
Lit(Node<Literal, R>),
|
||||
Ident(String),
|
||||
BinaryOp(Operator, BoxNode<R>, BoxNode<R>),
|
||||
BinaryOp(BinaryOperator, BoxNode<R>, BoxNode<R>),
|
||||
UnaryOp(UnaryOperator, BoxNode<R>),
|
||||
Block(Node<Body<R>, R>),
|
||||
Call(BoxNode<R>, Vec<Node<Expr<R>, 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> {
|
||||
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 next = cursor.expect_peek()?;
|
||||
let mut e1 = if next.is_symbol(Symbol::OpenParen) {
|
||||
cursor.next();
|
||||
if cursor.expect_peek()?.is_symbol(Symbol::CloseParen) {
|
||||
cursor.next();
|
||||
return Ok(Expr::Lit(Node::new_unres(
|
||||
return ParseResult::Ok(Expr::Lit(Node::new(
|
||||
Literal::Unit,
|
||||
cursor.next_pos().char_span(),
|
||||
)));
|
||||
}
|
||||
let expr = Node::parse(cursor, errors).bx();
|
||||
if expr.is_err() {
|
||||
let res = Node::parse(cursor, errors);
|
||||
if res.recover {
|
||||
cursor.seek_sym(Symbol::CloseParen);
|
||||
}
|
||||
cursor.expect_sym(Symbol::CloseParen)?;
|
||||
Self::Group(expr)
|
||||
Self::Group(res.node.bx())
|
||||
} 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) {
|
||||
Self::Lit(val)
|
||||
} else {
|
||||
@@ -62,36 +61,47 @@ impl Parsable for Expr<Unresolved> {
|
||||
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 {
|
||||
return Ok(e1);
|
||||
return ParseResult::Ok(e1);
|
||||
};
|
||||
while next.is_symbol(Symbol::OpenParen) {
|
||||
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)?;
|
||||
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 {
|
||||
return Ok(e1);
|
||||
return ParseResult::Ok(e1);
|
||||
};
|
||||
next = next2
|
||||
}
|
||||
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();
|
||||
let mut n1 = Node::new_unres(e1, start.to(end)).bx();
|
||||
let mut n2 = Node::parse(cursor, errors).bx();
|
||||
let mut n1 = Node::new(e1, start.to(end)).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 op.presedence() > op2.presedence() {
|
||||
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();
|
||||
n1 = Node::new(Self::BinaryOp(op, n1, n21), start.to(end)).bx();
|
||||
op = op2;
|
||||
n2 = n22;
|
||||
}
|
||||
@@ -99,7 +109,8 @@ impl Parsable for Expr<Unresolved> {
|
||||
Self::BinaryOp(op, n1, n2)
|
||||
} else {
|
||||
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::Ident(n) => Expr::Ident(n),
|
||||
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::Call(f, args) => Expr::Call(
|
||||
f.resolve()?,
|
||||
@@ -148,6 +160,11 @@ impl Debug for Expr<Unresolved> {
|
||||
}
|
||||
f.write_char(')')?;
|
||||
}
|
||||
Expr::UnaryOp(op, e) => {
|
||||
write!(f, "(")?;
|
||||
write!(f, "{}", op.str())?;
|
||||
write!(f, "{:?})", *e)?;
|
||||
}
|
||||
Expr::Group(inner) => inner.fmt(f)?,
|
||||
}
|
||||
Ok(())
|
||||
@@ -1,5 +1,6 @@
|
||||
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;
|
||||
|
||||
@@ -9,13 +10,12 @@ pub struct Function<R: MaybeResolved> {
|
||||
}
|
||||
|
||||
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)?;
|
||||
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 })
|
||||
Node::parse(cursor, errors).map(|body| Self {name, body})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ impl Resolvable<Function<Resolved>> for Function<Unresolved> {
|
||||
fn resolve(self) -> Result<Function<Resolved>, ()> {
|
||||
Ok(Function {
|
||||
name: self.name,
|
||||
body: self.body.resolve()?
|
||||
body: self.body.resolve()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
17
src/parser/v1/nodes/mod.rs
Normal file
17
src/parser/v1/nodes/mod.rs
Normal 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::*;
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
func::Function, Keyword, MaybeResolved, Node, Parsable, ParserError, ParserErrors, Resolvable,
|
||||
Resolved, TokenCursor, Unresolved,
|
||||
Function, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserError, ParserErrors,
|
||||
Resolvable, Resolved, TokenCursor, Unresolved,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
@@ -9,14 +9,18 @@ pub struct Module<R: MaybeResolved> {
|
||||
}
|
||||
|
||||
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();
|
||||
loop {
|
||||
let Some(next) = cursor.peek() else {
|
||||
return Ok(Self { functions });
|
||||
return ParseResult::Ok(Self { functions });
|
||||
};
|
||||
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 {
|
||||
errors.add(ParserError::unexpected_token(next, "fn"));
|
||||
cursor.next();
|
||||
96
src/parser/v1/nodes/op.rs
Normal file
96
src/parser/v1/nodes/op.rs
Normal 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;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
use super::{
|
||||
Expr, Keyword, MaybeResolved, Node, Parsable, ParserError, ParserErrors, Resolvable, Resolved,
|
||||
Symbol, Token, TokenCursor, Unresolved,
|
||||
Expr, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable, Resolved, Symbol, Token, TokenCursor, Unresolved
|
||||
};
|
||||
|
||||
pub enum Statement<R: MaybeResolved> {
|
||||
@@ -10,34 +9,22 @@ pub enum Statement<R: MaybeResolved> {
|
||||
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> {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
|
||||
let next = cursor.expect_peek()?;
|
||||
Ok(match next.token {
|
||||
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)
|
||||
Node::parse(cursor, errors).map(|expr| Self::Let(name, expr))
|
||||
}
|
||||
Token::Keyword(Keyword::Return) => {
|
||||
cursor.next();
|
||||
Self::Return(Node::parse(cursor, errors))
|
||||
Node::parse(cursor, errors).map(Self::Return)
|
||||
}
|
||||
_ => Node::parse(cursor, errors).map(Self::Expr),
|
||||
}
|
||||
_ => Self::Expr(Node::parse(cursor, errors)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
189
src/parser/v1/parse.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -46,15 +46,6 @@ impl CharCursor<'_> {
|
||||
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> {
|
||||
self.next().ok_or(ParserError::unexpected_end())
|
||||
}
|
||||
|
||||
@@ -16,12 +16,4 @@ impl Keyword {
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
pub const fn str(&self) -> &str {
|
||||
match self {
|
||||
Keyword::Fn => "fn",
|
||||
Keyword::Let => "let",
|
||||
Keyword::If => "if",
|
||||
Keyword::Return => "return",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ pub enum Symbol {
|
||||
SingleQuote,
|
||||
DoubleQuote,
|
||||
Bang,
|
||||
Ampersand,
|
||||
DoubleAmpersand,
|
||||
Pipe,
|
||||
DoublePipe,
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
@@ -59,6 +63,8 @@ impl Symbol {
|
||||
'\'' => Self::SingleQuote,
|
||||
'"' => Self::DoubleQuote,
|
||||
'!' => Self::Bang,
|
||||
'&' => Self::Ampersand,
|
||||
'|' => Self::Pipe,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@@ -79,10 +85,18 @@ impl Symbol {
|
||||
'=' => Self::DoubleEquals,
|
||||
'>' => Self::DoubleArrow,
|
||||
_ => return,
|
||||
}
|
||||
},
|
||||
Self::Slash => match next {
|
||||
'/' => Self::DoubleSlash,
|
||||
_ => return,
|
||||
},
|
||||
Self::Ampersand => match next {
|
||||
'&' => Self::DoubleAmpersand,
|
||||
_ => return,
|
||||
}
|
||||
Self::Pipe => match next {
|
||||
'&' => Self::DoublePipe,
|
||||
_ => return,
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
@@ -114,6 +128,10 @@ impl Symbol {
|
||||
Self::SingleQuote => "'",
|
||||
Self::DoubleQuote => "\"",
|
||||
Self::Bang => "!",
|
||||
Self::Ampersand => "&",
|
||||
Self::DoubleAmpersand => "&&",
|
||||
Self::Pipe => "|",
|
||||
Self::DoublePipe => "||",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user