///|
fn split_extensions(raw : String) -> Array[String] {
let extensions : Array[String] = []
for part in raw.split(",") {
let extension = wgsl_regex_trim_whitespace(part.to_owned())
if extension != "" {
extensions.push(extension)
}
}
extensions
}
///|
fn collect_effective_def_names(
line : String,
effective_defs : @set.Set[String],
) -> Unit {
for reference in parse_wgsl_shader_def_references(line) {
effective_defs.add(reference.name())
}
}
///|
fn parse_define_value(raw_value : String) -> ShaderDefValue {
let value = trim_trailing_semicolons(raw_value)
if value == "" {
return Bool(true)
}
if value == "true" {
return Bool(true)
}
if value == "false" {
return Bool(false)
}
let parsed_unsigned = @string.parse_uint(value[:], base=10) catch {
_ => {
let parsed = @string.parse_int(value[:], base=10) catch {
_ => return Bool(false)
}
return Int(parsed)
}
}
UInt(parsed_unsigned)
}
///|
fn split_define_name_and_value(text : String) -> (String, String) {
let trimmed = wgsl_regex_trim_whitespace(text)
if trimmed == "" {
return ("", "")
}
let mut i = 0
while i < trimmed.length() {
let width = wgsl_regex_word_width(trimmed, i)
guard width > 0 else { break }
i = i + width
}
if i == 0 {
return ("", "")
}
let name = trimmed[0:i].to_owned()
while i < trimmed.length() {
if wgsl_regex_whitespace_code_point(trimmed.code_unit_at(i).to_int()) {
i = i + 1
continue
}
break
}
let value_start = i
while i < trimmed.length() {
let code = trimmed.code_unit_at(i).to_int()
if code == 45 {
i = i + 1
continue
}
let width = wgsl_regex_word_width(trimmed, i)
guard width > 0 else { break }
i = i + width
}
(name, trimmed[value_start:i].to_owned())
}
///|
fn extract_wgsl_directives(
source : String,
) -> (String, WgslDirectives) raise MetadataError {
let directives = WgslDirectives::default()
let cleaned_lines : Array[String] = []
let mut in_directive_section = true
let mut line_index = 0
for item in parse_wgsl_source_directive_items(source) {
let line = item.line()
let trimmed = wgsl_regex_trim_whitespace(line)
match item.kind() {
Trivia => {
cleaned_lines.push(line)
line_index = line_index + 1
continue
}
_ => ()
}
if in_directive_section {
match item.kind() {
Enable(body) => {
let extensions = split_extensions(body)
if extensions.is_empty() {
raise InvalidWgslDirective(
trimmed, line_index, "No extensions specified",
)
}
cleaned_lines.push("")
directives.enables.push(EnableDirective(extensions))
line_index = line_index + 1
continue
}
Requires(body) => {
let extensions = split_extensions(body)
if extensions.is_empty() {
raise InvalidWgslDirective(
trimmed, line_index, "No extensions specified",
)
}
cleaned_lines.push("")
directives.requires.push(RequiresDirective(extensions))
line_index = line_index + 1
continue
}
Diagnostic(severity, rule) => {
if severity != "off" &&
severity != "info" &&
severity != "warning" &&
severity != "warn" &&
severity != "error" {
raise InvalidWgslDirective(
trimmed,
line_index,
"Invalid severity '\{severity}'. Must be one of: off, info, warning, warn, error",
)
}
cleaned_lines.push("")
directives.diagnostics.push(DiagnosticDirective(severity, rule))
line_index = line_index + 1
continue
}
PrefixCandidate => ()
_ => in_directive_section = false
}
}
cleaned_lines.push(line)
line_index = line_index + 1
}
let mut cleaned_source = ""
for i in 0.. 0 {
cleaned_source = "\{cleaned_source}\n"
}
cleaned_source = cleaned_source + cleaned_lines[i]
}
(cleaned_source, directives)
}
///|