This commit is contained in:
2026-04-10 16:13:45 -04:00
parent bdf08ce52c
commit 29316e6353
16 changed files with 520 additions and 338 deletions
+15 -107
View File
@@ -1,31 +1,23 @@
use crate::{
io::{CompilerMsg, CompilerOutput, Span},
parser::cursor::{Cursor, Lit},
io::{CompilerOutput, Span},
parser::{Cursor, Lit, nodes::*},
};
use std::{marker::PhantomData, ops::Index};
mod expr;
pub use expr::*;
mod id;
mod parse;
pub use id::*;
pub use parse::*;
pub trait Parsable: Sized + Node {
fn parse(ctx: &mut ParseCtx) -> Result<Self, CompilerMsg>;
}
pub struct ParseCtx<'a> {
start: usize,
cursor: Cursor<'a>,
nodes: Nodes,
}
def_nodes!(
def_nodes! {
exprs: Expr,
idents: Ident,
statements: Statement,
blocks: Block,
lits: Lit,
);
}
impl Nodes {
pub fn parse_root(path: &str, output: &mut CompilerOutput) -> Option<(Self, Id<Expr>)> {
pub fn parse_root(path: &str, output: &mut CompilerOutput) -> Option<(Self, Id<Block>)> {
let root_code = match std::fs::read_to_string(path) {
Ok(code) => code,
Err(err) => {
@@ -34,44 +26,15 @@ impl Nodes {
}
};
output.files.push(path.to_string());
let nodes = Self::default();
let mut ctx = ParseCtx {
start: 0,
nodes,
cursor: Cursor::new(&root_code, 0),
};
let root = match ctx.parse::<Expr>() {
let mut ctx = ParseCtx::new(Cursor::new(&root_code, 0));
let root = match ctx.parse() {
Ok(expr) => expr,
Err(msg) => {
output.error(msg);
return None;
}
};
Some((ctx.nodes, root))
}
pub fn format<N: FmtNode>(
&self,
w: &mut impl std::io::Write,
id: Id<N>,
) -> std::io::Result<()> {
self[id].format(w, self)
}
}
impl<N: Node> Index<Id<N>> for Nodes {
type Output = N;
fn index(&self, index: Id<N>) -> &Self::Output {
&N::vec(self).vec[index.id]
}
}
impl<N: Node> Index<&Id<N>> for Nodes {
type Output = N;
fn index(&self, index: &Id<N>) -> &Self::Output {
&N::vec(self).vec[index.id]
Some((ctx.finish(), root))
}
}
@@ -86,10 +49,7 @@ impl<N> NodeVec<N> {
let id = self.vec.len();
self.vec.push(v);
self.spans.push(span);
Id {
id,
_pd: PhantomData,
}
Id::new(id)
}
}
@@ -102,61 +62,13 @@ impl<N> Default for NodeVec<N> {
}
}
pub struct Id<T> {
id: usize,
_pd: PhantomData<T>,
}
impl<T> Clone for Id<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Id<T> {}
pub trait Node: Sized {
fn vec(nodes: &Nodes) -> &NodeVec<Self>;
fn vec_mut(nodes: &mut Nodes) -> &mut NodeVec<Self>;
}
impl ParseCtx<'_> {
pub fn parse<P: Parsable>(&mut self) -> Result<Id<P>, CompilerMsg> {
let old_start = self.start;
self.start = self.cursor.peek_start();
let res = P::parse(self).map(|r| self.push(r));
self.start = old_start;
res
}
pub fn ident(&mut self, s: String) -> Id<Ident> {
let span = self.cursor.span;
self.nodes.idents.add(Ident { inner: s }, span)
}
pub fn lit(&mut self, lit: Lit) -> Id<Lit> {
let span = self.cursor.span;
self.nodes.lits.add(lit, span)
}
pub fn push_adv<N: Node>(&mut self, node: N) -> Id<N> {
let res = self.push(node);
self.cursor.next();
res
}
pub fn push<N: Node>(&mut self, node: N) -> Id<N> {
let end = self.cursor.cur_end();
N::vec_mut(&mut self.nodes).add(
node,
Span {
file: self.cursor.file(),
start: self.start,
end,
},
)
}
}
macro_rules! def_nodes {
($($field:ident: $ty:ident,)*) => {
{$($field:ident: $ty:ident,)*} => {
#[derive(Default)]
pub struct Nodes {
$($field: NodeVec<$ty>,)*
@@ -173,7 +85,3 @@ macro_rules! def_nodes {
};
}
use def_nodes;
pub trait FmtNode: Node {
fn format(&self, w: &mut impl std::io::Write, nodes: &Nodes) -> std::io::Result<()>;
}