From d8545fee66cf2987d9cdf179529df4d7987d9c6e Mon Sep 17 00:00:00 2001 From: slavek-kucera <53339291+slavek-kucera@users.noreply.github.com> Date: Wed, 18 Aug 2021 12:26:27 +0200 Subject: [PATCH] fix: Preserve mixed-case labels on macro calls (#165) fix: Keep mixed-case variant of the ordsymbol label and use it in macro calls (fixes eclipse/che-che4z-lsp-for-hlasm#155) --- .../src/parsing/grammar/label_field_rules.g4 | 2 +- .../src/parsing/grammar/lookahead_rules.g4 | 5 +- .../low_language_processor.cpp | 56 ++++++++++--------- .../instruction_sets/macro_processor.cpp | 16 +++--- .../statement_analyzers/lsp_analyzer.cpp | 2 +- .../lookahead_processor.cpp | 4 +- parser_library/src/semantics/collector.cpp | 5 +- parser_library/src/semantics/collector.h | 3 +- .../src/semantics/statement_fields.h | 10 +++- parser_library/test/processing/label_test.cpp | 21 +++++++ 10 files changed, 80 insertions(+), 44 deletions(-) diff --git a/parser_library/src/parsing/grammar/label_field_rules.g4 b/parser_library/src/parsing/grammar/label_field_rules.g4 index b777cb393..0a118e60d 100644 --- a/parser_library/src/parsing/grammar/label_field_rules.g4 +++ b/parser_library/src/parsing/grammar/label_field_rules.g4 @@ -32,7 +32,7 @@ label if (!label.empty() && label[0] != '&') collector.add_hl_symbol(token_info(r,hl_scopes::label)); auto id = hlasm_ctx->ids().add($l_char_string.value); - collector.set_label_field(id,$l_char_string.ctx,r); + collector.set_label_field(id,std::move($l_char_string.value),$l_char_string.ctx,r); } } | l_char_string_sp l_char_string_o diff --git a/parser_library/src/parsing/grammar/lookahead_rules.g4 b/parser_library/src/parsing/grammar/lookahead_rules.g4 index 31978733d..12473d913 100644 --- a/parser_library/src/parsing/grammar/lookahead_rules.g4 +++ b/parser_library/src/parsing/grammar/lookahead_rules.g4 @@ -27,8 +27,9 @@ look_lab_instr returns [std::optional op_text, range op_range] if ($ORDSYMBOL) { auto r = provider.get_range($ORDSYMBOL); - auto id = hlasm_ctx->ids().add($ORDSYMBOL->getText()); - collector.set_label_field(id,nullptr,r); + auto ord_symbol = $ORDSYMBOL->getText(); + auto id = hlasm_ctx->ids().add(ord_symbol); + collector.set_label_field(id,std::move(ord_symbol),nullptr,r); } $op_text = $operand_field_rest.ctx->getText(); diff --git a/parser_library/src/processing/instruction_sets/low_language_processor.cpp b/parser_library/src/processing/instruction_sets/low_language_processor.cpp index 3d4335f1e..64ef0abcc 100644 --- a/parser_library/src/processing/instruction_sets/low_language_processor.cpp +++ b/parser_library/src/processing/instruction_sets/low_language_processor.cpp @@ -88,10 +88,10 @@ rebuilt_statement low_language_processor::preprocess(std::shared_ptr(stmt.label_ref().value), stmt.label_ref().field_range); + auto ret = mngr.get_symbol_name(*std::get(label.value).symbol, label.field_range); collect_diags_from_child(mngr); return ret; } @@ -130,51 +130,55 @@ bool trim_right(std::string& s) low_language_processor::preprocessed_part low_language_processor::preprocess_inner(const resolved_statement& stmt) { - std::optional label; - std::optional operands; + using namespace semantics; + std::optional label; + std::optional operands; std::string new_label; // label - switch (stmt.label_ref().type) + switch (const auto& label_ref = stmt.label_ref(); label_ref.type) { - case semantics::label_si_type::CONC: - new_label = semantics::concatenation_point::evaluate( - std::get(stmt.label_ref().value), eval_ctx); + case label_si_type::CONC: + new_label = concatenation_point::evaluate(std::get(label_ref.value), eval_ctx); if (!trim_right(new_label)) - label.emplace(stmt.label_ref().field_range); + label.emplace(label_ref.field_range); else - label.emplace(stmt.label_ref().field_range, std::move(new_label)); + { + auto ord_id = hlasm_ctx.ids().add(new_label); + label.emplace(label_ref.field_range, ord_symbol_string { ord_id, std::move(new_label) }); + } break; - case semantics::label_si_type::VAR: - new_label = semantics::var_sym_conc::evaluate( - std::get(stmt.label_ref().value)->evaluate(eval_ctx)); + case label_si_type::VAR: + new_label = var_sym_conc::evaluate(std::get(label_ref.value)->evaluate(eval_ctx)); if (!trim_right(new_label)) - label.emplace(stmt.label_ref().field_range); + label.emplace(label_ref.field_range); else - label.emplace(stmt.label_ref().field_range, std::move(new_label)); + { + auto ord_id = hlasm_ctx.ids().add(new_label); + label.emplace(label_ref.field_range, ord_symbol_string { ord_id, std::move(new_label) }); + } break; - case semantics::label_si_type::MAC: - add_diagnostic(diagnostic_op::error_E057(stmt.label_ref().field_range)); + case label_si_type::MAC: + add_diagnostic(diagnostic_op::error_E057(label_ref.field_range)); break; - case semantics::label_si_type::SEQ: - branch_provider.register_sequence_symbol(std::get(stmt.label_ref().value).name, - std::get(stmt.label_ref().value).symbol_range); + case label_si_type::SEQ: + branch_provider.register_sequence_symbol( + std::get(label_ref.value).name, std::get(label_ref.value).symbol_range); break; default: break; } // operands - if (!stmt.operands_ref().value.empty() && stmt.operands_ref().value[0]->type == semantics::operand_type::MODEL) + if (const auto& operands_ref = stmt.operands_ref(); + !operands_ref.value.empty() && operands_ref.value[0]->type == operand_type::MODEL) { - assert(stmt.operands_ref().value.size() == 1); - std::string field( - semantics::concatenation_point::evaluate(stmt.operands_ref().value[0]->access_model()->chain, eval_ctx)); + assert(operands_ref.value.size() == 1); + std::string field(concatenation_point::evaluate(operands_ref.value[0]->access_model()->chain, eval_ctx)); operands.emplace(parser .parse_operand_field(std::move(field), true, - semantics::range_provider(stmt.operands_ref().value[0]->operand_range, - semantics::adjusting_state::SUBSTITUTION), + range_provider(operands_ref.value[0]->operand_range, adjusting_state::SUBSTITUTION), processing_status(stmt.format_ref(), stmt.opcode_ref()), *this) .first); diff --git a/parser_library/src/processing/instruction_sets/macro_processor.cpp b/parser_library/src/processing/instruction_sets/macro_processor.cpp index f26256a7e..92dc900dd 100644 --- a/parser_library/src/processing/instruction_sets/macro_processor.cpp +++ b/parser_library/src/processing/instruction_sets/macro_processor.cpp @@ -180,18 +180,20 @@ macro_arguments macro_processor::get_args(const resolved_statement& statement) c context::macro_data_ptr macro_processor::get_label_args(const resolved_statement& statement) const { - switch (statement.label_ref().type) + const auto& label = statement.label_ref(); + switch (label.type) { case semantics::label_si_type::CONC: - return std::make_unique(semantics::concatenation_point::evaluate( - std::get(statement.label_ref().value), eval_ctx)); + return std::make_unique( + semantics::concatenation_point::evaluate(std::get(label.value), eval_ctx)); case semantics::label_si_type::ORD: - case semantics::label_si_type::MAC: return std::make_unique( - std::get(statement.label_ref().value)); + std::get(label.value).mixed_case); + case semantics::label_si_type::MAC: + return std::make_unique(std::get(label.value)); case semantics::label_si_type::VAR: - return std::make_unique(semantics::var_sym_conc::evaluate( - std::get(statement.label_ref().value)->evaluate(eval_ctx))); + return std::make_unique( + semantics::var_sym_conc::evaluate(std::get(label.value)->evaluate(eval_ctx))); default: return context::macro_data_ptr(); } diff --git a/parser_library/src/processing/statement_analyzers/lsp_analyzer.cpp b/parser_library/src/processing/statement_analyzers/lsp_analyzer.cpp index 300278add..ca2b2feb3 100644 --- a/parser_library/src/processing/statement_analyzers/lsp_analyzer.cpp +++ b/parser_library/src/processing/statement_analyzers/lsp_analyzer.cpp @@ -163,7 +163,7 @@ void lsp_analyzer::collect_occurence(const semantics::label_si& label, occurence collector.get_occurence(std::get(label.value)); break; case semantics::label_si_type::ORD: - collector.get_occurence(hlasm_ctx_.ids().add(std::get(label.value)), label.field_range); + collector.get_occurence(std::get(label.value).symbol, label.field_range); break; case semantics::label_si_type::SEQ: collector.get_occurence(std::get(label.value)); diff --git a/parser_library/src/processing/statement_processors/lookahead_processor.cpp b/parser_library/src/processing/statement_processors/lookahead_processor.cpp index f5a257bd5..4565e163c 100644 --- a/parser_library/src/processing/statement_processors/lookahead_processor.cpp +++ b/parser_library/src/processing/statement_processors/lookahead_processor.cpp @@ -290,8 +290,8 @@ void lookahead_processor::find_ord(const resolved_statement& statement) if (statement.label_ref().type != semantics::label_si_type::ORD) return; - auto name = std::get(statement.label_ref().value); - auto [valid, id] = context_manager(hlasm_ctx).try_get_symbol_name(std::move(name)); + auto name = std::get(statement.label_ref().value).symbol; + auto [valid, id] = context_manager(hlasm_ctx).try_get_symbol_name(*name); if (!valid) return; diff --git a/parser_library/src/semantics/collector.cpp b/parser_library/src/semantics/collector.cpp index 523fd1e26..bcf7517e7 100644 --- a/parser_library/src/semantics/collector.cpp +++ b/parser_library/src/semantics/collector.cpp @@ -65,7 +65,8 @@ void collector::set_label_field(seq_sym sequence_symbol, range symbol_range) lbl_.emplace(symbol_range, std::move(sequence_symbol)); } -void collector::set_label_field(const std::string* label, antlr4::ParserRuleContext* parser_ctx, range symbol_range) +void collector::set_label_field( + const std::string* label, std::string mixed_case_label, antlr4::ParserRuleContext* parser_ctx, range symbol_range) { if (lbl_) throw std::runtime_error("field already assigned"); @@ -74,7 +75,7 @@ void collector::set_label_field(const std::string* label, antlr4::ParserRuleCont || (parser_ctx->getStart() == parser_ctx->getStop() && parser_ctx->getStart()->getType() == lexing::lexer::Tokens::ORDSYMBOL)) { - lbl_.emplace(symbol_range, *label); + lbl_.emplace(symbol_range, ord_symbol_string { label, std::move(mixed_case_label) }); } // otherwise it is macro label parameter else diff --git a/parser_library/src/semantics/collector.h b/parser_library/src/semantics/collector.h index c53998716..37b134d55 100644 --- a/parser_library/src/semantics/collector.h +++ b/parser_library/src/semantics/collector.h @@ -42,7 +42,8 @@ class collector void set_label_field(range symbol_range); void set_label_field(std::string label, range symbol_range); void set_label_field(seq_sym sequence_symbol, range symbol_range); - void set_label_field(const std::string* label, antlr4::ParserRuleContext* ctx, range symbol_range); + void set_label_field( + const std::string* label, std::string mixed_case_label, antlr4::ParserRuleContext* ctx, range symbol_range); void set_label_field(concat_chain label, range symbol_range); void set_instruction_field(range symbol_range); diff --git a/parser_library/src/semantics/statement_fields.h b/parser_library/src/semantics/statement_fields.h index 686b72f92..b9417cdaa 100644 --- a/parser_library/src/semantics/statement_fields.h +++ b/parser_library/src/semantics/statement_fields.h @@ -36,14 +36,20 @@ enum class label_si_type EMPTY }; -using label_si_value_t = std::variant; +struct ord_symbol_string +{ + context::id_index symbol = nullptr; + std::string mixed_case; +}; + +using label_si_value_t = std::variant; // struct holding semantic information (si) about label field struct label_si { struct mac_flag {}; - label_si(range field_range, std::string value) + label_si(range field_range, ord_symbol_string value) : type(label_si_type::ORD) , field_range(std::move(field_range)) , value(std::move(value)) diff --git a/parser_library/test/processing/label_test.cpp b/parser_library/test/processing/label_test.cpp index fbc996967..eed54cc69 100644 --- a/parser_library/test/processing/label_test.cpp +++ b/parser_library/test/processing/label_test.cpp @@ -52,3 +52,24 @@ TEST(instruction_label, invalid_concatenation) EXPECT_EQ(diags.size(), 2); } + +TEST(instruction_label, mixed_case_in_macro_call) +{ + std::string input(R"( + MACRO +&LABEL TEST + AIF ('&LABEL' EQ 'MixedCase').SKIP + FAIL +.SKIP ANOP + MEND + +MixedCase TEST + +)"); + analyzer a(input); + a.analyze(); + + a.collect_diags(); + + EXPECT_TRUE(a.diags().empty()); +}