Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Preserve mixed-case labels on macro calls #165

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion parser_library/src/parsing/grammar/label_field_rules.g4
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions parser_library/src/parsing/grammar/lookahead_rules.g4
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ look_lab_instr returns [std::optional<std::string> 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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ rebuilt_statement low_language_processor::preprocess(std::shared_ptr<const proce

context::id_index low_language_processor::find_label_symbol(const rebuilt_statement& stmt) const
{
if (stmt.label_ref().type == semantics::label_si_type::ORD)
if (const auto& label = stmt.label_ref(); label.type == semantics::label_si_type::ORD)
{
context_manager mngr(hlasm_ctx);
auto ret = mngr.get_symbol_name(std::get<std::string>(stmt.label_ref().value), stmt.label_ref().field_range);
auto ret = mngr.get_symbol_name(*std::get<semantics::ord_symbol_string>(label.value).symbol, label.field_range);
collect_diags_from_child(mngr);
return ret;
}
Expand Down Expand Up @@ -130,51 +130,56 @@ bool trim_right(std::string& s)

low_language_processor::preprocessed_part low_language_processor::preprocess_inner(const resolved_statement& stmt)
{
std::optional<semantics::label_si> label;
std::optional<semantics::operands_si> operands;
using namespace semantics;
std::optional<label_si> label;
std::optional<operands_si> operands;

std::string new_label;
// label
switch (stmt.label_ref().type)
const auto& label_ref = stmt.label_ref();
switch (label_ref.type)
{
case semantics::label_si_type::CONC:
new_label = semantics::concatenation_point::evaluate(
std::get<semantics::concat_chain>(stmt.label_ref().value), eval_ctx);
case label_si_type::CONC:
new_label = concatenation_point::evaluate(std::get<concat_chain>(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<semantics::vs_ptr>(stmt.label_ref().value)->evaluate(eval_ctx));
case label_si_type::VAR:
new_label = var_sym_conc::evaluate(std::get<vs_ptr>(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<semantics::seq_sym>(stmt.label_ref().value).name,
std::get<semantics::seq_sym>(stmt.label_ref().value).symbol_range);
case label_si_type::SEQ:
branch_provider.register_sequence_symbol(
std::get<seq_sym>(label_ref.value).name, std::get<seq_sym>(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)
const auto& operands_ref = stmt.operands_ref();
if (!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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<context::macro_param_data_single>(semantics::concatenation_point::evaluate(
std::get<semantics::concat_chain>(statement.label_ref().value), eval_ctx));
return std::make_unique<context::macro_param_data_single>(
semantics::concatenation_point::evaluate(std::get<semantics::concat_chain>(label.value), eval_ctx));
case semantics::label_si_type::ORD:
case semantics::label_si_type::MAC:
return std::make_unique<context::macro_param_data_single>(
std::get<std::string>(statement.label_ref().value));
std::get<semantics::ord_symbol_string>(label.value).mixed_case);
case semantics::label_si_type::MAC:
return std::make_unique<context::macro_param_data_single>(std::get<std::string>(label.value));
case semantics::label_si_type::VAR:
return std::make_unique<context::macro_param_data_single>(semantics::var_sym_conc::evaluate(
std::get<semantics::vs_ptr>(statement.label_ref().value)->evaluate(eval_ctx)));
return std::make_unique<context::macro_param_data_single>(
semantics::var_sym_conc::evaluate(std::get<semantics::vs_ptr>(label.value)->evaluate(eval_ctx)));
default:
return context::macro_data_ptr();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ void lsp_analyzer::collect_occurence(const semantics::label_si& label, occurence
collector.get_occurence(std::get<semantics::concat_chain>(label.value));
break;
case semantics::label_si_type::ORD:
collector.get_occurence(hlasm_ctx_.ids().add(std::get<std::string>(label.value)), label.field_range);
collector.get_occurence(std::get<semantics::ord_symbol_string>(label.value).symbol, label.field_range);
break;
case semantics::label_si_type::SEQ:
collector.get_occurence(std::get<semantics::seq_sym>(label.value));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string>(statement.label_ref().value);
auto [valid, id] = context_manager(hlasm_ctx).try_get_symbol_name(std::move(name));
auto name = std::get<semantics::ord_symbol_string>(statement.label_ref().value).symbol;
auto [valid, id] = context_manager(hlasm_ctx).try_get_symbol_name(*name);
if (!valid)
return;

Expand Down
5 changes: 3 additions & 2 deletions parser_library/src/semantics/collector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion parser_library/src/semantics/collector.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 8 additions & 2 deletions parser_library/src/semantics/statement_fields.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,20 @@ enum class label_si_type
EMPTY
};

using label_si_value_t = std::variant<std::string, concat_chain, seq_sym, vs_ptr>;
struct ord_symbol_string
{
context::id_index symbol = nullptr;
std::string mixed_case;
};

using label_si_value_t = std::variant<std::string, ord_symbol_string, concat_chain, seq_sym, vs_ptr>;

// 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))
Expand Down
21 changes: 21 additions & 0 deletions parser_library/test/processing/label_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}