[wgsl] first bits of function parsing

This commit is contained in:
Dzmitry Malyshau 2020-03-03 13:52:47 -05:00
parent c2265ca4c8
commit 4a9f838208
2 changed files with 66 additions and 4 deletions

View File

@ -7,7 +7,7 @@ global_decl = {
| global_constant_decl ~ ";"
// | entry_point_decl ~ ";"
| type_alias ~ ";"
// | function_decl
| function_decl
}
import_decl = { "import" ~ string ~ "as" ~ (ident ~ "::")* ~ ident}
@ -46,15 +46,18 @@ struct_decoration = {
}
struct_body_decl = { "{" ~ struct_member* ~ "}" }
struct_member = { struct_member_decoration_decl? ~ variable_ident_decl ~ ";" }
struct_member_decoration_decl = { "[[" ~ (struct_member_decoration ~ ",")* ~ struct_member_decoration ~ "]]" }
struct_member_decoration = {
"offset" ~ int_literal
}
function_decl = { function_header ~ body_stmt }
function_header = { "fn" ~ ident ~ "(" ~ param_list ~ ")" ~ "->" ~ function_type_decl }
function_type_decl = _{ type_decl | "void" }
param_list = { (variable_ident_decl ~ ",")* ~ variable_ident_decl }
body_stmt = { "{" ~ statement* ~ "}" }
storage_class = {
"in"
| "out"
@ -103,6 +106,26 @@ scalar_type = {
| "u32"
}
statement = {
";"
| "return" ~ primary_expression ~ ";"
// | if_stmt
// | unless_stmt
// | regardless_stmt
// | switch_stmt
// | loop_stmt
// | variable_stmt SEMICOLON
// | break_stmt SEMICOLON
// | continue_stmt SEMICOLON
// | KILL SEMICOLON
// | NOP SEMICOLON
// | assignment_stmt SEMICOLON
}
primary_expression = {
const_literal
}
ident = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")* }
int_literal = @{ ("-"? ~ "0x"? ~ (ASCII_DIGIT | 'a'..'f' | 'A'..'F')+) | "0" | ("-"? ~ '1'..'9' ~ ASCII_DIGIT*) }
string = @{ "\"" ~ ( "\"\"" | (!"\"" ~ ANY) )* ~ "\"" }

View File

@ -159,6 +159,42 @@ impl Parser {
Ok(crate::TypeInner::Struct { members })
}
fn parse_function_decl(
&self,
function_decl: pest::iterators::Pair<Rule>,
module: &mut crate::Module,
) -> Result<Token<crate::Function>, Error> {
assert_eq!(function_decl.as_rule(), Rule::function_decl);
let mut function_decl_pairs = function_decl.into_inner();
let function_header = function_decl_pairs.next().unwrap();
assert_eq!(function_header.as_rule(), Rule::function_header);
let mut function_header_pairs = function_header.into_inner();
let fun_name = function_header_pairs.next().unwrap().as_str().to_owned();
let param_list = function_header_pairs.next().unwrap();
assert_eq!(param_list.as_rule(), Rule::param_list);
let function_type_decl = function_header_pairs.next().unwrap();
let fun = crate::Function {
name: Some(fun_name),
control: spirv::FunctionControl::empty(),
parameter_types: Vec::new(),
return_type: if function_type_decl.as_rule() == Rule::type_decl {
self.parse_type_decl(function_type_decl, &mut module.types)?
} else {
module.types.append(crate::Type {
name: None,
inner: crate::TypeInner::Void,
})
},
expressions: Storage::new(),
body: Vec::new(),
};
let function_body = function_decl_pairs.next().unwrap();
assert_eq!(function_body.as_rule(), Rule::body_stmt);
Ok(module.functions.append(fun))
}
pub fn parse(&mut self, source: &str) -> Result<crate::Module, Error> {
use pest::Parser as _;
let pairs = Tokenizer::parse(Rule::translation_unit, source)?;
@ -222,6 +258,9 @@ impl Parser {
other => panic!("Unexpected type alias rule {:?}", other),
};
}
Rule::function_decl => {
self.parse_function_decl(global_decl, &mut module)?;
}
unknown => panic!("Unexpected global decl: {:?}", unknown),
}
}