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: Remove ALIAS operand parsing limitation #178

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions clients/vscode-hlasmplugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- Files with extension should not be set to hlasm in libs folder
- Lookahead mode does not work correctly when triggered from AINSERTed code
- Incorrect relative immediate operand validation
- Remove ALIAS operand parsing limitation

## [0.14.0](https://github.com/eclipse/che-che4z-lsp-for-hlasm/compare/0.13.0...0.14.0) (2021-08-18)

Expand Down
8 changes: 2 additions & 6 deletions parser_library/src/checking/asm_instr_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,7 @@ bool alias::check(const std::vector<const asm_operand*>& to_check,
{
// TO DO - no support for four characters in EBCDIC (¢, ¬, ±, ¦) - we throw an error although it should
// not be
std::regex regex(R"([\.<¢\(\+\|&!\$\*\);¬\-\/¦,%_>\?`,:#@\=\"~±\[\]\{\}\^\\a-zA-Z0-9]*)");
static const std::regex regex(R"([\.<¢\(\+\|&!\$\*\);¬\-\/¦,%_>\?`,:#@\=\"~±\[\]\{\}\^\\a-zA-Z0-9]*)");
std::string substr = first->operand_identifier.substr(2, first->operand_identifier.size() - 3);
if (!std::regex_match(substr, regex))
{
Expand All @@ -1247,7 +1247,7 @@ bool alias::check(const std::vector<const asm_operand*>& to_check,
}
else if (first->operand_identifier[0] == 'X')
{
if (first->operand_identifier.size() % 2 == 1)
if ((first->operand_identifier.size() - 3) % 2 == 1)
{
add_diagnostic(diagnostic_op::error_A154_ALIAS_X_format_no_of_chars(first->operand_range));
return false;
Expand Down Expand Up @@ -1282,10 +1282,6 @@ bool alias::check(const std::vector<const asm_operand*>& to_check,
}
return true;
}
else
{
return false;
}
}
add_diagnostic(diagnostic_op::error_A151_ALIAS_op_format(first->operand_range));
return false;
Expand Down
5 changes: 5 additions & 0 deletions parser_library/src/diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,11 @@ diagnostic_op diagnostic_op::error_A162_PROCESS_uknown_option(const std::string&
diagnostic_severity::error, "A162", "Error at *PROCESS instruction: unknown assembler option " + option, range);
}

diagnostic_op diagnostic_op::error_A163_ALIAS_mandatory_label(const range& range)
{
return diagnostic_op(diagnostic_severity::error, "A163", "Label not provided on ALIAS instruction", range);
}

diagnostic_op diagnostic_op::error_A200_SCOPE_param(const std::string& instr_name, const range& range)
{
return diagnostic_op(diagnostic_severity::error,
Expand Down
2 changes: 2 additions & 0 deletions parser_library/src/diagnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ struct diagnostic_op

static diagnostic_op error_A162_PROCESS_uknown_option(const std::string& option, const range& range);

static diagnostic_op error_A163_ALIAS_mandatory_label(const range& range);

// operand parameters

static diagnostic_op error_A200_SCOPE_param(const std::string& instr_name, const range& range);
Expand Down
11 changes: 9 additions & 2 deletions parser_library/src/parsing/grammar/assembler_operand_rules.g4
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@
parser grammar assembler_operand_rules;

asm_op returns [operand_ptr op]
: id lpar asm_op_comma_c rpar
:
{ ALIAS() }? ORDSYMBOL string
{
auto range = provider.get_range($ORDSYMBOL,$string.ctx->getStop());
collector.add_hl_symbol(token_info(provider.get_range($ORDSYMBOL),hl_scopes::self_def_type));
$op = std::make_unique<expr_assembler_operand>(std::make_unique<mach_expr_default>(range),$ctx->getText(),range);
}
| id lpar asm_op_comma_c rpar
{
$op = std::make_unique<complex_assembler_operand>(
*$id.name,std::move($asm_op_comma_c.asm_ops),
Expand Down Expand Up @@ -47,7 +54,7 @@ asm_op returns [operand_ptr op]
provider.get_range($lpar.ctx->getStart(),$rpar.ctx->getStop())
);
}
| mach_expr
| { !ALIAS() }? mach_expr
{
std::string upper_case = $mach_expr.ctx->getText();
context::to_upper(upper_case);
Expand Down
6 changes: 6 additions & 0 deletions parser_library/src/parsing/parser_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,12 @@ bool parser_impl::UNKNOWN()
return format.form == processing::processing_form::UNKNOWN;
}

bool parser_impl::ALIAS()
{
auto& [format, opcode] = *proc_status;
return opcode.type == instruction_type::ASM && *opcode.value == "ALIAS";
}

antlr4::misc::IntervalSet parser_impl::getExpectedTokens()
{
if (proc_status->first.kind == processing::processing_kind::LOOKAHEAD)
Expand Down
1 change: 1 addition & 0 deletions parser_library/src/parsing/parser_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class parser_impl : public antlr4::Parser
bool CA();
bool MAC();
bool UNKNOWN();
bool ALIAS();

private:
antlr4::misc::IntervalSet getExpectedTokens() override;
Expand Down
15 changes: 15 additions & 0 deletions parser_library/src/processing/instruction_sets/asm_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ asm_processor::process_table_t asm_processor::create_table(context::hlasm_contex
table.emplace(h_ctx.ids().add("CCW1"), [this](rebuilt_statement stmt) { process_CCW(std::move(stmt)); });
table.emplace(h_ctx.ids().add("CNOP"), [this](rebuilt_statement stmt) { process_CNOP(std::move(stmt)); });
table.emplace(h_ctx.ids().add("START"), [this](rebuilt_statement stmt) { process_START(std::move(stmt)); });
table.emplace(h_ctx.ids().add("ALIAS"), [this](rebuilt_statement stmt) { process_ALIAS(std::move(stmt)); });

return table;
}
Expand Down Expand Up @@ -817,4 +818,18 @@ void asm_processor::process_START(rebuilt_statement stmt)
hlasm_ctx.ord_ctx.set_available_location_counter_value(start_section_alignment, offset);
}

void asm_processor::process_ALIAS(rebuilt_statement stmt)
{
if (!check(stmt, hlasm_ctx, checker_, *this))
return;
auto symbol_name = find_label_symbol(stmt);
if (symbol_name->empty())
{
add_diagnostic(diagnostic_op::error_A163_ALIAS_mandatory_label(stmt.stmt_range_ref()));
return;
}

// TODO: check that the symbol_name is an external symbol
}

} // namespace hlasm_plugin::parser_library::processing
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class asm_processor : public low_language_processor
void process_CCW(rebuilt_statement stmt);
void process_CNOP(rebuilt_statement stmt);
void process_START(rebuilt_statement stmt);
void process_ALIAS(rebuilt_statement stmt);

template<checking::data_instr_type instr_type>
void process_data_instruction(rebuilt_statement stmt);
Expand Down
4 changes: 0 additions & 4 deletions parser_library/test/checking/asm_instr_check_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -876,14 +876,10 @@ TEST_F(instruction_test, ainsert)

TEST_F(instruction_test, alias)
{
// TO DO - not working due to self-defining terms issues

/*
EXPECT_FALSE(checker.check("ALIAS", test_alias_false, range(), collector));
EXPECT_TRUE(checker.check("ALIAS", test_alias_true_one, range(), collector));
EXPECT_TRUE(checker.check("ALIAS", test_alias_true_two, range(), collector));
EXPECT_FALSE(checker.check("ALIAS", test_acontrol_true, range(), collector));
*/
}

TEST_F(instruction_test, amode)
Expand Down
81 changes: 80 additions & 1 deletion parser_library/test/processing/asm_instr_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "gtest/gtest.h"

#include "../common_testing.h"
#include "analyzer.h"
#include "ebcdic_encoding.h"

Expand Down Expand Up @@ -132,4 +133,82 @@ CNOPSYM CNOP ADDR,16
auto symbol = ctx.ord_ctx.get_symbol(ctx.ids().add("CNOPSYM"));
ASSERT_NE(symbol, nullptr);
EXPECT_EQ(symbol->value().get_reloc().offset(), 4);
}
}

TEST(asm_instr_processing, ALIAS_mandatory_label)
{
std::string input = R"(
ALIAS C'SOMESTRING'
ALIAS X'434343434343'
)";

analyzer a(input);
a.analyze();
a.collect_diags();

EXPECT_TRUE(matches_message_codes(a.diags(), { "A163", "A163" }));
}

TEST(asm_instr_processing, ALIAS_external_missing)
{
/* TODO: label must be an external symbol
std::string input = R"(
A ALIAS C'SOMESTRING'
)";

analyzer a(input);
a.analyze();
a.collect_diags();

EXPECT_TRUE(matches_message_codes(a.diags(), { "????" }));
*/
}

TEST(asm_instr_processing, ALIAS_external_present)
{
std::string input = R"(
A DSECT
B START
C CSECT
D DXD F
DC Q(A)
ENTRY E
E DS 0H
DC V(F)
G RSECT
H COM
EXTRN I
WXTRN J
A ALIAS C'STRING'
B ALIAS C'STRING'
C ALIAS C'STRING'
D ALIAS C'STRING'
E ALIAS C'STRING'
F ALIAS C'STRING'
G ALIAS C'STRING'
H ALIAS C'STRING'
I ALIAS C'STRING'
J ALIAS C'STRING'
)";

analyzer a(input);
a.analyze();
a.collect_diags();

EXPECT_TRUE(a.diags().empty());
}

TEST(asm_instr_processing, ALIAS_with_opsyn)
{
std::string input = R"(
X OPSYN ALIAS
L X C'SOMESTRING'
EXTRN L
)";

analyzer a(input);
a.analyze();
a.collect_diags();

EXPECT_TRUE(a.diags().empty());
}