Skip to content

Commit

Permalink
fix: Remove ALIAS operand parsing limitation (#178)
Browse files Browse the repository at this point in the history
(fixes #157)
  • Loading branch information
slavek-kucera authored Sep 17, 2021
1 parent 614c86e commit 480e602
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 13 deletions.
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());
}

0 comments on commit 480e602

Please sign in to comment.