start of ir
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
mod v1;
|
||||
mod v2;
|
||||
|
||||
pub use v1::*;
|
||||
|
||||
pub fn main() {
|
||||
let arg = std::env::args_os().nth(1);
|
||||
if let Some(path) = arg {
|
||||
|
||||
@@ -36,6 +36,14 @@ impl<'a> TokenCursor<'a> {
|
||||
.is_some_and(|n| n.token != Token::Symbol(symbol))
|
||||
{}
|
||||
}
|
||||
pub fn seek_syms(&mut self, syms: &[Symbol]) {
|
||||
while self
|
||||
.peek()
|
||||
.is_some_and(|n| !syms.iter().any(|s| n.is_symbol(*s)))
|
||||
{
|
||||
self.next();
|
||||
}
|
||||
}
|
||||
pub fn seek(&mut self, f: impl Fn(&TokenInstance) -> bool) -> Option<&TokenInstance> {
|
||||
loop {
|
||||
if f(self.peek()?) {
|
||||
@@ -53,13 +61,6 @@ impl<'a> TokenCursor<'a> {
|
||||
pub fn expect_peek(&mut self) -> Result<&TokenInstance, ParserError> {
|
||||
self.peek().ok_or(ParserError::unexpected_end())
|
||||
}
|
||||
pub fn expect_ident(&mut self) -> Result<String, ParserError> {
|
||||
let i = self.expect_next()?;
|
||||
let Token::Ident(n) = &i.token else {
|
||||
return Err(ParserError::unexpected_token(&i, "an identifier"));
|
||||
};
|
||||
Ok(n.to_string())
|
||||
}
|
||||
pub fn chars(&mut self) -> &mut CharCursor<'a> {
|
||||
&mut self.cursor
|
||||
}
|
||||
|
||||
@@ -7,13 +7,12 @@ use super::{
|
||||
use crate::util::Padder;
|
||||
|
||||
pub struct Body<R: MaybeResolved> {
|
||||
statements: Vec<Node<Statement<R>, R>>,
|
||||
pub statements: Vec<Node<Statement<R>, R>>,
|
||||
}
|
||||
|
||||
impl Parsable for Body<Unresolved> {
|
||||
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();
|
||||
@@ -44,13 +43,12 @@ impl Parsable for Body<Unresolved> {
|
||||
let res = Statement::parse_node(cursor, errors);
|
||||
statements.push(res.node);
|
||||
expect_semi = true;
|
||||
if res.recover
|
||||
&& cursor
|
||||
.seek(|t| t.is_symbol_and(|s| statement_end.contains(&s)))
|
||||
.is_none()
|
||||
{
|
||||
recover = true;
|
||||
break;
|
||||
if res.recover {
|
||||
cursor.seek_syms(&[Symbol::Semicolon, Symbol::CloseCurly]);
|
||||
if cursor.peek().is_none() {
|
||||
recover = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ParseResult::from_recover(Self { statements }, recover)
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
|
||||
use super::token::{Symbol, Token};
|
||||
use super::{
|
||||
BinaryOperator, Body, Literal, MaybeResolved, Node, NodeParsable, Parsable, ParseResult,
|
||||
ParserError, ParserErrors, Resolvable, Resolved, TokenCursor, UnaryOperator, Unresolved,
|
||||
BinaryOperator, Body, Ident, Literal, MaybeResolved, Node, NodeParsable, Parsable, ParseResult,
|
||||
ParserError, ParserErrors, Resolvable, Resolved, Symbol, TokenCursor, UnaryOperator,
|
||||
Unresolved,
|
||||
};
|
||||
|
||||
type BoxNode<R> = Node<Box<Expr<R>>, R>;
|
||||
|
||||
pub enum Expr<R: MaybeResolved> {
|
||||
Lit(Node<Literal, R>),
|
||||
Ident(String),
|
||||
Ident(Node<Ident, R>),
|
||||
BinaryOp(BinaryOperator, BoxNode<R>, BoxNode<R>),
|
||||
UnaryOp(UnaryOperator, BoxNode<R>),
|
||||
Block(Node<Body<R>, R>),
|
||||
@@ -53,16 +53,12 @@ impl Parsable for Expr<Unresolved> {
|
||||
} else if let Some(val) = Node::maybe_parse(cursor, errors) {
|
||||
Self::Lit(val)
|
||||
} else {
|
||||
let next = cursor.peek().unwrap();
|
||||
match &next.token {
|
||||
Token::Ident(name) => {
|
||||
let name = name.to_string();
|
||||
cursor.next();
|
||||
Self::Ident(name)
|
||||
}
|
||||
_ => {
|
||||
return ParseResult::Err(ParserError::unexpected_token(next, "an expression"));
|
||||
}
|
||||
let res = Node::parse(cursor, &mut ParserErrors::new());
|
||||
if res.node.is_ok() {
|
||||
Self::Ident(res.node)
|
||||
} else {
|
||||
let next = cursor.expect_peek()?;
|
||||
return ParseResult::Err(ParserError::unexpected_token(next, "an expression"));
|
||||
}
|
||||
};
|
||||
let Some(mut next) = cursor.peek() else {
|
||||
@@ -71,13 +67,21 @@ impl Parsable for Expr<Unresolved> {
|
||||
while next.is_symbol(Symbol::OpenParen) {
|
||||
cursor.next();
|
||||
let mut args = Vec::new();
|
||||
while !cursor.expect_peek()?.is_symbol(Symbol::CloseParen) {
|
||||
loop {
|
||||
let next = cursor.expect_peek()?;
|
||||
if next.is_symbol(Symbol::CloseParen) {
|
||||
break;
|
||||
}
|
||||
let res = Node::<Expr<Unresolved>, Unresolved>::parse(cursor, errors);
|
||||
args.push(res.node);
|
||||
if res.recover {
|
||||
cursor.seek_sym(Symbol::CloseParen);
|
||||
cursor.seek_syms(&[Symbol::CloseParen, Symbol::Comma]);
|
||||
}
|
||||
let next = cursor.expect_peek()?;
|
||||
if !next.is_symbol(Symbol::Comma) {
|
||||
break;
|
||||
}
|
||||
cursor.next();
|
||||
}
|
||||
cursor.expect_sym(Symbol::CloseParen)?;
|
||||
let end = cursor.prev_end();
|
||||
@@ -118,7 +122,7 @@ 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::Ident(n) => Expr::Ident(n.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()?),
|
||||
@@ -137,7 +141,7 @@ impl Debug for Expr<Unresolved> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Expr::Lit(c) => c.fmt(f)?,
|
||||
Expr::Ident(n) => f.write_str(n)?,
|
||||
Expr::Ident(n) => n.fmt(f)?,
|
||||
Expr::Block(b) => b.fmt(f)?,
|
||||
Expr::BinaryOp(op, e1, e2) => {
|
||||
write!(f, "({:?}", *e1)?;
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
use super::{
|
||||
Body, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable, Resolved,
|
||||
Symbol, TokenCursor, Unresolved,
|
||||
Body, Ident, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable,
|
||||
Resolved, Symbol, TokenCursor, Unresolved,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub struct Function<R: MaybeResolved> {
|
||||
pub name: String,
|
||||
pub name: Node<Ident, R>,
|
||||
pub body: Node<Body<R>, R>,
|
||||
}
|
||||
|
||||
impl Parsable for Function<Unresolved> {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
|
||||
cursor.expect_kw(Keyword::Fn)?;
|
||||
let name = cursor.expect_ident()?;
|
||||
let name = Node::parse(cursor, errors)?;
|
||||
cursor.expect_sym(Symbol::OpenParen)?;
|
||||
cursor.expect_sym(Symbol::CloseParen)?;
|
||||
Node::parse(cursor, errors).map(|body| Self {name, body})
|
||||
Node::parse(cursor, errors).map(|body| 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)?;
|
||||
self.name.fmt(f)?;
|
||||
f.write_str("() ")?;
|
||||
self.body.fmt(f)?;
|
||||
Ok(())
|
||||
@@ -32,7 +32,7 @@ impl Debug for Function<Unresolved> {
|
||||
impl Resolvable<Function<Resolved>> for Function<Unresolved> {
|
||||
fn resolve(self) -> Result<Function<Resolved>, ()> {
|
||||
Ok(Function {
|
||||
name: self.name,
|
||||
name: self.name.resolve()?,
|
||||
body: self.body.resolve()?,
|
||||
})
|
||||
}
|
||||
|
||||
34
src/parser/v1/nodes/ident.rs
Normal file
34
src/parser/v1/nodes/ident.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use std::fmt::Debug;
|
||||
use super::{Parsable, ParseResult, ParserError, Resolvable, Token};
|
||||
|
||||
pub struct Ident(String);
|
||||
|
||||
impl Ident {
|
||||
pub fn val(&self) -> &String {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Parsable for Ident {
|
||||
fn parse(cursor: &mut super::TokenCursor, errors: &mut super::ParserErrors) -> ParseResult<Self> {
|
||||
let next = cursor.expect_peek()?;
|
||||
let Token::Ident(name) = &next.token else {
|
||||
return ParseResult::Err(ParserError::unexpected_token(next, "an identifier"));
|
||||
};
|
||||
let name = name.to_string();
|
||||
cursor.next();
|
||||
ParseResult::Ok(Self(name))
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Ident {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolvable<Ident> for Ident {
|
||||
fn resolve(self) -> Result<Ident, ()> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
use super::{CharCursor, MaybeParsable, ParserError, ParserErrors, Resolvable, Symbol, Token, TokenCursor};
|
||||
use super::{
|
||||
CharCursor, MaybeParsable, ParserError, ParserErrors, Resolvable, Symbol, Token, TokenCursor,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
@@ -17,7 +19,10 @@ pub struct Number {
|
||||
}
|
||||
|
||||
impl MaybeParsable for Literal {
|
||||
fn maybe_parse(cursor: &mut TokenCursor, _: &mut ParserErrors) -> Result<Option<Self>, ParserError> {
|
||||
fn maybe_parse(
|
||||
cursor: &mut TokenCursor,
|
||||
_: &mut ParserErrors,
|
||||
) -> Result<Option<Self>, ParserError> {
|
||||
let inst = cursor.expect_peek()?;
|
||||
let mut res = match &inst.token {
|
||||
Token::Symbol(Symbol::SingleQuote) => {
|
||||
@@ -42,15 +47,14 @@ impl MaybeParsable for Literal {
|
||||
_ => return Ok(None),
|
||||
};
|
||||
cursor.next();
|
||||
if let Some(next) = cursor.peek() {
|
||||
if let Self::Number(num) = &mut res {
|
||||
if let Token::Symbol(Symbol::Dot) = next.token {
|
||||
let chars = cursor.chars();
|
||||
if let Some(c) = chars.peek() {
|
||||
if c.is_ascii_digit() {
|
||||
if let (Some(next), Self::Number(num)) = (cursor.peek(), &mut res) {
|
||||
if next.token.is_symbol(Symbol::Dot) {
|
||||
cursor.next();
|
||||
if let Some(next) = cursor.peek() {
|
||||
if let Token::Ident(i) = &next.token {
|
||||
if i.chars().next().unwrap().is_ascii_digit() {
|
||||
num.decimal = Some(i.to_string());
|
||||
cursor.next();
|
||||
let decimal = cursor.expect_ident()?;
|
||||
num.decimal = Some(decimal);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,4 +118,3 @@ impl Debug for Number {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ mod func;
|
||||
mod module;
|
||||
mod op;
|
||||
mod statement;
|
||||
mod val;
|
||||
mod lit;
|
||||
mod ident;
|
||||
|
||||
pub use body::*;
|
||||
pub use expr::*;
|
||||
@@ -12,6 +13,7 @@ pub use func::*;
|
||||
pub use module::*;
|
||||
pub use op::*;
|
||||
pub use statement::*;
|
||||
pub use val::*;
|
||||
pub use lit::*;
|
||||
pub use ident::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
use super::{
|
||||
Expr, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable, Resolved, Symbol, Token, TokenCursor, Unresolved
|
||||
Expr, Ident, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable, Resolved, Symbol, Token, TokenCursor, Unresolved
|
||||
};
|
||||
|
||||
pub enum Statement<R: MaybeResolved> {
|
||||
Let(String, Node<Expr<R>, R>),
|
||||
Let(Node<Ident, R>, Node<Expr<R>, R>),
|
||||
Return(Node<Expr<R>, R>),
|
||||
Expr(Node<Expr<R>, R>),
|
||||
}
|
||||
@@ -15,7 +15,7 @@ impl Parsable for Statement<Unresolved> {
|
||||
match next.token {
|
||||
Token::Keyword(Keyword::Let) => {
|
||||
cursor.next();
|
||||
let name = cursor.expect_ident()?;
|
||||
let name = Node::parse(cursor, errors)?;
|
||||
cursor.expect_sym(Symbol::Equals)?;
|
||||
Node::parse(cursor, errors).map(|expr| Self::Let(name, expr))
|
||||
}
|
||||
@@ -31,7 +31,7 @@ impl Parsable for Statement<Unresolved> {
|
||||
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::Let(i, e) => Statement::Let(i.resolve()?, e.resolve()?),
|
||||
Self::Return(e) => Statement::Return(e.resolve()?),
|
||||
Self::Expr(e) => Statement::Expr(e.resolve()?),
|
||||
})
|
||||
@@ -43,7 +43,7 @@ impl Debug for Statement<Unresolved> {
|
||||
match self {
|
||||
Statement::Let(n, e) => {
|
||||
f.write_str("let ")?;
|
||||
f.write_str(n)?;
|
||||
n.fmt(f);
|
||||
f.write_str(" = ")?;
|
||||
e.fmt(f)?;
|
||||
f.write_char(';')?;
|
||||
|
||||
@@ -68,17 +68,6 @@ impl<T, U> FromResidual<ParseResult<T>> for ParseResult<U> {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -116,8 +105,8 @@ impl<T> Try for NodeParseResult<T> {
|
||||
}
|
||||
|
||||
impl<T> FromResidual for NodeParseResult<T> {
|
||||
fn from_residual(residual: <Self as Try>::Residual) -> Self {
|
||||
// ???
|
||||
fn from_residual(_: <Self as Try>::Residual) -> Self {
|
||||
// I hope this is unreachable ???
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ pub enum Symbol {
|
||||
DoubleAmpersand,
|
||||
Pipe,
|
||||
DoublePipe,
|
||||
Comma,
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
@@ -65,6 +66,7 @@ impl Symbol {
|
||||
'!' => Self::Bang,
|
||||
'&' => Self::Ampersand,
|
||||
'|' => Self::Pipe,
|
||||
',' => Self::Comma,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@@ -93,11 +95,11 @@ impl Symbol {
|
||||
Self::Ampersand => match next {
|
||||
'&' => Self::DoubleAmpersand,
|
||||
_ => return,
|
||||
}
|
||||
},
|
||||
Self::Pipe => match next {
|
||||
'&' => Self::DoublePipe,
|
||||
_ => return,
|
||||
}
|
||||
},
|
||||
_ => return,
|
||||
};
|
||||
cursor.advance();
|
||||
@@ -128,6 +130,7 @@ impl Symbol {
|
||||
Self::SingleQuote => "'",
|
||||
Self::DoubleQuote => "\"",
|
||||
Self::Bang => "!",
|
||||
Self::Comma => ",",
|
||||
Self::Ampersand => "&",
|
||||
Self::DoubleAmpersand => "&&",
|
||||
Self::Pipe => "|",
|
||||
|
||||
Reference in New Issue
Block a user