Skip to content

Commit

Permalink
fix: Preserve mixed-case labels on macro calls (#165)
Browse files Browse the repository at this point in the history
fix: Keep mixed-case variant of the ordsymbol label and use it in macro calls (fixes #155)
  • Loading branch information
slavek-kucera authored Aug 18, 2021
1 parent 9f65cd4 commit d8545fe
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 44 deletions.
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,55 @@ 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)
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<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)
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);
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());
}

0 comments on commit d8545fe

Please sign in to comment.