Merge pull request #98267 from Chaosus/shader_pp_error

Add `#error` preprocessor directive to shading language
This commit is contained in:
Thaddeus Crews 2024-10-21 16:39:23 -05:00
commit 1a9628f937
No known key found for this signature in database
GPG Key ID: 62181B86FE9E5D84
2 changed files with 31 additions and 12 deletions

View File

@ -393,6 +393,8 @@ void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) {
process_else(p_tokenizer); process_else(p_tokenizer);
} else if (directive == "endif") { } else if (directive == "endif") {
process_endif(p_tokenizer); process_endif(p_tokenizer);
} else if (directive == "error") {
process_error(p_tokenizer);
} else if (directive == "define") { } else if (directive == "define") {
process_define(p_tokenizer); process_define(p_tokenizer);
} else if (directive == "undef") { } else if (directive == "undef") {
@ -466,7 +468,7 @@ void ShaderPreprocessor::process_elif(Tokenizer *p_tokenizer) {
const int line = p_tokenizer->get_line(); const int line = p_tokenizer->get_line();
if (state->current_branch == nullptr || state->current_branch->else_defined) { if (state->current_branch == nullptr || state->current_branch->else_defined) {
set_error(RTR("Unmatched elif."), line); set_error(vformat(RTR("Unmatched '%s' directive."), "elif"), line);
return; return;
} }
if (state->previous_region != nullptr) { if (state->previous_region != nullptr) {
@ -523,7 +525,7 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) {
const int line = p_tokenizer->get_line(); const int line = p_tokenizer->get_line();
if (state->current_branch == nullptr || state->current_branch->else_defined) { if (state->current_branch == nullptr || state->current_branch->else_defined) {
set_error(RTR("Unmatched else."), line); set_error(vformat(RTR("Unmatched '%s' directive."), "else"), line);
return; return;
} }
if (state->previous_region != nullptr) { if (state->previous_region != nullptr) {
@ -531,7 +533,7 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) {
} }
if (!p_tokenizer->consume_empty_line()) { if (!p_tokenizer->consume_empty_line()) {
set_error(RTR("Invalid else."), p_tokenizer->get_line()); set_error(vformat(RTR("Invalid '%s' directive."), "else"), line);
} }
bool skip = false; bool skip = false;
@ -559,7 +561,7 @@ void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) {
state->condition_depth--; state->condition_depth--;
if (state->condition_depth < 0) { if (state->condition_depth < 0) {
set_error(RTR("Unmatched endif."), line); set_error(vformat(RTR("Unmatched '%s' directive."), "endif"), line);
return; return;
} }
if (state->previous_region != nullptr) { if (state->previous_region != nullptr) {
@ -568,13 +570,28 @@ void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) {
} }
if (!p_tokenizer->consume_empty_line()) { if (!p_tokenizer->consume_empty_line()) {
set_error(RTR("Invalid endif."), line); set_error(vformat(RTR("Invalid '%s' directive."), "endif"), line);
} }
state->current_branch = state->current_branch->parent; state->current_branch = state->current_branch->parent;
state->branches.pop_back(); state->branches.pop_back();
} }
void ShaderPreprocessor::process_error(Tokenizer *p_tokenizer) {
const int line = p_tokenizer->get_line();
const String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
if (body.is_empty()) {
set_error(" ", line);
} else {
set_error(body, line);
}
if (!p_tokenizer->consume_empty_line()) {
set_error(vformat(RTR("Invalid '%s' directive."), "error"), line);
}
}
void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) { void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) {
const int line = p_tokenizer->get_line(); const int line = p_tokenizer->get_line();
@ -626,7 +643,7 @@ void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) {
} }
if (!p_tokenizer->consume_empty_line()) { if (!p_tokenizer->consume_empty_line()) {
set_error(RTR("Invalid ifdef."), line); set_error(vformat(RTR("Invalid '%s' directive."), "ifdef"), line);
return; return;
} }
@ -648,7 +665,7 @@ void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) {
} }
if (!p_tokenizer->consume_empty_line()) { if (!p_tokenizer->consume_empty_line()) {
set_error(RTR("Invalid ifndef."), line); set_error(vformat(RTR("Invalid '%s' directive."), "ifndef"), line);
return; return;
} }
@ -771,21 +788,21 @@ void ShaderPreprocessor::process_pragma(Tokenizer *p_tokenizer) {
} }
if (label.is_empty()) { if (label.is_empty()) {
set_error(RTR("Invalid pragma directive."), line); set_error(vformat(RTR("Invalid '%s' directive."), "pragma"), line);
return; return;
} }
// Rxplicitly handle pragma values here. // Explicitly handle pragma values here.
// If more pragma options are created, then refactor into a more defined structure. // If more pragma options are created, then refactor into a more defined structure.
if (label == "disable_preprocessor") { if (label == "disable_preprocessor") {
state->disabled = true; state->disabled = true;
} else { } else {
set_error(RTR("Invalid pragma directive."), line); set_error(vformat(RTR("Invalid '%s' directive."), "pragma"), line);
return; return;
} }
if (!p_tokenizer->consume_empty_line()) { if (!p_tokenizer->consume_empty_line()) {
set_error(RTR("Invalid pragma directive."), line); set_error(vformat(RTR("Invalid '%s' directive."), "pragma"), line);
return; return;
} }
} }
@ -794,7 +811,7 @@ void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) {
const int line = p_tokenizer->get_line(); const int line = p_tokenizer->get_line();
const String label = p_tokenizer->get_identifier(); const String label = p_tokenizer->get_identifier();
if (label.is_empty() || !p_tokenizer->consume_empty_line()) { if (label.is_empty() || !p_tokenizer->consume_empty_line()) {
set_error(RTR("Invalid undef."), line); set_error(vformat(RTR("Invalid '%s' directive."), "undef"), line);
return; return;
} }
@ -1383,6 +1400,7 @@ void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_inclu
r_keywords->push_back("else"); r_keywords->push_back("else");
} }
r_keywords->push_back("endif"); r_keywords->push_back("endif");
r_keywords->push_back("error");
if (p_include_shader_keywords) { if (p_include_shader_keywords) {
r_keywords->push_back("if"); r_keywords->push_back("if");
} }

View File

@ -191,6 +191,7 @@ private:
void process_elif(Tokenizer *p_tokenizer); void process_elif(Tokenizer *p_tokenizer);
void process_else(Tokenizer *p_tokenizer); void process_else(Tokenizer *p_tokenizer);
void process_endif(Tokenizer *p_tokenizer); void process_endif(Tokenizer *p_tokenizer);
void process_error(Tokenizer *p_tokenizer);
void process_if(Tokenizer *p_tokenizer); void process_if(Tokenizer *p_tokenizer);
void process_ifdef(Tokenizer *p_tokenizer); void process_ifdef(Tokenizer *p_tokenizer);
void process_ifndef(Tokenizer *p_tokenizer); void process_ifndef(Tokenizer *p_tokenizer);