pub use ast::{Precision, Profile};
pub use error::{Error, ErrorKind, ExpectedToken, ParseErrors};
pub use token::TokenValue;
use alloc::{string::String, vec::Vec};
use crate::{proc::Layouter, FastHashMap, FastHashSet, Handle, Module, ShaderStage, Span, Type};
use ast::{EntryArg, FunctionDeclaration, GlobalLookup};
use parser::ParsingContext;
mod ast;
mod builtins;
mod context;
mod error;
mod functions;
mod lex;
mod offset;
mod parser;
#[cfg(test)]
mod parser_tests;
mod token;
mod types;
mod variables;
type Result<T> = core::result::Result<T, Error>;
#[derive(Debug)]
pub struct Options {
pub stage: ShaderStage,
pub defines: FastHashMap<String, String>,
}
impl From<ShaderStage> for Options {
fn from(stage: ShaderStage) -> Self {
Options {
stage,
defines: FastHashMap::default(),
}
}
}
#[derive(Debug)]
pub struct ShaderMetadata {
pub version: u16,
pub profile: Profile,
pub stage: ShaderStage,
pub workgroup_size: [u32; 3],
pub early_fragment_tests: bool,
pub extensions: FastHashSet<String>,
}
impl ShaderMetadata {
fn reset(&mut self, stage: ShaderStage) {
self.version = 0;
self.profile = Profile::Core;
self.stage = stage;
self.workgroup_size = [u32::from(stage.compute_like()); 3];
self.early_fragment_tests = false;
self.extensions.clear();
}
}
impl Default for ShaderMetadata {
fn default() -> Self {
ShaderMetadata {
version: 0,
profile: Profile::Core,
stage: ShaderStage::Vertex,
workgroup_size: [0; 3],
early_fragment_tests: false,
extensions: FastHashSet::default(),
}
}
}
#[derive(Debug, Default)]
pub struct Frontend {
meta: ShaderMetadata,
lookup_function: FastHashMap<String, FunctionDeclaration>,
lookup_type: FastHashMap<String, Handle<Type>>,
global_variables: Vec<(String, GlobalLookup)>,
entry_args: Vec<EntryArg>,
layouter: Layouter,
errors: Vec<Error>,
}
impl Frontend {
fn reset(&mut self, stage: ShaderStage) {
self.meta.reset(stage);
self.lookup_function.clear();
self.lookup_type.clear();
self.global_variables.clear();
self.entry_args.clear();
self.layouter.clear();
}
pub fn parse(
&mut self,
options: &Options,
source: &str,
) -> core::result::Result<Module, ParseErrors> {
self.reset(options.stage);
let lexer = lex::Lexer::new(source, &options.defines);
let mut ctx = ParsingContext::new(lexer);
match ctx.parse(self) {
Ok(module) => {
if self.errors.is_empty() {
Ok(module)
} else {
Err(core::mem::take(&mut self.errors).into())
}
}
Err(e) => {
self.errors.push(e);
Err(core::mem::take(&mut self.errors).into())
}
}
}
pub const fn metadata(&self) -> &ShaderMetadata {
&self.meta
}
}