50 lines
1.5 KiB
Rust
50 lines
1.5 KiB
Rust
use std::mem::{discriminant, Discriminant};
|
|
|
|
use crate::{token::Token, cons, ir::{self, BindingScope, Identifier}};
|
|
|
|
use super::{ParseError, Parsable, WrappedLexer, declaration::Declaration};
|
|
|
|
#[derive(Debug)]
|
|
pub struct Program(pub Vec<Declaration>);
|
|
|
|
impl Parsable for Program {
|
|
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
|
(
|
|
cons(Declaration::expected().0, discriminant(&Token::DeclarationStart)),
|
|
true
|
|
)
|
|
}
|
|
|
|
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
|
parse_program_inner(l, Vec::with_capacity(10)).map(Program)
|
|
}
|
|
}
|
|
|
|
fn parse_program_inner(l: &mut WrappedLexer, acc: Vec<Declaration>) -> Result<Vec<Declaration>, ParseError> {
|
|
if *l.curtok() == Token::DeclarationStart {
|
|
l.monch();
|
|
parse_program_inner(l, acc)
|
|
} else if Declaration::matches(l.curtok()) {
|
|
let acc = cons(acc, Declaration::parse(l)?);
|
|
parse_program_inner(l, acc)
|
|
} else {
|
|
eprintln!("Looking for a declaration but got {:?} at {:?}", *l.curtok(), l.span());
|
|
Ok(acc)
|
|
}
|
|
}
|
|
|
|
impl Program {
|
|
pub fn gen_ir(self) -> ir::Result<Vec<ir::Declaration>> {
|
|
// We need a first pass to generate a list of all of the identifiers
|
|
let root_scope = self.0.iter()
|
|
.enumerate()
|
|
.filter_map(|(i, decl)| decl.get_identifier(&Identifier::ROOT, i as u32))
|
|
.fold(BindingScope::builtins(), |scope, ident| scope.bind_single(ident));
|
|
println!("DEBUG {root_scope:?}");
|
|
self.0.into_iter()
|
|
.enumerate()
|
|
.filter_map(|(i, decl)| decl.gen_ir(&root_scope, i as u32, Identifier::ROOT).transpose())
|
|
.collect()
|
|
}
|
|
}
|