Skip to content

Commit

Permalink
feat: Location counter length attribute support (#208)
Browse files Browse the repository at this point in the history
(closes #71)
  • Loading branch information
slavek-kucera authored Dec 14, 2021
1 parent 44a93f2 commit c2d64c9
Show file tree
Hide file tree
Showing 19 changed files with 321 additions and 233 deletions.
4 changes: 4 additions & 0 deletions clients/vscode-hlasmplugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## ****Unreleased****

#### Added
- Literal support
- Location counter length attribute support

## [0.15.1](https://github.com/eclipse/che-che4z-lsp-for-hlasm/compare/0.15.0...0.15.1) (2021-11-11)

#### Fixed
Expand Down
24 changes: 18 additions & 6 deletions parser_library/src/parsing/grammar/machine_expr_rules.g4
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ mach_term returns [mach_expr_ptr m_e]
if constexpr (std::is_same_v<std::decay_t<decltype(arg)>,std::monostate>) {
return std::make_unique<mach_expr_default>(rng);
}
else if constexpr (std::is_same_v<std::decay_t<decltype(arg)>,int>) {
return std::make_unique<mach_expr_constant>(arg, symbol_rng);
}
else {
return std::make_unique<mach_expr_data_attr>(std::move(arg), attr, rng, symbol_rng);
}
Expand Down Expand Up @@ -122,14 +125,24 @@ literal returns [std::optional<data_definition> value]
add_diagnostic(diagnostic_severity::error, "S0013", "Invalid literal usage", provider.get_range($equals.ctx));
};

mach_data_attribute returns [data_attr_kind attribute, std::variant<std::monostate, id_index, std::unique_ptr<mach_expr_literal>> data, range symbol_rng]
: ORDSYMBOL (attr|apostrophe_as_attr) {auto lit_restore = enable_literals();} mach_data_attribute_value
mach_data_attribute returns [data_attr_kind attribute, std::variant<std::monostate, id_index, std::unique_ptr<mach_expr_literal>, int> data, range symbol_rng]
: ORDSYMBOL (attr|apostrophe_as_attr) {auto lit_restore = enable_literals();}
{
collector.add_hl_symbol(token_info(provider.get_range($ORDSYMBOL), hl_scopes::data_attr_type));
$attribute = get_attribute($ORDSYMBOL->getText());
$data = std::move($mach_data_attribute_value.data);
$symbol_rng = provider.get_range($mach_data_attribute_value.ctx);
};
}
(
{ loctr_len_allowed($ORDSYMBOL.text) }? mach_location_counter
{
$data = (int)get_loctr_len();
}
|
mach_data_attribute_value
{
std::visit([&data = $data](auto&x){data=std::move(x);}, $mach_data_attribute_value.data);
$symbol_rng = provider.get_range($mach_data_attribute_value.ctx);
}
);

mach_data_attribute_value returns [std::variant<std::monostate, id_index, std::unique_ptr<mach_expr_literal>> data]
: literal
Expand All @@ -138,7 +151,6 @@ mach_data_attribute_value returns [std::variant<std::monostate, id_index, std::u
if (auto& lv = $literal.value; lv.has_value())
$data = std::make_unique<mach_expr_literal>(rng, std::move(lv.value()), $literal.text);
}
| mach_location_counter
| id
{
collector.add_hl_symbol(token_info(provider.get_range($id.ctx), hl_scopes::ordinary_symbol));
Expand Down
12 changes: 12 additions & 0 deletions parser_library/src/parsing/parser_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "hlasmparser.h"
#include "lexing/token_stream.h"
#include "processing/context_manager.h"
#include "processing/op_code.h"

namespace hlasm_plugin::parser_library::parsing {

Expand Down Expand Up @@ -119,6 +120,17 @@ context::id_index parser_impl::parse_identifier(std::string value, range id_rang
return hlasm_ctx->ids().add(std::move(value));
}

size_t parser_impl::get_loctr_len() const
{
auto [_, opcode] = *proc_status;
return processing::processing_status_cache_key::generate_loctr_len(opcode.value);
}

bool parser_impl::loctr_len_allowed(const std::string& attr) const
{
return (attr == "L" || attr == "l") && proc_status.has_value();
}

void parser_impl::resolve_expression(expressions::ca_expr_ptr& expr, context::SET_t_enum type) const
{
expr->resolve_expression_tree(type);
Expand Down
2 changes: 2 additions & 0 deletions parser_library/src/parsing/parser_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ class parser_impl : public antlr4::Parser
self_def_t parse_self_def_term(const std::string& option, const std::string& value, range term_range);
context::data_attr_kind get_attribute(std::string attr_data);
context::id_index parse_identifier(std::string value, range id_range);
size_t get_loctr_len() const;
bool loctr_len_allowed(const std::string& attr) const;

void resolve_expression(expressions::ca_expr_ptr& expr, context::SET_t_enum type) const;
void resolve_expression(std::vector<expressions::ca_expr_ptr>& expr, context::SET_t_enum type) const;
Expand Down
17 changes: 17 additions & 0 deletions parser_library/src/processing/op_code.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,27 @@ inline unsigned char get_reladdr_bitmask(context::id_index id)
return 0;
}

// Generates value of L'* expression
unsigned char processing_status_cache_key::generate_loctr_len(context::id_index id)
{
if (id && !id->empty())
{
if (auto p_instr = context::instruction::machine_instructions.find(*id);
p_instr != context::instruction::machine_instructions.end())
return static_cast<unsigned char>(p_instr->second.size_for_alloc / 8);

if (auto p_mnemo = context::instruction::mnemonic_codes.find(*id);
p_mnemo != context::instruction::mnemonic_codes.end())
return static_cast<unsigned char>(p_mnemo->second.instruction->size_for_alloc / 8);
}
return 1;
}

processing_status_cache_key::processing_status_cache_key(const processing_status& s)
: form(s.first.form)
, occurence(s.first.occurence)
, is_alias(s.second.type == context::instruction_type::ASM && s.second.value && *s.second.value == "ALIAS")
, loctr_len(generate_loctr_len(s.second.value))
, rel_addr(get_reladdr_bitmask(s.second.value))
{}
} // namespace hlasm_plugin::parser_library::processing
7 changes: 5 additions & 2 deletions parser_library/src/processing/op_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,20 @@ class processing_status_cache_key
{
processing_form form;
operand_occurence occurence;
bool is_alias;
unsigned char is_alias : 1, loctr_len : 7;
unsigned char rel_addr;

public:
friend bool operator==(processing_status_cache_key l, processing_status_cache_key r)
{
return l.form == r.form && l.occurence == r.occurence && l.is_alias == r.is_alias && l.rel_addr == r.rel_addr;
return l.form == r.form && l.occurence == r.occurence && l.is_alias == r.is_alias && l.loctr_len == r.loctr_len
&& l.rel_addr == r.rel_addr;
}
friend bool operator!=(processing_status_cache_key l, processing_status_cache_key r) { return !(l == r); }

explicit processing_status_cache_key(const processing_status& s);

static unsigned char generate_loctr_len(context::id_index id);
};

} // namespace hlasm_plugin::parser_library::processing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,17 +489,9 @@ LZ EQU *-Z
a.collect_diags();
EXPECT_EQ(a.diags().size(), (size_t)0);

auto LX = a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("LX"));
auto LY = a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("LY"));
auto LZ = a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("LZ"));

ASSERT_TRUE(LX && LX->value().value_kind() == context::symbol_value_kind::ABS);
ASSERT_TRUE(LY && LY->value().value_kind() == context::symbol_value_kind::ABS);
ASSERT_TRUE(LZ && LZ->value().value_kind() == context::symbol_value_kind::ABS);

EXPECT_EQ(LX->value().get_abs(), 24);
EXPECT_EQ(LY->value().get_abs(), 6);
EXPECT_EQ(LZ->value().get_abs(), 15);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "LX"), 24);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "LY"), 6);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "LZ"), 15);
}

TEST(data_definition, no_loctr_ref)
Expand Down
32 changes: 29 additions & 3 deletions parser_library/test/common_testing.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,37 @@ inline const section* get_section(hlasm_context& ctx, std::string name)

inline const symbol* get_symbol(hlasm_context& ctx, std::string name)
{
auto sect = ctx.ids().find(std::move(name));
if (!sect)
auto symbol = ctx.ids().find(std::move(name));
if (!symbol)
return nullptr;

return ctx.ord_ctx.get_symbol(sect);
return ctx.ord_ctx.get_symbol(symbol);
}

inline std::optional<symbol_value::abs_value_t> get_symbol_abs(hlasm_context& ctx, std::string name)
{
auto symbol = ctx.ids().find(std::move(name));
if (!symbol)
return std::nullopt;

auto s = ctx.ord_ctx.get_symbol(symbol);
if (!s || s->kind() != symbol_value_kind::ABS)
return std::nullopt;

return s->value().get_abs();
}

inline std::optional<symbol_value::reloc_value_t> get_symbol_reloc(hlasm_context& ctx, std::string name)
{
auto symbol = ctx.ids().find(std::move(name));
if (!symbol)
return std::nullopt;

auto s = ctx.ord_ctx.get_symbol(symbol);
if (!s || s->kind() != symbol_value_kind::RELOC)
return std::nullopt;

return s->value().get_reloc();
}

#endif
77 changes: 43 additions & 34 deletions parser_library/test/context/data_attribute_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,9 @@ C LOCTR
analyzer a(input);
a.analyze();

EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("A"))->attributes().type(),
ebcdic_encoding::a2e[U'I']);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("B"))->attributes().type(),
ebcdic_encoding::a2e[U'J']);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("C"))->attributes().type(),
ebcdic_encoding::a2e[U'J']);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "A")->attributes().type(), ebcdic_encoding::a2e[U'I']);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "B")->attributes().type(), ebcdic_encoding::a2e[U'J']);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "C")->attributes().type(), ebcdic_encoding::a2e[U'J']);

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
Expand Down Expand Up @@ -373,8 +370,8 @@ B EQU L'LBL
analyzer a(input);
a.analyze();

EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("A"))->value().get_abs(), 1);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("B"))->value().get_abs(), 2);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "A"), 1);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "B"), 2);

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
Expand Down Expand Up @@ -414,7 +411,7 @@ B EQU S'A
analyzer a(input);
a.analyze();

EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("B"))->value().get_abs(), 12);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "B"), 12);

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
Expand Down Expand Up @@ -451,16 +448,11 @@ EXTEND DC LS10'5.312'
analyzer a(input);
a.analyze();

EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("HALFCON"))->attributes().integer(),
(symbol_attributes::len_attr)9);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("ONECON"))->attributes().integer(),
(symbol_attributes::len_attr)23);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("SHORT"))->attributes().integer(),
(symbol_attributes::len_attr)4);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("LONG"))->attributes().integer(),
(symbol_attributes::len_attr)9);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("EXTEND"))->attributes().integer(),
(symbol_attributes::len_attr)18);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "HALFCON")->attributes().integer(), (symbol_attributes::len_attr)9);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "ONECON")->attributes().integer(), (symbol_attributes::len_attr)23);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "SHORT")->attributes().integer(), (symbol_attributes::len_attr)4);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "LONG")->attributes().integer(), (symbol_attributes::len_attr)9);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "EXTEND")->attributes().integer(), (symbol_attributes::len_attr)18);

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
Expand All @@ -476,7 +468,7 @@ X EQU I'HALFCON
analyzer a(input);
a.analyze();

EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("X"))->value().get_abs(), 9);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "X"), 9);

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
Expand Down Expand Up @@ -597,9 +589,8 @@ B EQU T'W
analyzer a(input);
a.analyze();

EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("A"))->value().get_abs(), 1);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("B"))->value().get_abs(),
symbol_attributes::undef_type);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "A"), 1);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "B"), symbol_attributes::undef_type);

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
Expand All @@ -619,8 +610,8 @@ W EQU 4,5,6
analyzer a(input);
a.analyze();

EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("A"))->value().get_abs(), 2);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("B"))->value().get_abs(), 6);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "A"), 2);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "B"), 6);

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
Expand All @@ -641,8 +632,7 @@ B EQU 1,11
a.analyze();

EXPECT_EQ(get_var_value<A_t>(a.hlasm_ctx(), "V1"), 1);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("A"))->attributes().length(),
(symbol_attributes::len_attr)1);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "A")->attributes().length(), (symbol_attributes::len_attr)1);

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
Expand Down Expand Up @@ -677,12 +667,10 @@ B EQU L'A
ASSERT_TRUE(a.hlasm_ctx().ord_ctx.symbol_defined(a.hlasm_ctx().ids().add("A")));
ASSERT_TRUE(a.hlasm_ctx().ord_ctx.symbol_defined(a.hlasm_ctx().ids().add("B")));

EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("A"))->value().get_abs(), 11);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("A"))->attributes().length(),
(symbol_attributes::len_attr)11);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("B"))->value().get_abs(), 11);
EXPECT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("B"))->attributes().length(),
(symbol_attributes::len_attr)1);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "A"), 11);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "A")->attributes().length(), (symbol_attributes::len_attr)11);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "B"), 11);
EXPECT_EQ(get_symbol(a.hlasm_ctx(), "B")->attributes().length(), (symbol_attributes::len_attr)1);

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
Expand All @@ -703,7 +691,7 @@ C EQU 1,12
analyzer a(input);
a.analyze();

ASSERT_EQ(a.hlasm_ctx().ord_ctx.get_symbol(a.hlasm_ctx().ids().add("X"))->kind(), symbol_value_kind::ABS);
ASSERT_EQ(get_symbol(a.hlasm_ctx(), "X")->kind(), symbol_value_kind::ABS);

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
Expand All @@ -723,3 +711,24 @@ V EQU I'C
a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)1);
}

TEST(data_attributes, loctr_length)
{
std::string input = R"(
X1 DS (L'*)C
A EQU *-X1
X2 DC (L'*)C' '
B EQU *-X2
C EQU L'*
)";

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

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

EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "A"), 1);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "B"), 1);
EXPECT_EQ(get_symbol_abs(a.hlasm_ctx(), "C"), 1);
}
Loading

0 comments on commit c2d64c9

Please sign in to comment.