pub mod lexer;
pub mod parser;
mod tokenizer;
pub mod vm;
pub use besl_derive::BeslStruct;
pub use lexer::Expressions;
pub use lexer::Node;
pub use lexer::Nodes;
pub use lexer::Operators;
pub use crate::lexer::BindingTypes;
pub use crate::lexer::NodeReference;
pub type ParserNode<'a> = parser::Node<'a>;
pub trait BeslStructDefinition {
fn besl_struct_node() -> ParserNode<'static>;
fn besl_definition(&self) -> ParserNode<'static> {
Self::besl_struct_node()
}
}
#[macro_export]
macro_rules! besl_struct_node {
(struct $name:ident { $($body:tt)* }) => {{
let mut fields = Vec::new();
$crate::besl_struct_node!(@fields fields [] $($body)*);
$crate::ParserNode::r#struct(
stringify!($name),
fields,
)
}};
(@fields $fields:ident [] ) => {};
(@fields $fields:ident [$($field:tt)+] ) => {
$crate::besl_struct_node!(@emit $fields [$($field)+]);
};
(@fields $fields:ident [$($field:tt)*] , $($rest:tt)*) => {
$crate::besl_struct_node!(@emit $fields [$($field)*]);
$crate::besl_struct_node!(@fields $fields [] $($rest)*);
};
(@fields $fields:ident [$($field:tt)*] $next:tt $($rest:tt)*) => {
$crate::besl_struct_node!(@fields $fields [$($field)* $next] $($rest)*);
};
(@emit $fields:ident []) => {};
(@emit $fields:ident [$field:ident : $($field_type:tt)+]) => {
{
let field_type = stringify!($($field_type)+).replace(' ', "");
$fields.push($crate::ParserNode::member(stringify!($field), &field_type));
}
};
}
pub fn parse<'a>(source: &'a str) -> Result<parser::Node<'a>, CompilationError> {
let tokens = tokenizer::tokenize(source).map_err(|_e| CompilationError::Tokenization)?;
let parser_root_node = parser::parse(&tokens).map_err(CompilationError::Parsing)?;
Ok(parser_root_node)
}
pub fn lex(node: parser::Node) -> Result<NodeReference, CompilationError> {
let besl = lexer::lex(node).map_err(CompilationError::Lex)?;
Ok(besl)
}
pub fn compile_to_besl(source: &str, parent: Option<Node>) -> Result<NodeReference, CompilationError> {
if source.split_whitespace().next().is_none() {
return Ok(lexer::Node::scope("".to_string()).into());
}
let parser_root_node = parse(source)?;
let besl = if let Some(parent) = parent {
lexer::lex_with_root(parent, parser_root_node).map_err(CompilationError::Lex)?
} else {
lexer::lex(parser_root_node).map_err(CompilationError::Lex)?
};
Ok(besl)
}
#[derive(Debug)]
pub enum CompilationError {
Undefined,
Tokenization,
Parsing(parser::ParsingFailReasons),
Lex(lexer::LexError),
}
#[cfg(test)]
mod tests {
use crate::parser::Nodes;
#[test]
fn besl_struct_node_macro_builds_a_struct_node() {
let mut node = crate::besl_struct_node!(struct Light {
position: vec3f,
color: vec3f,
indices: u32[3],
});
match node.node_mut() {
Nodes::Struct { name, fields } => {
assert_eq!(*name, "Light");
assert_eq!(fields.len(), 3);
match fields[0].node_mut() {
Nodes::Member { name, r#type } => {
assert_eq!(*name, "position");
assert_eq!(r#type, "vec3f");
}
_ => panic!("Expected member node."),
}
match fields[2].node_mut() {
Nodes::Member { name, r#type } => {
assert_eq!(*name, "indices");
assert_eq!(r#type, "u32[3]");
}
_ => panic!("Expected member node."),
}
}
_ => panic!("Expected struct node."),
}
}
}