Skip to content

Commit

Permalink
feat(wgsl-in): create skeleton for parsing directives
Browse files Browse the repository at this point in the history
  • Loading branch information
ErichDonGubler committed Oct 3, 2024
1 parent fc4f811 commit d8e73a7
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 0 deletions.
43 changes: 43 additions & 0 deletions naga/src/front/wgsl/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,14 @@ pub(crate) enum Error<'a> {
PipelineConstantIDValue(Span),
NotBool(Span),
ConstAssertFailed(Span),
DirectiveNotYetImplemented {
kind: &'static str,
span: Span,
tracking_issue_num: u16,
},
DirectiveAfterFirstGlobalDecl {
directive_span: Span,
},
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -861,6 +869,41 @@ impl<'a> Error<'a> {
labels: vec![(span, "evaluates to false".into())],
notes: vec![],
},
Error::DirectiveNotYetImplemented {
kind,
span,
tracking_issue_num,
} => ParseError {
message: format!("`{kind}` global directives are not yet supported (sorry!)"),
labels: vec![(
span,
concat!(
"this directive specifies standard functionality ",
"which is not yet implemented in Naga"
)
.into(),
)],
notes: vec![format!(
concat!(
"Let Naga maintainers know that you ran into this at ",
"<https://github.com/gfx-rs/wgpu/issues/{}>, ",
"so they can prioritize it!"
),
tracking_issue_num
)],
},
Error::DirectiveAfterFirstGlobalDecl { directive_span } => ParseError {
message: "expected global declaration, but found a global directive".into(),
labels: vec![(
directive_span,
"this directive was written after global declaration parsing started".into(),
)],
notes: vec![concat!(
"global directives are only allowed before global declarations; ",
"maybe hoist this closer to the top of the shader?"
)
.into()],
},
}
}
}
Expand Down
41 changes: 41 additions & 0 deletions naga/src/front/wgsl/parse/directive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub enum DirectiveKind {
Unimplemented(UnimplementedDirectiveKind),
}

impl DirectiveKind {
pub fn from_ident(s: &str) -> Option<(Self, &'static str)> {
Some(match s {
"diagnostic" => (
Self::Unimplemented(UnimplementedDirectiveKind::Diagnostic),
"diagnostic",
),
"enable" => (
Self::Unimplemented(UnimplementedDirectiveKind::Enable),
"enable",
),
"requires" => (
Self::Unimplemented(UnimplementedDirectiveKind::Requires),
"requires",
),
_ => return None,
})
}
}

#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub enum UnimplementedDirectiveKind {
Diagnostic,
Enable,
Requires,
}

impl UnimplementedDirectiveKind {
pub const fn tracking_issue_num(self) -> u16 {
match self {
Self::Diagnostic => 5320,
Self::Requires => 6350,
Self::Enable => 5476,
}
}
}
29 changes: 29 additions & 0 deletions naga/src/front/wgsl/parse/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::front::wgsl::error::{Error, ExpectedToken};
use crate::front::wgsl::parse::directive::DirectiveKind;
use crate::front::wgsl::parse::lexer::{Lexer, Token};
use crate::front::wgsl::parse::number::Number;
use crate::front::wgsl::Scalar;
Expand All @@ -7,6 +8,7 @@ use crate::{Arena, FastIndexSet, Handle, ShaderStage, Span};

pub mod ast;
pub mod conv;
pub mod directive;
pub mod lexer;
pub mod number;

Expand Down Expand Up @@ -136,6 +138,7 @@ enum Rule {
SingularExpr,
UnaryExpr,
GeneralExpr,
Directive,
}

struct ParsedAttribute<T> {
Expand Down Expand Up @@ -2357,6 +2360,9 @@ impl Parser {
let start = lexer.start_byte_offset();
let kind = match lexer.next() {
(Token::Separator(';'), _) => None,
(Token::Word(word), directive_span) if DirectiveKind::from_ident(word).is_some() => {
return Err(Error::DirectiveAfterFirstGlobalDecl { directive_span });
}
(Token::Word("struct"), _) => {
let name = lexer.next_ident()?;

Expand Down Expand Up @@ -2474,6 +2480,29 @@ impl Parser {

let mut lexer = Lexer::new(source);
let mut tu = ast::TranslationUnit::default();

// Parse directives.
#[allow(clippy::never_loop)]
loop {
if let Ok(ident) = lexer.peek_ident() {
self.push_rule_span(Rule::Directive, &mut lexer);
if let Some((kind, name)) = DirectiveKind::from_ident(ident.name) {
match kind {
DirectiveKind::Unimplemented(unimplemented) => {
return Err(Error::DirectiveNotYetImplemented {
kind: name,
span: ident.span,
tracking_issue_num: unimplemented.tracking_issue_num(),
})
}
}
}
// TODO: add directives to set of expected things in errors later
self.pop_rule_span(&lexer);
}
break;
}

loop {
match self.global_decl(&mut lexer, &mut tu) {
Err(error) => return Err(error),
Expand Down

0 comments on commit d8e73a7

Please sign in to comment.