actually compiles and does stuff now

This commit is contained in:
2024-12-06 19:44:33 -05:00
parent 31c197e991
commit 620c4557e9
67 changed files with 1931 additions and 1287 deletions

View File

@@ -1,23 +1,59 @@
use crate::compiler::riscv64::AsmInstruction;
use super::{
util::parse_list, PIdent, Node, Parsable, ParseResult, PInstruction, ParserCtx, Symbol,
};
use super::{Parsable, ParseResult, Symbol};
#[derive(Debug)]
pub struct AsmBlock {
pub instructions: Vec<AsmInstruction>,
pub struct PAsmBlock {
pub instructions: Vec<Node<PInstruction>>,
pub args: Vec<Node<PAsmBlockArg>>,
}
impl Parsable for AsmBlock {
fn parse(
cursor: &mut super::TokenCursor,
output: &mut super::ParserOutput,
) -> ParseResult<Self> {
cursor.expect_sym(Symbol::OpenCurly)?;
pub struct PAsmBlockArg {
pub reg: Node<PIdent>,
pub var: Node<PIdent>,
}
impl Parsable for PAsmBlock {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let args = if ctx.expect_peek()?.is_symbol(Symbol::OpenParen) {
ctx.next();
parse_list(ctx, Symbol::CloseParen)?
} else {
Vec::new()
};
ctx.expect_sym(Symbol::OpenCurly)?;
let mut instructions = Vec::new();
while !cursor.expect_peek()?.is_symbol(Symbol::CloseCurly) {
instructions.push(AsmInstruction::parse(cursor, output)?);
while !ctx.expect_peek()?.is_symbol(Symbol::CloseCurly) {
let res = ctx.parse();
instructions.push(res.node);
if res.recover {
ctx.seek_sym_on_line(Symbol::CloseCurly);
}
}
cursor.expect_sym(Symbol::CloseCurly)?;
ParseResult::Ok(Self { instructions })
ctx.expect_sym(Symbol::CloseCurly)?;
ParseResult::Ok(Self { instructions, args })
}
}
impl Parsable for PAsmBlockArg {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let reg = ctx.parse()?;
ctx.expect_sym(Symbol::Equals)?;
let var = ctx.parse()?;
ParseResult::Ok(Self { reg, var })
}
}
impl std::fmt::Debug for PAsmBlock {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("asm {")?;
for i in &self.instructions {
f.write_str("\n ")?;
i.fmt(f)?;
}
if !self.instructions.is_empty() {
f.write_str("\n")?;
}
f.write_str("}")?;
Ok(())
}
}

View File

@@ -1,53 +1,63 @@
use crate::compiler::riscv64::{AsmInstruction, Reg};
use super::{
util::parse_list, AsmBlock, Ident, Keyword, Node, Parsable, ParseResult, SelfVar, Symbol,
util::parse_list, PAsmBlock, PIdent, Keyword, Node, Parsable, ParseResult, ParserCtx, Symbol, PType, PVarDef,
};
#[derive(Debug)]
pub struct AsmFunctionHeader {
pub name: Node<Ident>,
pub sel: Option<Node<SelfVar>>,
pub args: Vec<Node<Reg>>,
}
#[derive(Debug)]
pub struct AsmFunction {
pub header: Node<AsmFunctionHeader>,
pub body: Node<AsmBlock>,
}
impl Parsable for AsmFunctionHeader {
fn parse(
cursor: &mut super::TokenCursor,
output: &mut super::ParserOutput,
) -> ParseResult<Self> {
cursor.expect_kw(Keyword::Asm)?;
cursor.expect_kw(Keyword::Fn)?;
let name = Node::parse(cursor, output)?;
cursor.expect_sym(Symbol::OpenParen)?;
let sel = Node::maybe_parse(cursor, output);
if sel.is_some() {
if let Err(err) = cursor.expect_sym(Symbol::Comma) {
output.err(err);
cursor.seek_syms(&[Symbol::Comma, Symbol::CloseParen]);
if cursor.peek().is_some_and(|i| i.is_symbol(Symbol::Comma)) {
cursor.next();
}
}
}
let args = parse_list(cursor, output, Symbol::CloseParen)?;
ParseResult::Ok(Self { name, sel, args })
}
}
impl Parsable for AsmFunction {
fn parse(
cursor: &mut super::TokenCursor,
output: &mut super::ParserOutput,
) -> ParseResult<Self> {
let header = Node::parse(cursor, output)?;
let body = Node::parse(cursor, output)?;
ParseResult::Ok(Self { header, body })
}
}
// #[derive(Debug)]
// pub struct AsmFunctionHeader {
// pub name: Node<Ident>,
// pub args: Vec<Node<AsmVarDef>>,
// }
//
// #[derive(Debug)]
// pub struct AsmFunction {
// pub header: Node<AsmFunctionHeader>,
// pub body: Node<AsmBlock>,
// }
//
// impl Parsable for AsmFunctionHeader {
// fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
// ctx.expect_kw(Keyword::Asm)?;
// ctx.expect_kw(Keyword::Fn)?;
// let name = ctx.parse()?;
// ctx.expect_sym(Symbol::OpenParen)?;
// let args = parse_list(ctx, Symbol::CloseParen)?;
// ParseResult::Ok(Self { name, args })
// }
// }
//
// impl Parsable for AsmFunction {
// fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
// let header = ctx.parse()?;
// let body = ctx.parse()?;
// ParseResult::Ok(Self { header, body })
// }
// }
//
// pub struct AsmVarDef {
// pub reg: Node<Ident>,
// pub name: Node<Ident>,
// pub ty: Option<Node<Type>>,
// }
//
// impl Parsable for AsmVarDef {
// fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
// let reg = ctx.parse()?;
// let name = ctx.parse()?;
// if ctx.peek().is_some_and(|n| n.is_symbol(Symbol::Colon)) {
// ctx.next();
// ctx.parse().map(|ty| Self { reg, name, ty: Some(ty) })
// } else {
// ParseResult::Ok(Self { reg, name, ty: None })
// }
// }
// }
//
// impl std::fmt::Debug for AsmVarDef {
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// self.name.fmt(f)?;
// if let Some(ty) = &self.ty {
// write!(f, ": {:?}", ty)?;
// }
// Ok(())
// }
// }

View File

@@ -0,0 +1,82 @@
use super::{PIdent, Node, Parsable, ParseResult, ParserCtx, ParserMsg, Symbol};
pub struct PInstruction {
pub op: Node<PIdent>,
pub args: Vec<Node<PAsmArg>>,
}
pub enum PAsmArg {
Value(Node<PIdent>),
Ref(Node<PIdent>),
}
impl Parsable for PInstruction {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let op = ctx.parse()?;
let mut args = Vec::new();
if !ctx.next_on_new_line() {
let arg = ctx.parse()?;
args.push(arg);
loop {
if ctx.next_on_new_line() {
break;
}
ctx.expect_sym(Symbol::Comma)?;
let arg = ctx.parse()?;
args.push(arg);
}
}
ParseResult::Ok(Self { op, args })
}
}
impl Parsable for PAsmArg {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
if let Some(ident) = ctx.maybe_parse() {
return ParseResult::Ok(Self::Value(ident));
}
let next = ctx.expect_peek()?;
if !next.is_symbol(Symbol::OpenCurly) {
return ParseResult::Err(ParserMsg::unexpected_token(
next,
"An identifier or {identifier}",
));
}
ctx.next();
let res = ctx.parse();
if res.recover {
ctx.seek_sym(Symbol::CloseCurly);
return ParseResult::SubErr;
}
ctx.expect_sym(Symbol::CloseCurly)?;
ParseResult::Ok(Self::Ref(res.node))
}
}
impl std::fmt::Debug for PAsmArg {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Value(v) => v.fmt(f),
Self::Ref(r) => write!(f, "{{{:?}}}", r),
}
}
}
impl std::fmt::Debug for PInstruction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.op.fmt(f)?;
let mut iter = self.args.iter();
if let Some(arg) = iter.next() {
f.write_str(" ")?;
arg.fmt(f)?;
}
for arg in iter {
f.write_str(", ")?;
arg.fmt(f)?;
}
Ok(())
}
}

View File

@@ -1,53 +1,52 @@
use std::fmt::{Debug, Write};
use super::{
token::Symbol, Node, NodeParsable, Parsable, ParseResult, ParserMsg, ParserOutput, Statement,
TokenCursor,
token::Symbol, Node, NodeParsable, Parsable, ParseResult, ParserCtx, ParserMsg, PStatement,
};
use crate::util::Padder;
pub struct Block {
pub statements: Vec<Node<Statement>>,
pub result: Option<Node<Box<Statement>>>,
pub struct PBlock {
pub statements: Vec<Node<PStatement>>,
pub result: Option<Node<Box<PStatement>>>,
}
impl Parsable for Block {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserOutput) -> ParseResult<Self> {
impl Parsable for PBlock {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let mut statements = Vec::new();
let mut result = None;
cursor.expect_sym(Symbol::OpenCurly)?;
if cursor.expect_peek()?.is_symbol(Symbol::CloseCurly) {
cursor.next();
ctx.expect_sym(Symbol::OpenCurly)?;
if ctx.expect_peek()?.is_symbol(Symbol::CloseCurly) {
ctx.next();
return ParseResult::Ok(Self { statements, result });
}
let mut expect_semi = false;
let mut recover = false;
loop {
let Some(next) = cursor.peek() else {
let Some(next) = ctx.peek() else {
recover = true;
errors.err(ParserMsg::unexpected_end());
ctx.err(ParserMsg::unexpected_end());
break;
};
if next.is_symbol(Symbol::CloseCurly) {
cursor.next();
ctx.next();
break;
}
if next.is_symbol(Symbol::Semicolon) {
cursor.next();
ctx.next();
expect_semi = false;
continue;
} else if expect_semi {
errors.err(ParserMsg {
ctx.err(ParserMsg {
msg: "expected ';'".to_string(),
spans: vec![cursor.next_pos().char_span()],
spans: vec![ctx.next_start().char_span()],
});
}
let res = Statement::parse_node(cursor, errors);
let res = PStatement::parse_node(ctx);
statements.push(res.node);
expect_semi = true;
if res.recover {
cursor.seek_syms(&[Symbol::Semicolon, Symbol::CloseCurly]);
if cursor.peek().is_none() {
ctx.seek_syms(&[Symbol::Semicolon, Symbol::CloseCurly]);
if ctx.peek().is_none() {
recover = true;
break;
}
@@ -62,14 +61,17 @@ impl Parsable for Block {
}
}
impl Debug for Block {
impl Debug for PBlock {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.statements.first().is_some() {
if !self.statements.is_empty() || self.result.is_some() {
f.write_str("{\n ")?;
let mut padder = Padder::new(f);
for s in &self.statements {
// they don't expose wrap_buf :grief:
padder.write_str(&format!("{s:?}\n"))?;
padder.write_str(&format!("{s:?};\n"))?;
}
if let Some(res) = &self.result {
padder.write_str(&format!("{res:?}\n"))?;
}
f.write_char('}')?;
} else {

View File

@@ -1,21 +1,20 @@
use std::fmt::Debug;
use super::{Ident, MaybeParsable, Node, Parsable, ParseResult, ParserMsg, Symbol, Token, Type};
use super::{
PIdent, MaybeParsable, Node, Parsable, ParseResult, ParserCtx, ParserMsg, Symbol, Token, PType,
};
pub struct VarDef {
pub name: Node<Ident>,
pub ty: Option<Node<Type>>,
pub struct PVarDef {
pub name: Node<PIdent>,
pub ty: Option<Node<PType>>,
}
impl Parsable for VarDef {
fn parse(
cursor: &mut super::TokenCursor,
errors: &mut super::ParserOutput,
) -> ParseResult<Self> {
let name = Node::parse(cursor, errors)?;
if cursor.peek().is_some_and(|n| n.is_symbol(Symbol::Colon)) {
cursor.next();
Node::parse(cursor, errors).map(|ty| Self { name, ty: Some(ty) })
impl Parsable for PVarDef {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let name = ctx.parse()?;
if ctx.peek().is_some_and(|n| n.is_symbol(Symbol::Colon)) {
ctx.next();
ctx.parse().map(|ty| Self { name, ty: Some(ty) })
} else {
ParseResult::Ok(Self { name, ty: None })
}
@@ -33,20 +32,17 @@ pub enum SelfType {
}
impl MaybeParsable for SelfVar {
fn maybe_parse(
cursor: &mut super::TokenCursor,
errors: &mut super::ParserOutput,
) -> Result<Option<Self>, super::ParserMsg> {
if let Some(mut next) = cursor.peek() {
fn maybe_parse(ctx: &mut ParserCtx) -> Result<Option<Self>, super::ParserMsg> {
if let Some(mut next) = ctx.peek() {
let mut ty = SelfType::Take;
if next.is_symbol(Symbol::Ampersand) {
cursor.next();
ctx.next();
ty = SelfType::Ref;
next = cursor.expect_peek()?;
next = ctx.expect_peek()?;
}
if let Token::Word(name) = &next.token {
if name == "self" {
cursor.next();
ctx.next();
return Ok(Some(Self { ty }));
}
}
@@ -58,7 +54,7 @@ impl MaybeParsable for SelfVar {
}
}
impl Debug for VarDef {
impl Debug for PVarDef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.name.fmt(f)?;
if let Some(ty) = &self.ty {

View File

@@ -1,52 +1,52 @@
use std::fmt::{Debug, Write};
use super::{
op::{BinaryOp, UnaryOp},
op::{PInfixOp, UnaryOp},
util::parse_list,
AsmBlock, Block, Ident, Keyword, Literal, Node, NodeParsable, Parsable, ParseResult, ParserMsg,
ParserOutput, Symbol, TokenCursor,
PAsmBlock, PBlock, PIdent, Keyword, PLiteral, Node, NodeParsable, Parsable, ParseResult, ParserCtx,
ParserMsg, Symbol,
};
type BoxNode = Node<Box<Expr>>;
type BoxNode = Node<Box<PExpr>>;
pub enum Expr {
Lit(Node<Literal>),
Ident(Node<Ident>),
BinaryOp(BinaryOp, BoxNode, BoxNode),
pub enum PExpr {
Lit(Node<PLiteral>),
Ident(Node<PIdent>),
BinaryOp(PInfixOp, BoxNode, BoxNode),
UnaryOp(UnaryOp, BoxNode),
Block(Node<Block>),
Call(BoxNode, Vec<Node<Expr>>),
Block(Node<PBlock>),
Call(BoxNode, Vec<Node<PExpr>>),
Group(BoxNode),
AsmBlock(Node<AsmBlock>),
AsmBlock(Node<PAsmBlock>),
}
impl Parsable for Expr {
fn parse(cursor: &mut TokenCursor, output: &mut ParserOutput) -> ParseResult<Self> {
let start = cursor.next_pos();
let next = cursor.expect_peek()?;
impl Parsable for PExpr {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let start = ctx.next_start();
let next = ctx.expect_peek()?;
let mut e1 = if next.is_symbol(Symbol::OpenParen) {
cursor.next();
if cursor.expect_peek()?.is_symbol(Symbol::CloseParen) {
cursor.next();
return ParseResult::Ok(Expr::Lit(Node::new(
Literal::Unit,
cursor.next_pos().char_span(),
ctx.next();
if ctx.expect_peek()?.is_symbol(Symbol::CloseParen) {
ctx.next();
return ParseResult::Ok(PExpr::Lit(Node::new(
PLiteral::Unit,
ctx.next_start().char_span(),
)));
}
let res = Node::parse(cursor, output);
let res = ctx.parse();
if res.recover {
cursor.seek_sym(Symbol::CloseParen);
ctx.seek_sym(Symbol::CloseParen);
}
cursor.expect_sym(Symbol::CloseParen)?;
ctx.expect_sym(Symbol::CloseParen)?;
Self::Group(res.node.bx())
} else if next.is_symbol(Symbol::OpenCurly) {
Self::Block(Block::parse_node(cursor, output)?)
Self::Block(PBlock::parse_node(ctx)?)
} else if next.is_keyword(Keyword::Asm) {
cursor.next();
Self::AsmBlock(Node::parse(cursor, output)?)
ctx.next();
Self::AsmBlock(ctx.parse()?)
} else if let Some(op) = UnaryOp::from_token(next) {
cursor.next();
return Node::parse(cursor, output).map(|n| {
ctx.next();
return ctx.parse().map(|n| {
let n = n.bx();
if let Some(box Self::BinaryOp(op2, n1, n2)) = n.inner {
let span = start.to(n1.span.end);
@@ -55,36 +55,36 @@ impl Parsable for Expr {
Self::UnaryOp(op, n)
}
});
} else if let Some(val) = Node::maybe_parse(cursor, output) {
} else if let Some(val) = Node::maybe_parse(ctx) {
Self::Lit(val)
} else {
let res = Node::parse(cursor, &mut ParserOutput::new());
let res = ctx.parse();
if res.node.is_some() {
Self::Ident(res.node)
} else {
let next = cursor.expect_peek()?;
let next = ctx.expect_peek()?;
return ParseResult::Err(ParserMsg::unexpected_token(next, "an expression"));
}
};
let Some(mut next) = cursor.peek() else {
let Some(mut next) = ctx.peek() else {
return ParseResult::Ok(e1);
};
while next.is_symbol(Symbol::OpenParen) {
cursor.next();
let args = parse_list(cursor, output, Symbol::CloseParen)?;
let end = cursor.prev_end();
ctx.next();
let args = parse_list(ctx, Symbol::CloseParen)?;
let end = ctx.prev_end();
e1 = Self::Call(Node::new(Box::new(e1), start.to(end)), args);
let Some(next2) = cursor.peek() else {
let Some(next2) = ctx.peek() else {
return ParseResult::Ok(e1);
};
next = next2
}
let end = cursor.prev_end();
let end = ctx.prev_end();
let mut recover = false;
let res = if let Some(mut op) = BinaryOp::from_token(&next.token) {
cursor.next();
let res = if let Some(mut op) = PInfixOp::from_token(&next.token) {
ctx.next();
let mut n1 = Node::new(e1, start.to(end)).bx();
let res = Node::parse(cursor, output);
let res = ctx.parse();
let mut n2 = res.node.bx();
recover = res.recover;
if let Some(box Self::BinaryOp(op2, _, _)) = n2.as_ref() {
@@ -106,13 +106,13 @@ impl Parsable for Expr {
}
}
impl Debug for Expr {
impl Debug for PExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expr::Lit(c) => c.fmt(f)?,
Expr::Ident(n) => n.fmt(f)?,
Expr::Block(b) => b.fmt(f)?,
Expr::BinaryOp(op, e1, e2) => {
PExpr::Lit(c) => c.fmt(f)?,
PExpr::Ident(n) => n.fmt(f)?,
PExpr::Block(b) => b.fmt(f)?,
PExpr::BinaryOp(op, e1, e2) => {
write!(f, "({:?}", *e1)?;
if op.pad() {
write!(f, " {} ", op.str())?;
@@ -121,7 +121,7 @@ impl Debug for Expr {
}
write!(f, "{:?})", *e2)?;
}
Expr::Call(n, args) => {
PExpr::Call(n, args) => {
n.fmt(f)?;
f.write_char('(')?;
if let Some(a) = args.first() {
@@ -133,13 +133,13 @@ impl Debug for Expr {
}
f.write_char(')')?;
}
Expr::UnaryOp(op, e) => {
PExpr::UnaryOp(op, e) => {
write!(f, "(")?;
write!(f, "{}", op.str())?;
write!(f, "{:?})", *e)?;
}
Expr::Group(inner) => inner.fmt(f)?,
Expr::AsmBlock(inner) => inner.fmt(f)?,
PExpr::Group(inner) => inner.fmt(f)?,
PExpr::AsmBlock(inner) => inner.fmt(f)?,
}
Ok(())
}

View File

@@ -1,71 +1,69 @@
use super::{
util::parse_list, Block, Ident, Keyword, Node, Parsable, ParseResult, ParserOutput, SelfVar,
Symbol, TokenCursor, Type, VarDef,
util::parse_list, PBlock, PIdent, Keyword, Node, Parsable, ParseResult, ParserCtx,
Symbol, PType, PVarDef,
};
use std::fmt::Debug;
pub struct FunctionHeader {
pub name: Node<Ident>,
pub sel: Option<Node<SelfVar>>,
pub args: Vec<Node<VarDef>>,
pub ret: Option<Node<Type>>,
pub struct PFunctionHeader {
pub name: Node<PIdent>,
pub args: Vec<Node<PVarDef>>,
pub ret: Option<Node<PType>>,
}
pub struct Function {
pub header: Node<FunctionHeader>,
pub body: Node<Block>,
pub struct PFunction {
pub header: Node<PFunctionHeader>,
pub body: Node<PBlock>,
}
impl Parsable for FunctionHeader {
fn parse(cursor: &mut TokenCursor, output: &mut ParserOutput) -> ParseResult<Self> {
cursor.expect_kw(Keyword::Fn)?;
let name = Node::parse(cursor, output)?;
cursor.expect_sym(Symbol::OpenParen)?;
let sel = Node::maybe_parse(cursor, output);
if sel.is_some() {
if let Err(err) = cursor.expect_sym(Symbol::Comma) {
output.err(err);
cursor.seek_syms(&[Symbol::Comma, Symbol::CloseParen]);
if cursor.peek().is_some_and(|i| i.is_symbol(Symbol::Comma)) {
cursor.next();
}
}
}
let args = parse_list(cursor, output, Symbol::CloseParen)?;
let ret = if cursor.peek().is_some_and(|i| i.is_symbol(Symbol::Arrow)) {
cursor.next();
Some(Node::parse(cursor, output)?)
impl Parsable for PFunctionHeader {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
ctx.expect_kw(Keyword::Fn)?;
let name = ctx.parse()?;
ctx.expect_sym(Symbol::OpenParen)?;
// let sel = ctx.maybe_parse();
// if sel.is_some() {
// if let Err(err) = ctx.expect_sym(Symbol::Comma) {
// ctx.err(err);
// ctx.seek_syms(&[Symbol::Comma, Symbol::CloseParen]);
// if ctx.peek().is_some_and(|i| i.is_symbol(Symbol::Comma)) {
// ctx.next();
// }
// }
// }
let args = parse_list(ctx, Symbol::CloseParen)?;
let ret = if ctx.peek().is_some_and(|i| i.is_symbol(Symbol::Arrow)) {
ctx.next();
Some(ctx.parse()?)
} else {
None
};
ParseResult::Ok(Self {
name,
args,
sel,
ret,
})
}
}
impl Parsable for Function {
fn parse(cursor: &mut TokenCursor, output: &mut ParserOutput) -> ParseResult<Self> {
let header = Node::parse(cursor, output)?;
let body = Node::parse(cursor, output)?;
impl Parsable for PFunction {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let header = ctx.parse()?;
let body = ctx.parse()?;
ParseResult::Ok(Self { header, body })
}
}
impl Debug for FunctionHeader {
impl Debug for PFunctionHeader {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("fn ")?;
self.name.fmt(f)?;
f.write_str("(")?;
if let Some(s) = &self.sel {
s.fmt(f)?;
if self.args.first().is_some() {
f.write_str(", ")?;
}
}
// if let Some(s) = &self.sel {
// s.fmt(f)?;
// if self.args.first().is_some() {
// f.write_str(", ")?;
// }
// }
if let Some(a) = self.args.first() {
a.fmt(f)?;
}
@@ -80,7 +78,7 @@ impl Debug for FunctionHeader {
Ok(())
}
}
impl Debug for Function {
impl Debug for PFunction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.header.fmt(f)?;
f.write_str(" ")?;

View File

@@ -1,29 +1,52 @@
use std::fmt::Debug;
use super::{Parsable, ParseResult, ParserMsg, Token};
use super::{MaybeParsable, Parsable, ParseResult, ParserCtx, ParserMsg, Token};
use std::{
fmt::{Debug, Display},
ops::Deref,
};
pub struct Ident(String);
#[derive(Clone)]
pub struct PIdent(String);
impl Ident {
pub fn val(&self) -> &String {
&self.0
}
}
impl Parsable for Ident {
fn parse(cursor: &mut super::TokenCursor, errors: &mut super::ParserOutput) -> ParseResult<Self> {
let next = cursor.expect_peek()?;
impl Parsable for PIdent {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let next = ctx.expect_peek()?;
let Token::Word(name) = &next.token else {
return ParseResult::Err(ParserMsg::unexpected_token(next, "an identifier"));
};
let name = name.to_string();
cursor.next();
ctx.next();
ParseResult::Ok(Self(name))
}
}
impl Debug for Ident {
impl MaybeParsable for PIdent {
fn maybe_parse(ctx: &mut ParserCtx) -> Result<Option<Self>, ParserMsg> {
let Some(next) = ctx.peek() else { return Ok(None) };
let Token::Word(name) = &next.token else {
return Ok(None);
};
let name = name.to_string();
ctx.next();
Ok(Some(Self(name)))
}
}
impl Debug for PIdent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Deref for PIdent {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Display for PIdent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}

View File

@@ -1,38 +1,35 @@
use super::{CharCursor, MaybeParsable, ParserMsg, ParserOutput, Symbol, Token, TokenCursor};
use super::{CharCursor, MaybeParsable, ParserCtx, ParserMsg, Symbol, Token};
use std::fmt::Debug;
#[derive(Clone, PartialEq, Eq)]
pub enum Literal {
pub enum PLiteral {
String(String),
Char(char),
Number(Number),
Number(PNumber),
Unit,
}
#[derive(Clone, PartialEq, Eq)]
pub struct Number {
pub struct PNumber {
pub whole: String,
pub decimal: Option<String>,
pub ty: Option<String>,
}
impl MaybeParsable for Literal {
fn maybe_parse(
cursor: &mut TokenCursor,
_: &mut ParserOutput,
) -> Result<Option<Self>, ParserMsg> {
let inst = cursor.expect_peek()?;
impl MaybeParsable for PLiteral {
fn maybe_parse(ctx: &mut ParserCtx) -> Result<Option<Self>, ParserMsg> {
let inst = ctx.expect_peek()?;
Ok(Some(match &inst.token {
Token::Symbol(Symbol::SingleQuote) => {
let chars = cursor.chars();
let chars = ctx.chars();
let c = chars.expect_next()?;
chars.expect('\'')?;
cursor.next();
ctx.next();
Self::Char(c)
}
Token::Symbol(Symbol::DoubleQuote) => {
let res = Self::String(string_from(cursor.chars())?);
cursor.next();
let res = Self::String(string_from(ctx.chars())?);
ctx.next();
res
}
Token::Word(text) => {
@@ -41,21 +38,21 @@ impl MaybeParsable for Literal {
return Ok(None);
}
let (whole, ty) = parse_whole_num(text);
let mut num = Number {
let mut num = PNumber {
whole,
decimal: None,
ty,
};
cursor.next();
if num.ty.is_none() && cursor.peek().is_some_and(|i| i.is_symbol(Symbol::Dot)) {
cursor.next();
if let Some(next) = cursor.peek() {
ctx.next();
if num.ty.is_none() && ctx.peek().is_some_and(|i| i.is_symbol(Symbol::Dot)) {
ctx.next();
if let Some(next) = ctx.peek() {
if let Token::Word(i) = &next.token {
if i.chars().next().unwrap().is_ascii_digit() {
let (decimal, ty) = parse_whole_num(i);
num.decimal = Some(decimal);
num.ty = ty;
cursor.next();
ctx.next();
}
}
}
@@ -110,7 +107,7 @@ pub fn string_from(cursor: &mut CharCursor) -> Result<String, ParserMsg> {
}
}
impl Debug for Literal {
impl Debug for PLiteral {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::String(str) => str.fmt(f),
@@ -121,7 +118,7 @@ impl Debug for Literal {
}
}
impl Debug for Number {
impl Debug for PNumber {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.whole)?;
if let Some(d) = &self.decimal {

View File

@@ -13,6 +13,7 @@ mod util;
mod trai;
mod asm_fn;
mod asm_block;
mod asm_instr;
pub use block::*;
pub use expr::*;
@@ -28,6 +29,7 @@ pub use trai::*;
pub use op::*;
pub use asm_fn::*;
pub use asm_block::*;
pub use asm_instr::*;
use super::*;

View File

@@ -1,79 +1,70 @@
use super::{
AsmFunction, Function, Impl, Keyword, Node, Parsable, ParseResult, ParserMsg, ParserOutput,
Struct, Symbol, Token, TokenCursor, Trait,
PFunction, PImpl, Keyword, Node, Parsable, ParseResult, ParserCtx, ParserMsg,
PStruct, Symbol, Token, PTrait,
};
use std::fmt::Debug;
pub struct Module {
pub traits: Vec<Node<Trait>>,
pub structs: Vec<Node<Struct>>,
pub functions: Vec<Node<Function>>,
pub asm_fns: Vec<Node<AsmFunction>>,
pub impls: Vec<Node<Impl>>,
pub struct PModule {
pub traits: Vec<Node<PTrait>>,
pub structs: Vec<Node<PStruct>>,
pub functions: Vec<Node<PFunction>>,
pub impls: Vec<Node<PImpl>>,
}
impl Parsable for Module {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserOutput) -> ParseResult<Self> {
impl Parsable for PModule {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let mut functions = Vec::new();
let mut structs = Vec::new();
let mut traits = Vec::new();
let mut impls = Vec::new();
let mut asm_fns = Vec::new();
loop {
let Some(next) = cursor.peek() else {
let Some(next) = ctx.peek() else {
break;
};
if let Token::Keyword(kw) = next.token {
match kw {
Keyword::Fn => {
let res = Node::parse(cursor, errors);
let res = ctx.parse();
functions.push(res.node);
if res.recover {
break;
}
}
Keyword::Struct => {
let res = Node::parse(cursor, errors);
let res = ctx.parse();
structs.push(res.node);
if res.recover {
break;
}
}
Keyword::Trait => {
let res = Node::parse(cursor, errors);
let res = ctx.parse();
traits.push(res.node);
if res.recover {
break;
}
}
Keyword::Impl => {
let res = Node::parse(cursor, errors);
let res = ctx.parse();
impls.push(res.node);
if res.recover {
break;
}
}
Keyword::Asm => {
let res = Node::parse(cursor, errors);
asm_fns.push(res.node);
if res.recover {
break;
}
}
_ => {
errors.err(ParserMsg::unexpected_token(next, "a definition"));
cursor.next();
ctx.err(ParserMsg::unexpected_token(next, "a definition"));
ctx.next();
}
}
} else if next.is_symbol(Symbol::Semicolon) {
errors.hint(ParserMsg::from_instances(
ctx.hint(ParserMsg::from_instances(
&[next],
"unneeded semicolon".to_string(),
));
cursor.next();
ctx.next();
} else {
errors.err(ParserMsg::unexpected_token(next, "a definition"));
cursor.next();
ctx.err(ParserMsg::unexpected_token(next, "a definition"));
ctx.next();
}
}
ParseResult::Ok(Self {
@@ -81,12 +72,11 @@ impl Parsable for Module {
structs,
traits,
impls,
asm_fns,
})
}
}
impl Debug for Module {
impl Debug for PModule {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for st in &self.structs {
st.fmt(f)?;
@@ -104,10 +94,6 @@ impl Debug for Module {
func.fmt(f)?;
writeln!(f)?;
}
for func in &self.asm_fns {
func.fmt(f)?;
writeln!(f)?;
}
Ok(())
}
}

View File

@@ -1,7 +1,7 @@
use super::{Symbol, Token};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum BinaryOp {
pub enum PInfixOp {
Add,
Sub,
Mul,
@@ -12,7 +12,7 @@ pub enum BinaryOp {
Assign,
}
impl BinaryOp {
impl PInfixOp {
pub fn presedence(&self) -> u32 {
match self {
Self::Assign => 0,
@@ -69,7 +69,7 @@ pub enum UnaryOp {
Deref,
}
impl BinaryOp {
impl PInfixOp {
pub fn from_token(token: &Token) -> Option<Self> {
let Token::Symbol(symbol) = token else {
return None;

View File

@@ -1,51 +1,45 @@
use super::{
Expr, Keyword, Node, Parsable, ParseResult, ParserOutput, Symbol, Token, TokenCursor, VarDef,
};
use std::fmt::{Debug, Write};
use super::{PExpr, Keyword, Node, Parsable, ParseResult, ParserCtx, Symbol, Token, PVarDef};
pub enum Statement {
Let(Node<VarDef>, Node<Expr>),
Return(Node<Expr>),
Expr(Node<Expr>),
pub enum PStatement {
Let(Node<PVarDef>, Node<PExpr>),
Return(Node<PExpr>),
Expr(Node<PExpr>),
}
impl Parsable for Statement {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserOutput) -> ParseResult<Self> {
let next = cursor.expect_peek()?;
impl Parsable for PStatement {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let next = ctx.expect_peek()?;
match next.token {
Token::Keyword(Keyword::Let) => {
cursor.next();
let def = Node::parse(cursor, errors)?;
cursor.expect_sym(Symbol::Equals)?;
Node::parse(cursor, errors).map(|expr| Self::Let(def, expr))
ctx.next();
let def = ctx.parse()?;
ctx.expect_sym(Symbol::Equals)?;
ctx.parse().map(|expr| Self::Let(def, expr))
}
Token::Keyword(Keyword::Return) => {
cursor.next();
Node::parse(cursor, errors).map(Self::Return)
ctx.next();
ctx.parse().map(Self::Return)
}
_ => Node::parse(cursor, errors).map(Self::Expr),
_ => ctx.parse().map(Self::Expr),
}
}
}
impl Debug for Statement {
impl std::fmt::Debug for PStatement {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Statement::Let(n, e) => {
PStatement::Let(n, e) => {
f.write_str("let ")?;
n.fmt(f)?;
f.write_str(" = ")?;
e.fmt(f)?;
f.write_char(';')?;
}
Statement::Return(e) => {
PStatement::Return(e) => {
f.write_str("return ")?;
e.fmt(f)?;
f.write_char(';')?;
}
Statement::Expr(e) => {
PStatement::Expr(e) => {
e.fmt(f)?;
f.write_char(';')?;
}
}
Ok(())

View File

@@ -1,45 +1,45 @@
use std::fmt::Debug;
use super::{
util::parse_list, Ident, Keyword, Node, Parsable, ParseResult, ParserMsg, ParserOutput,
Symbol, TokenCursor, Type, VarDef,
util::parse_list, PIdent, Keyword, Node, Parsable, ParseResult, ParserCtx, ParserMsg, Symbol,
PType, PVarDef,
};
#[derive(Debug)]
pub struct Struct {
pub name: Node<Ident>,
pub fields: StructFields,
pub struct PStruct {
pub name: Node<PIdent>,
pub fields: PStructFields,
}
#[derive(Debug)]
pub enum StructFields {
Named(Vec<Node<VarDef>>),
Tuple(Vec<Node<Type>>),
pub enum PStructFields {
Named(Vec<Node<PVarDef>>),
Tuple(Vec<Node<PType>>),
None,
}
impl Parsable for Struct {
fn parse(cursor: &mut TokenCursor, errors: &mut ParserOutput) -> ParseResult<Self> {
cursor.expect_kw(Keyword::Struct)?;
let name = Node::parse(cursor, errors)?;
let next = cursor.expect_peek()?;
impl Parsable for PStruct {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
ctx.expect_kw(Keyword::Struct)?;
let name = ctx.parse()?;
let next = ctx.expect_peek()?;
let fields = if next.is_symbol(Symbol::Semicolon) {
cursor.next();
StructFields::None
ctx.next();
PStructFields::None
} else if next.is_symbol(Symbol::OpenCurly) {
cursor.next();
StructFields::Named(parse_list(cursor, errors, Symbol::CloseCurly)?)
ctx.next();
PStructFields::Named(parse_list(ctx, Symbol::CloseCurly)?)
} else if next.is_symbol(Symbol::OpenParen) {
cursor.next();
StructFields::Tuple(parse_list(cursor, errors, Symbol::CloseParen)?)
ctx.next();
PStructFields::Tuple(parse_list(ctx, Symbol::CloseParen)?)
} else {
errors.err(ParserMsg::unexpected_token(next, "`;`, `(`, or `{`"));
return ParseResult::Recover(Struct {
let msg = ParserMsg::unexpected_token(next, "`;`, `(`, or `{`");
ctx.err(msg);
return ParseResult::Recover(PStruct {
name,
fields: StructFields::None,
fields: PStructFields::None,
});
};
ParseResult::Ok(Struct { name, fields })
ParseResult::Ok(PStruct { name, fields })
}
}

View File

@@ -1,36 +1,39 @@
use super::{util::{parse_list, parse_list_nosep}, Function, FunctionHeader, Ident, Keyword, Node, Parsable, Symbol, Type};
use super::{
util::{parse_list, parse_list_nosep},
PFunction, PFunctionHeader, PIdent, Keyword, Node, Parsable, ParserCtx, Symbol, PType,
};
#[derive(Debug)]
pub struct Trait {
pub name: Node<Ident>,
pub fns: Vec<Node<FunctionHeader>>
pub struct PTrait {
pub name: Node<PIdent>,
pub fns: Vec<Node<PFunctionHeader>>,
}
#[derive(Debug)]
pub struct Impl {
pub trait_: Node<Type>,
pub for_: Node<Type>,
pub fns: Vec<Node<Function>>
pub struct PImpl {
pub trait_: Node<PType>,
pub for_: Node<PType>,
pub fns: Vec<Node<PFunction>>,
}
impl Parsable for Trait {
fn parse(cursor: &mut super::TokenCursor, errors: &mut super::ParserOutput) -> super::ParseResult<Self> {
cursor.expect_kw(Keyword::Trait)?;
let name = Node::parse(cursor, errors)?;
cursor.expect_sym(Symbol::OpenCurly)?;
let fns = parse_list(cursor, errors, Symbol::CloseCurly)?;
super::ParseResult::Ok(Self {name, fns})
impl Parsable for PTrait {
fn parse(ctx: &mut ParserCtx) -> super::ParseResult<Self> {
ctx.expect_kw(Keyword::Trait)?;
let name = ctx.parse()?;
ctx.expect_sym(Symbol::OpenCurly)?;
let fns = parse_list(ctx, Symbol::CloseCurly)?;
super::ParseResult::Ok(Self { name, fns })
}
}
impl Parsable for Impl {
fn parse(cursor: &mut super::TokenCursor, errors: &mut super::ParserOutput) -> super::ParseResult<Self> {
cursor.expect_kw(Keyword::Impl)?;
let trait_ = Node::parse(cursor, errors)?;
cursor.expect_kw(Keyword::For)?;
let for_ = Node::parse(cursor, errors)?;
cursor.expect_sym(Symbol::OpenCurly)?;
let fns = parse_list_nosep(cursor, errors, Symbol::CloseCurly)?;
super::ParseResult::Ok(Self {trait_, for_, fns})
impl Parsable for PImpl {
fn parse(ctx: &mut ParserCtx) -> super::ParseResult<Self> {
ctx.expect_kw(Keyword::Impl)?;
let trait_ = ctx.parse()?;
ctx.expect_kw(Keyword::For)?;
let for_ = ctx.parse()?;
ctx.expect_sym(Symbol::OpenCurly)?;
let fns = parse_list_nosep(ctx, Symbol::CloseCurly)?;
super::ParseResult::Ok(Self { trait_, for_, fns })
}
}

View File

@@ -1,13 +1,13 @@
use std::fmt::Debug;
use super::{util::parse_list, Node, Parsable, ParseResult, ParserMsg, Symbol, Token};
use super::{util::parse_list, Node, Parsable, ParseResult, ParserCtx, ParserMsg, Symbol, Token};
pub struct Type {
pub struct PType {
pub name: String,
pub args: Vec<Node<Type>>,
pub args: Vec<Node<PType>>,
}
impl Type {
impl PType {
pub fn unit() -> Self {
Self {
name: "()".to_string(),
@@ -16,15 +16,12 @@ impl Type {
}
}
impl Parsable for Type {
fn parse(
cursor: &mut super::TokenCursor,
errors: &mut super::ParserOutput,
) -> ParseResult<Self> {
let next = cursor.expect_peek()?;
impl Parsable for PType {
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
let next = ctx.expect_peek()?;
let res = if next.is_symbol(Symbol::Ampersand) {
cursor.next();
let arg = Node::parse(cursor, errors)?;
ctx.next();
let arg = ctx.parse()?;
Self {
name: "&".to_string(),
args: vec![arg],
@@ -34,12 +31,12 @@ impl Parsable for Type {
return ParseResult::Err(ParserMsg::unexpected_token(next, "a type identifier"));
};
let n = name.to_string();
cursor.next();
ctx.next();
let mut args = Vec::new();
if let Some(next) = cursor.peek() {
if let Some(next) = ctx.peek() {
if next.is_symbol(Symbol::OpenAngle) {
cursor.next();
args = parse_list(cursor, errors, Symbol::CloseAngle)?;
ctx.next();
args = parse_list(ctx, Symbol::CloseAngle)?;
}
}
Self { name: n, args }
@@ -48,7 +45,7 @@ impl Parsable for Type {
}
}
impl Debug for Type {
impl Debug for PType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)?;
if self.name == "&" {

View File

@@ -1,57 +1,54 @@
use super::{Node, Parsable, ParserMsg, ParserOutput, Symbol, TokenCursor};
use super::{Node, Parsable, ParserCtx, ParserMsg, Symbol};
pub fn parse_list_sep<T: Parsable>(
cursor: &mut TokenCursor,
errors: &mut ParserOutput,
ctx: &mut ParserCtx,
sep: Symbol,
end: Symbol,
) -> Result<Vec<Node<T>>, ParserMsg> {
let mut vals = Vec::new();
loop {
let next = cursor.expect_peek()?;
let next = ctx.expect_peek()?;
if next.is_symbol(end) {
break;
}
let res = Node::parse(cursor, errors);
let res = ctx.parse();
vals.push(res.node);
if res.recover {
cursor.seek_syms(&[end, sep]);
ctx.seek_syms(&[end, sep]);
}
let next = cursor.expect_peek()?;
let next = ctx.expect_peek()?;
if !next.is_symbol(sep) {
break;
}
cursor.next();
ctx.next();
}
cursor.expect_sym(end)?;
ctx.expect_sym(end)?;
Ok(vals)
}
pub fn parse_list<T: Parsable>(
cursor: &mut TokenCursor,
errors: &mut ParserOutput,
ctx: &mut ParserCtx,
end: Symbol,
) -> Result<Vec<Node<T>>, ParserMsg> {
parse_list_sep(cursor, errors, Symbol::Comma, end)
parse_list_sep(ctx, Symbol::Comma, end)
}
pub fn parse_list_nosep<T: Parsable>(
cursor: &mut TokenCursor,
errors: &mut ParserOutput,
ctx: &mut ParserCtx,
end: Symbol,
) -> Result<Vec<Node<T>>, ParserMsg> {
let mut vals = Vec::new();
loop {
let next = cursor.expect_peek()?;
let next = ctx.expect_peek()?;
if next.is_symbol(end) {
break;
}
let res = Node::parse(cursor, errors);
let res = ctx.parse();
vals.push(res.node);
if res.recover {
cursor.seek_sym(end);
ctx.seek_sym(end);
}
}
cursor.expect_sym(end)?;
ctx.expect_sym(end)?;
Ok(vals)
}