mod declaration;
mod rich_types;
pub mod tokenizer;
pub mod utils;
mod value;
use crate::{
DeclProvider, ParseError, Value,
declaration::{DeclFile, TypeId},
errors::{ImportError, err},
parser::{
declaration::{DeclContext, parse_declarations},
tokenizer::tokenize,
utils::unexpected_token,
value::ValueCtx,
},
};
#[derive(Debug, Clone)]
pub struct ParseOptions {
pub metadata: bool,
pub relative_paths: bool,
}
impl Default for ParseOptions {
fn default() -> Self {
Self { metadata: false, relative_paths: true }
}
}
pub fn parse_declaration_file(
source: &str, name: String, options: &ParseOptions, provider: &dyn DeclProvider,
) -> Result<DeclFile, ParseError> {
let tokens = tokenize(source, &name)?;
let mut ind = 0;
let mut file = DeclFile::new(name);
parse_declarations(&mut file, &tokens, &mut ind, provider, options)?;
if ind != tokens.len() - 1 {
return unexpected_token(&tokens[ind], tokens[ind].pos(), &file.name);
}
if file.items.is_empty() {
return err!(format!("no declaration"), &file.name);
}
Ok(file)
}
struct MiddleProvider<'a> {
provider: &'a dyn DeclProvider,
ctx: &'a DeclContext<'a>,
}
impl DeclProvider for MiddleProvider<'_> {
fn get(&self, id: u64) -> &DeclFile {
if id == self.ctx.file.id { self.ctx.file } else { self.provider.get(id) }
}
fn load<'a>(&'a self, name: &str) -> Result<&'a DeclFile, ImportError> {
self.provider.load(name)
}
}
pub fn parse(
source: &str, options: &ParseOptions, provider: &dyn DeclProvider,
) -> Result<Value, ParseError> {
let tokens = tokenize(source, "root")?;
let mut ind = 0;
let mut root_file = DeclFile::new("root".to_string());
let ctx = parse_declarations(&mut root_file, &tokens, &mut ind, provider, options)?;
let provider = &MiddleProvider { provider, ctx: &ctx };
let ctx = ValueCtx { file: "root", decl: &ctx, provider, options };
let value = value::parse_value(&tokens, &mut ind, &TypeId::ANY, &ctx)?;
if tokens.len() - 1 != ind {
return unexpected_token(&tokens[ind], tokens[ind].pos(), "root");
}
Ok(value)
}