Amo/src/parser/program.rs

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()
}
}