a ton of stuff idk more ir work
This commit is contained in:
23
src/parser/v3/nodes/asm_block.rs
Normal file
23
src/parser/v3/nodes/asm_block.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
use crate::compiler::riscv64::AsmInstruction;
|
||||
|
||||
use super::{Parsable, ParseResult, Symbol};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AsmBlock {
|
||||
pub instructions: Vec<AsmInstruction>,
|
||||
}
|
||||
|
||||
impl Parsable for AsmBlock {
|
||||
fn parse(
|
||||
cursor: &mut super::TokenCursor,
|
||||
output: &mut super::ParserOutput,
|
||||
) -> ParseResult<Self> {
|
||||
cursor.expect_sym(Symbol::OpenCurly)?;
|
||||
let mut instructions = Vec::new();
|
||||
while !cursor.expect_peek()?.is_symbol(Symbol::CloseCurly) {
|
||||
instructions.push(AsmInstruction::parse(cursor, output)?);
|
||||
}
|
||||
cursor.expect_sym(Symbol::CloseCurly)?;
|
||||
ParseResult::Ok(Self { instructions })
|
||||
}
|
||||
}
|
||||
53
src/parser/v3/nodes/asm_fn.rs
Normal file
53
src/parser/v3/nodes/asm_fn.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use crate::compiler::riscv64::{AsmInstruction, Reg};
|
||||
|
||||
use super::{
|
||||
util::parse_list, AsmBlock, Ident, Keyword, Node, Parsable, ParseResult, SelfVar, Symbol,
|
||||
};
|
||||
|
||||
#[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 })
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,31 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
|
||||
use super::{
|
||||
token::Symbol, Node, NodeParsable, Parsable, ParseResult, ParserError,
|
||||
ParserErrors, Statement, TokenCursor,
|
||||
token::Symbol, Node, NodeParsable, Parsable, ParseResult, ParserMsg, ParserOutput, Statement,
|
||||
TokenCursor,
|
||||
};
|
||||
use crate::util::Padder;
|
||||
|
||||
pub struct Body {
|
||||
pub struct Block {
|
||||
pub statements: Vec<Node<Statement>>,
|
||||
pub result: Option<Node<Box<Statement>>>,
|
||||
}
|
||||
|
||||
impl Parsable for Body {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
|
||||
impl Parsable for Block {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserOutput) -> 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();
|
||||
return ParseResult::Ok(Self { statements });
|
||||
return ParseResult::Ok(Self { statements, result });
|
||||
}
|
||||
let mut expect_semi = false;
|
||||
let mut recover = false;
|
||||
loop {
|
||||
let Some(next) = cursor.peek() else {
|
||||
recover = true;
|
||||
errors.add(ParserError::unexpected_end());
|
||||
errors.err(ParserMsg::unexpected_end());
|
||||
break;
|
||||
};
|
||||
if next.is_symbol(Symbol::CloseCurly) {
|
||||
@@ -35,7 +37,7 @@ impl Parsable for Body {
|
||||
expect_semi = false;
|
||||
continue;
|
||||
} else if expect_semi {
|
||||
errors.add(ParserError {
|
||||
errors.err(ParserMsg {
|
||||
msg: "expected ';'".to_string(),
|
||||
spans: vec![cursor.next_pos().char_span()],
|
||||
});
|
||||
@@ -51,11 +53,16 @@ impl Parsable for Body {
|
||||
}
|
||||
}
|
||||
}
|
||||
ParseResult::from_recover(Self { statements }, recover)
|
||||
if expect_semi {
|
||||
if let Some(s) = statements.pop() {
|
||||
result = Some(s.bx());
|
||||
}
|
||||
}
|
||||
ParseResult::from_recover(Self { statements, result }, recover)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Body {
|
||||
impl Debug for Block {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if self.statements.first().is_some() {
|
||||
f.write_str("{\n ")?;
|
||||
82
src/parser/v3/nodes/def.rs
Normal file
82
src/parser/v3/nodes/def.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use super::{Ident, MaybeParsable, Node, Parsable, ParseResult, ParserMsg, Symbol, Token, Type};
|
||||
|
||||
pub struct VarDef {
|
||||
pub name: Node<Ident>,
|
||||
pub ty: Option<Node<Type>>,
|
||||
}
|
||||
|
||||
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) })
|
||||
} else {
|
||||
ParseResult::Ok(Self { name, ty: None })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SelfVar {
|
||||
pub ty: SelfType,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum SelfType {
|
||||
Ref,
|
||||
Take,
|
||||
}
|
||||
|
||||
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() {
|
||||
let mut ty = SelfType::Take;
|
||||
if next.is_symbol(Symbol::Ampersand) {
|
||||
cursor.next();
|
||||
ty = SelfType::Ref;
|
||||
next = cursor.expect_peek()?;
|
||||
}
|
||||
if let Token::Word(name) = &next.token {
|
||||
if name == "self" {
|
||||
cursor.next();
|
||||
return Ok(Some(Self { ty }));
|
||||
}
|
||||
}
|
||||
if ty != SelfType::Take {
|
||||
return Err(ParserMsg::unexpected_token(next, "self"));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for VarDef {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for SelfVar {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self.ty {
|
||||
SelfType::Ref => "&self",
|
||||
SelfType::Take => "self",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
|
||||
use super::{
|
||||
BinaryOperator, Body, Ident, Literal, Node, NodeParsable, Parsable, ParseResult, ParserError,
|
||||
ParserErrors, Symbol, TokenCursor, UnaryOperator,
|
||||
op::{BinaryOp, UnaryOp},
|
||||
util::parse_list,
|
||||
AsmBlock, Block, Ident, Keyword, Literal, Node, NodeParsable, Parsable, ParseResult, ParserMsg,
|
||||
ParserOutput, Symbol, TokenCursor,
|
||||
};
|
||||
|
||||
type BoxNode = Node<Box<Expr>>;
|
||||
@@ -10,15 +12,16 @@ type BoxNode = Node<Box<Expr>>;
|
||||
pub enum Expr {
|
||||
Lit(Node<Literal>),
|
||||
Ident(Node<Ident>),
|
||||
BinaryOp(BinaryOperator, BoxNode, BoxNode),
|
||||
UnaryOp(UnaryOperator, BoxNode),
|
||||
Block(Node<Body>),
|
||||
BinaryOp(BinaryOp, BoxNode, BoxNode),
|
||||
UnaryOp(UnaryOp, BoxNode),
|
||||
Block(Node<Block>),
|
||||
Call(BoxNode, Vec<Node<Expr>>),
|
||||
Group(BoxNode),
|
||||
AsmBlock(Node<AsmBlock>),
|
||||
}
|
||||
|
||||
impl Parsable for Expr {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
|
||||
fn parse(cursor: &mut TokenCursor, output: &mut ParserOutput) -> ParseResult<Self> {
|
||||
let start = cursor.next_pos();
|
||||
let next = cursor.expect_peek()?;
|
||||
let mut e1 = if next.is_symbol(Symbol::OpenParen) {
|
||||
@@ -30,17 +33,20 @@ impl Parsable for Expr {
|
||||
cursor.next_pos().char_span(),
|
||||
)));
|
||||
}
|
||||
let res = Node::parse(cursor, errors);
|
||||
let res = Node::parse(cursor, output);
|
||||
if res.recover {
|
||||
cursor.seek_sym(Symbol::CloseParen);
|
||||
}
|
||||
cursor.expect_sym(Symbol::CloseParen)?;
|
||||
Self::Group(res.node.bx())
|
||||
} else if next.is_symbol(Symbol::OpenCurly) {
|
||||
Self::Block(Body::parse_node(cursor, errors)?)
|
||||
} else if let Some(op) = UnaryOperator::from_token(next) {
|
||||
Self::Block(Block::parse_node(cursor, output)?)
|
||||
} else if next.is_keyword(Keyword::Asm) {
|
||||
cursor.next();
|
||||
return Node::parse(cursor, errors).map(|n| {
|
||||
Self::AsmBlock(Node::parse(cursor, output)?)
|
||||
} else if let Some(op) = UnaryOp::from_token(next) {
|
||||
cursor.next();
|
||||
return Node::parse(cursor, output).map(|n| {
|
||||
let n = n.bx();
|
||||
if let Some(box Self::BinaryOp(op2, n1, n2)) = n.inner {
|
||||
let span = start.to(n1.span.end);
|
||||
@@ -49,15 +55,15 @@ impl Parsable for Expr {
|
||||
Self::UnaryOp(op, n)
|
||||
}
|
||||
});
|
||||
} else if let Some(val) = Node::maybe_parse(cursor, errors) {
|
||||
} else if let Some(val) = Node::maybe_parse(cursor, output) {
|
||||
Self::Lit(val)
|
||||
} else {
|
||||
let res = Node::parse(cursor, &mut ParserErrors::new());
|
||||
let res = Node::parse(cursor, &mut ParserOutput::new());
|
||||
if res.node.is_some() {
|
||||
Self::Ident(res.node)
|
||||
} else {
|
||||
let next = cursor.expect_peek()?;
|
||||
return ParseResult::Err(ParserError::unexpected_token(next, "an expression"));
|
||||
return ParseResult::Err(ParserMsg::unexpected_token(next, "an expression"));
|
||||
}
|
||||
};
|
||||
let Some(mut next) = cursor.peek() else {
|
||||
@@ -65,24 +71,7 @@ impl Parsable for Expr {
|
||||
};
|
||||
while next.is_symbol(Symbol::OpenParen) {
|
||||
cursor.next();
|
||||
let mut args = Vec::new();
|
||||
loop {
|
||||
let next = cursor.expect_peek()?;
|
||||
if next.is_symbol(Symbol::CloseParen) {
|
||||
break;
|
||||
}
|
||||
let res = Node::<Expr>::parse(cursor, errors);
|
||||
args.push(res.node);
|
||||
if res.recover {
|
||||
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 args = parse_list(cursor, output, Symbol::CloseParen)?;
|
||||
let end = cursor.prev_end();
|
||||
e1 = Self::Call(Node::new(Box::new(e1), start.to(end)), args);
|
||||
let Some(next2) = cursor.peek() else {
|
||||
@@ -92,10 +81,10 @@ impl Parsable for Expr {
|
||||
}
|
||||
let end = cursor.prev_end();
|
||||
let mut recover = false;
|
||||
let res = if let Some(mut op) = BinaryOperator::from_token(&next.token) {
|
||||
let res = if let Some(mut op) = BinaryOp::from_token(&next.token) {
|
||||
cursor.next();
|
||||
let mut n1 = Node::new(e1, start.to(end)).bx();
|
||||
let res = Node::parse(cursor, errors);
|
||||
let res = Node::parse(cursor, output);
|
||||
let mut n2 = res.node.bx();
|
||||
recover = res.recover;
|
||||
if let Some(box Self::BinaryOp(op2, _, _)) = n2.as_ref() {
|
||||
@@ -150,6 +139,7 @@ impl Debug for Expr {
|
||||
write!(f, "{:?})", *e)?;
|
||||
}
|
||||
Expr::Group(inner) => inner.fmt(f)?,
|
||||
Expr::AsmBlock(inner) => inner.fmt(f)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,28 +1,90 @@
|
||||
use super::{Body, Ident, Keyword, Node, Parsable, ParseResult, ParserErrors, Symbol, TokenCursor};
|
||||
use super::{
|
||||
util::parse_list, Block, Ident, Keyword, Node, Parsable, ParseResult, ParserOutput, SelfVar,
|
||||
Symbol, TokenCursor, Type, VarDef,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub struct Function {
|
||||
pub struct FunctionHeader {
|
||||
pub name: Node<Ident>,
|
||||
pub body: Node<Body>,
|
||||
pub sel: Option<Node<SelfVar>>,
|
||||
pub args: Vec<Node<VarDef>>,
|
||||
pub ret: Option<Node<Type>>,
|
||||
}
|
||||
|
||||
impl Parsable for Function {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
|
||||
pub struct Function {
|
||||
pub header: Node<FunctionHeader>,
|
||||
pub body: Node<Block>,
|
||||
}
|
||||
|
||||
impl Parsable for FunctionHeader {
|
||||
fn parse(cursor: &mut TokenCursor, output: &mut ParserOutput) -> ParseResult<Self> {
|
||||
cursor.expect_kw(Keyword::Fn)?;
|
||||
let name = Node::parse(cursor, errors)?;
|
||||
let name = Node::parse(cursor, output)?;
|
||||
cursor.expect_sym(Symbol::OpenParen)?;
|
||||
cursor.expect_sym(Symbol::CloseParen)?;
|
||||
Node::parse(cursor, errors).map(|body| Self { name, body })
|
||||
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)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
ParseResult::Ok(Self {
|
||||
name,
|
||||
args,
|
||||
sel,
|
||||
ret,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Function {
|
||||
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)?;
|
||||
ParseResult::Ok(Self { header, body })
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FunctionHeader {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("fn ")?;
|
||||
self.name.fmt(f)?;
|
||||
f.write_str("() ")?;
|
||||
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)?;
|
||||
}
|
||||
for arg in self.args.iter().skip(1) {
|
||||
f.write_str(", ")?;
|
||||
arg.fmt(f)?;
|
||||
}
|
||||
f.write_str(")")?;
|
||||
if let Some(ret) = &self.ret {
|
||||
write!(f, " -> {:?}", ret)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl Debug for Function {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.header.fmt(f)?;
|
||||
f.write_str(" ")?;
|
||||
self.body.fmt(f)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::fmt::Debug;
|
||||
use super::{Parsable, ParseResult, ParserError, Token};
|
||||
use super::{Parsable, ParseResult, ParserMsg, Token};
|
||||
|
||||
pub struct Ident(String);
|
||||
|
||||
@@ -10,10 +10,10 @@ impl Ident {
|
||||
}
|
||||
|
||||
impl Parsable for Ident {
|
||||
fn parse(cursor: &mut super::TokenCursor, errors: &mut super::ParserErrors) -> ParseResult<Self> {
|
||||
fn parse(cursor: &mut super::TokenCursor, errors: &mut super::ParserOutput) -> ParseResult<Self> {
|
||||
let next = cursor.expect_peek()?;
|
||||
let Token::Ident(name) = &next.token else {
|
||||
return ParseResult::Err(ParserError::unexpected_token(next, "an identifier"));
|
||||
let Token::Word(name) = &next.token else {
|
||||
return ParseResult::Err(ParserMsg::unexpected_token(next, "an identifier"));
|
||||
};
|
||||
let name = name.to_string();
|
||||
cursor.next();
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use super::{
|
||||
CharCursor, MaybeParsable, ParserError, ParserErrors, Symbol, Token, TokenCursor,
|
||||
};
|
||||
use super::{CharCursor, MaybeParsable, ParserMsg, ParserOutput, Symbol, Token, TokenCursor};
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
@@ -21,49 +19,72 @@ pub struct Number {
|
||||
impl MaybeParsable for Literal {
|
||||
fn maybe_parse(
|
||||
cursor: &mut TokenCursor,
|
||||
_: &mut ParserErrors,
|
||||
) -> Result<Option<Self>, ParserError> {
|
||||
_: &mut ParserOutput,
|
||||
) -> Result<Option<Self>, ParserMsg> {
|
||||
let inst = cursor.expect_peek()?;
|
||||
let mut res = match &inst.token {
|
||||
Ok(Some(match &inst.token {
|
||||
Token::Symbol(Symbol::SingleQuote) => {
|
||||
let chars = cursor.chars();
|
||||
let c = chars.expect_next()?;
|
||||
chars.expect('\'')?;
|
||||
cursor.next();
|
||||
Self::Char(c)
|
||||
}
|
||||
Token::Symbol(Symbol::DoubleQuote) => Self::String(string_from(cursor.chars())?),
|
||||
Token::Ident(text) => {
|
||||
Token::Symbol(Symbol::DoubleQuote) => {
|
||||
let res = Self::String(string_from(cursor.chars())?);
|
||||
cursor.next();
|
||||
res
|
||||
}
|
||||
Token::Word(text) => {
|
||||
let first = text.chars().next().unwrap();
|
||||
if first.is_ascii_digit() {
|
||||
Self::Number(Number {
|
||||
whole: text.to_string(),
|
||||
decimal: None,
|
||||
ty: None,
|
||||
})
|
||||
} else {
|
||||
if !first.is_ascii_digit() {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
_ => return Ok(None),
|
||||
};
|
||||
cursor.next();
|
||||
if let (Some(next), Self::Number(num)) = (cursor.peek(), &mut res) {
|
||||
if next.token.is_symbol(Symbol::Dot) {
|
||||
let (whole, ty) = parse_whole_num(text);
|
||||
let mut num = Number {
|
||||
whole,
|
||||
decimal: None,
|
||||
ty,
|
||||
};
|
||||
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();
|
||||
if num.ty.is_none() && cursor.peek().is_some_and(|i| i.is_symbol(Symbol::Dot)) {
|
||||
cursor.next();
|
||||
if let Some(next) = cursor.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Number(num)
|
||||
}
|
||||
}
|
||||
Ok(Some(res))
|
||||
_ => return Ok(None),
|
||||
}))
|
||||
}
|
||||
}
|
||||
pub fn string_from(cursor: &mut CharCursor) -> Result<String, ParserError> {
|
||||
|
||||
pub fn parse_whole_num(text: &str) -> (String, Option<String>) {
|
||||
let mut whole = String::new();
|
||||
let mut ty = String::new();
|
||||
for c in text.chars() {
|
||||
if ty.is_empty() {
|
||||
if c.is_ascii_digit() {
|
||||
whole.push(c);
|
||||
} else if c != '_' {
|
||||
ty.push(c);
|
||||
}
|
||||
} else {
|
||||
ty.push(c);
|
||||
}
|
||||
}
|
||||
(whole, if ty.is_empty() { None } else { Some(ty) })
|
||||
}
|
||||
|
||||
pub fn string_from(cursor: &mut CharCursor) -> Result<String, ParserMsg> {
|
||||
let mut str = String::new();
|
||||
loop {
|
||||
let c = cursor.expect_next()?;
|
||||
@@ -107,7 +128,7 @@ impl Debug for Number {
|
||||
write!(f, ".{}", d)?;
|
||||
}
|
||||
if let Some(ty) = &self.ty {
|
||||
write!(f, "T{}", ty)?;
|
||||
write!(f, "_{}", ty)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
mod body;
|
||||
mod block;
|
||||
mod expr;
|
||||
mod func;
|
||||
mod module;
|
||||
@@ -6,14 +6,28 @@ mod op;
|
||||
mod statement;
|
||||
mod lit;
|
||||
mod ident;
|
||||
mod ty;
|
||||
mod def;
|
||||
mod struc;
|
||||
mod util;
|
||||
mod trai;
|
||||
mod asm_fn;
|
||||
mod asm_block;
|
||||
|
||||
pub use body::*;
|
||||
pub use block::*;
|
||||
pub use expr::*;
|
||||
pub use func::*;
|
||||
pub use module::*;
|
||||
pub use op::*;
|
||||
pub use statement::*;
|
||||
pub use lit::*;
|
||||
pub use ident::*;
|
||||
pub use ty::*;
|
||||
pub use def::*;
|
||||
pub use struc::*;
|
||||
pub use trai::*;
|
||||
pub use op::*;
|
||||
pub use asm_fn::*;
|
||||
pub use asm_block::*;
|
||||
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -1,35 +1,113 @@
|
||||
use super::{
|
||||
Function, Keyword, Node, Parsable, ParseResult, ParserError, ParserErrors, TokenCursor,
|
||||
AsmFunction, Function, Impl, Keyword, Node, Parsable, ParseResult, ParserMsg, ParserOutput,
|
||||
Struct, Symbol, Token, TokenCursor, Trait,
|
||||
};
|
||||
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>>,
|
||||
}
|
||||
|
||||
impl Parsable for Module {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserOutput) -> 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 {
|
||||
return ParseResult::Ok(Self { functions });
|
||||
break;
|
||||
};
|
||||
if next.is_keyword(Keyword::Fn) {
|
||||
let res = Node::parse(cursor, errors);
|
||||
functions.push(res.node);
|
||||
if res.recover {
|
||||
return ParseResult::Recover(Self { functions });
|
||||
if let Token::Keyword(kw) = next.token {
|
||||
match kw {
|
||||
Keyword::Fn => {
|
||||
let res = Node::parse(cursor, errors);
|
||||
functions.push(res.node);
|
||||
if res.recover {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Keyword::Struct => {
|
||||
let res = Node::parse(cursor, errors);
|
||||
structs.push(res.node);
|
||||
if res.recover {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Keyword::Trait => {
|
||||
let res = Node::parse(cursor, errors);
|
||||
traits.push(res.node);
|
||||
if res.recover {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Keyword::Impl => {
|
||||
let res = Node::parse(cursor, errors);
|
||||
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();
|
||||
}
|
||||
}
|
||||
} else if next.is_symbol(Symbol::Semicolon) {
|
||||
errors.hint(ParserMsg::from_instances(
|
||||
&[next],
|
||||
"unneeded semicolon".to_string(),
|
||||
));
|
||||
cursor.next();
|
||||
} else {
|
||||
errors.add(ParserError::unexpected_token(next, "fn"));
|
||||
errors.err(ParserMsg::unexpected_token(next, "a definition"));
|
||||
cursor.next();
|
||||
}
|
||||
}
|
||||
ParseResult::Ok(Self {
|
||||
functions,
|
||||
structs,
|
||||
traits,
|
||||
impls,
|
||||
asm_fns,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Module {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.functions.fmt(f)
|
||||
for st in &self.structs {
|
||||
st.fmt(f)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
for t in &self.traits {
|
||||
t.fmt(f)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
for t in &self.impls {
|
||||
t.fmt(f)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
for func in &self.functions {
|
||||
func.fmt(f)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
for func in &self.asm_fns {
|
||||
func.fmt(f)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::{Symbol, Token};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum BinaryOperator {
|
||||
pub enum BinaryOp {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
@@ -12,7 +12,7 @@ pub enum BinaryOperator {
|
||||
Assign,
|
||||
}
|
||||
|
||||
impl BinaryOperator {
|
||||
impl BinaryOp {
|
||||
pub fn presedence(&self) -> u32 {
|
||||
match self {
|
||||
Self::Assign => 0,
|
||||
@@ -37,6 +37,39 @@ impl BinaryOperator {
|
||||
Self::Assign => "=",
|
||||
}
|
||||
}
|
||||
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 fn traitt(&self) -> &str {
|
||||
match self {
|
||||
Self::Add => "Add",
|
||||
Self::Sub => "Sub",
|
||||
Self::Mul => "Mul",
|
||||
Self::Div => "Div",
|
||||
Self::LessThan => "LessThan",
|
||||
Self::GreaterThan => "GreaterThan",
|
||||
Self::Access => "Access",
|
||||
Self::Assign => "Assign",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum UnaryOp {
|
||||
Not,
|
||||
Ref,
|
||||
Deref,
|
||||
}
|
||||
|
||||
impl BinaryOp {
|
||||
pub fn from_token(token: &Token) -> Option<Self> {
|
||||
let Token::Symbol(symbol) = token else {
|
||||
return None;
|
||||
@@ -55,30 +88,14 @@ impl BinaryOperator {
|
||||
}
|
||||
})
|
||||
}
|
||||
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 {
|
||||
impl UnaryOp {
|
||||
pub fn str(&self) -> &str {
|
||||
match self {
|
||||
Self::Not => "!",
|
||||
Self::Ref => "&",
|
||||
Self::Deref => "*",
|
||||
}
|
||||
}
|
||||
pub fn from_token(token: &Token) -> Option<Self> {
|
||||
@@ -88,6 +105,7 @@ impl UnaryOperator {
|
||||
Some(match symbol {
|
||||
Symbol::Ampersand => Self::Ref,
|
||||
Symbol::Bang => Self::Not,
|
||||
Symbol::Asterisk => Self::Deref,
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
use super::{
|
||||
Expr, Ident, Keyword, Node, Parsable, ParseResult, ParserErrors, Symbol, Token, TokenCursor,
|
||||
Expr, Keyword, Node, Parsable, ParseResult, ParserOutput, Symbol, Token, TokenCursor, VarDef,
|
||||
};
|
||||
use std::fmt::{Debug, Write};
|
||||
|
||||
pub enum Statement {
|
||||
Let(Node<Ident>, Node<Expr>),
|
||||
Let(Node<VarDef>, Node<Expr>),
|
||||
Return(Node<Expr>),
|
||||
Expr(Node<Expr>),
|
||||
}
|
||||
|
||||
impl Parsable for Statement {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserOutput) -> ParseResult<Self> {
|
||||
let next = cursor.expect_peek()?;
|
||||
match next.token {
|
||||
Token::Keyword(Keyword::Let) => {
|
||||
cursor.next();
|
||||
let name = Node::parse(cursor, errors)?;
|
||||
let def = Node::parse(cursor, errors)?;
|
||||
cursor.expect_sym(Symbol::Equals)?;
|
||||
Node::parse(cursor, errors).map(|expr| Self::Let(name, expr))
|
||||
Node::parse(cursor, errors).map(|expr| Self::Let(def, expr))
|
||||
}
|
||||
Token::Keyword(Keyword::Return) => {
|
||||
cursor.next();
|
||||
|
||||
45
src/parser/v3/nodes/struc.rs
Normal file
45
src/parser/v3/nodes/struc.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use super::{
|
||||
util::parse_list, Ident, Keyword, Node, Parsable, ParseResult, ParserMsg, ParserOutput,
|
||||
Symbol, TokenCursor, Type, VarDef,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Struct {
|
||||
pub name: Node<Ident>,
|
||||
pub fields: StructFields,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum StructFields {
|
||||
Named(Vec<Node<VarDef>>),
|
||||
Tuple(Vec<Node<Type>>),
|
||||
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()?;
|
||||
let fields = if next.is_symbol(Symbol::Semicolon) {
|
||||
cursor.next();
|
||||
StructFields::None
|
||||
} else if next.is_symbol(Symbol::OpenCurly) {
|
||||
cursor.next();
|
||||
StructFields::Named(parse_list(cursor, errors, Symbol::CloseCurly)?)
|
||||
} else if next.is_symbol(Symbol::OpenParen) {
|
||||
cursor.next();
|
||||
StructFields::Tuple(parse_list(cursor, errors, Symbol::CloseParen)?)
|
||||
} else {
|
||||
errors.err(ParserMsg::unexpected_token(next, "`;`, `(`, or `{`"));
|
||||
return ParseResult::Recover(Struct {
|
||||
name,
|
||||
fields: StructFields::None,
|
||||
});
|
||||
};
|
||||
ParseResult::Ok(Struct { name, fields })
|
||||
}
|
||||
}
|
||||
|
||||
36
src/parser/v3/nodes/trai.rs
Normal file
36
src/parser/v3/nodes/trai.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use super::{util::{parse_list, parse_list_nosep}, Function, FunctionHeader, Ident, Keyword, Node, Parsable, Symbol, Type};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Trait {
|
||||
pub name: Node<Ident>,
|
||||
pub fns: Vec<Node<FunctionHeader>>
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Impl {
|
||||
pub trait_: Node<Type>,
|
||||
pub for_: Node<Type>,
|
||||
pub fns: Vec<Node<Function>>
|
||||
}
|
||||
|
||||
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 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})
|
||||
}
|
||||
}
|
||||
61
src/parser/v3/nodes/ty.rs
Normal file
61
src/parser/v3/nodes/ty.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use super::{util::parse_list, Node, Parsable, ParseResult, ParserMsg, Symbol, Token};
|
||||
|
||||
pub struct Type {
|
||||
pub name: String,
|
||||
pub args: Vec<Node<Type>>,
|
||||
}
|
||||
|
||||
impl Type {
|
||||
pub fn unit() -> Self {
|
||||
Self {
|
||||
name: "()".to_string(),
|
||||
args: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parsable for Type {
|
||||
fn parse(
|
||||
cursor: &mut super::TokenCursor,
|
||||
errors: &mut super::ParserOutput,
|
||||
) -> ParseResult<Self> {
|
||||
let next = cursor.expect_peek()?;
|
||||
let res = if next.is_symbol(Symbol::Ampersand) {
|
||||
cursor.next();
|
||||
let arg = Node::parse(cursor, errors)?;
|
||||
Self {
|
||||
name: "&".to_string(),
|
||||
args: vec![arg],
|
||||
}
|
||||
} else {
|
||||
let Token::Word(name) = &next.token else {
|
||||
return ParseResult::Err(ParserMsg::unexpected_token(next, "a type identifier"));
|
||||
};
|
||||
let n = name.to_string();
|
||||
cursor.next();
|
||||
let mut args = Vec::new();
|
||||
if let Some(next) = cursor.peek() {
|
||||
if next.is_symbol(Symbol::OpenAngle) {
|
||||
cursor.next();
|
||||
args = parse_list(cursor, errors, Symbol::CloseAngle)?;
|
||||
}
|
||||
}
|
||||
Self { name: n, args }
|
||||
};
|
||||
ParseResult::Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Type {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.name)?;
|
||||
if self.name == "&" {
|
||||
write!(f, "{:?}", self.args[0])?;
|
||||
} else if !self.args.is_empty() {
|
||||
write!(f, "<{:?}>", self.args)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
57
src/parser/v3/nodes/util.rs
Normal file
57
src/parser/v3/nodes/util.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use super::{Node, Parsable, ParserMsg, ParserOutput, Symbol, TokenCursor};
|
||||
|
||||
pub fn parse_list_sep<T: Parsable>(
|
||||
cursor: &mut TokenCursor,
|
||||
errors: &mut ParserOutput,
|
||||
sep: Symbol,
|
||||
end: Symbol,
|
||||
) -> Result<Vec<Node<T>>, ParserMsg> {
|
||||
let mut vals = Vec::new();
|
||||
loop {
|
||||
let next = cursor.expect_peek()?;
|
||||
if next.is_symbol(end) {
|
||||
break;
|
||||
}
|
||||
let res = Node::parse(cursor, errors);
|
||||
vals.push(res.node);
|
||||
if res.recover {
|
||||
cursor.seek_syms(&[end, sep]);
|
||||
}
|
||||
let next = cursor.expect_peek()?;
|
||||
if !next.is_symbol(sep) {
|
||||
break;
|
||||
}
|
||||
cursor.next();
|
||||
}
|
||||
cursor.expect_sym(end)?;
|
||||
Ok(vals)
|
||||
}
|
||||
|
||||
pub fn parse_list<T: Parsable>(
|
||||
cursor: &mut TokenCursor,
|
||||
errors: &mut ParserOutput,
|
||||
end: Symbol,
|
||||
) -> Result<Vec<Node<T>>, ParserMsg> {
|
||||
parse_list_sep(cursor, errors, Symbol::Comma, end)
|
||||
}
|
||||
|
||||
pub fn parse_list_nosep<T: Parsable>(
|
||||
cursor: &mut TokenCursor,
|
||||
errors: &mut ParserOutput,
|
||||
end: Symbol,
|
||||
) -> Result<Vec<Node<T>>, ParserMsg> {
|
||||
let mut vals = Vec::new();
|
||||
loop {
|
||||
let next = cursor.expect_peek()?;
|
||||
if next.is_symbol(end) {
|
||||
break;
|
||||
}
|
||||
let res = Node::parse(cursor, errors);
|
||||
vals.push(res.node);
|
||||
if res.recover {
|
||||
cursor.seek_sym(end);
|
||||
}
|
||||
}
|
||||
cursor.expect_sym(end)?;
|
||||
Ok(vals)
|
||||
}
|
||||
Reference in New Issue
Block a user