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: Various fixes #166

Merged
merged 17 commits into from
Aug 20, 2021
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
2 changes: 1 addition & 1 deletion parser_library/src/context/hlasm_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ C_t hlasm_context::get_type_attr(var_sym_ptr var_symbol, const std::vector<size_
if (offset.empty())
value = setc_sym->get_value();
else
value = setc_sym->get_value(offset.front());
value = setc_sym->get_value(offset.front() - 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a unit test?

}
else if (auto mac_par = var_symbol->access_macro_param_base())
{
Expand Down
16 changes: 8 additions & 8 deletions parser_library/src/context/instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,8 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions()
add_machine_instr(result, "CVDY", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 715);
add_machine_instr(result, "CVDG", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 715);
add_machine_instr(result, "CU24", mach_format::RRF_c, { reg_4_U, reg_4_U, mask_4_U }, 1, 715);
add_machine_instr(result, "CUUTF", mach_format::RRF_c, { reg_4_U, reg_4_U, mask_4_U }, 718);
add_machine_instr(result, "CU21", mach_format::RRF_c, { reg_4_U, reg_4_U, mask_4_U }, 718);
add_machine_instr(result, "CUUTF", mach_format::RRF_c, { reg_4_U, reg_4_U, mask_4_U }, 1, 718);
add_machine_instr(result, "CU21", mach_format::RRF_c, { reg_4_U, reg_4_U, mask_4_U }, 1, 718);
add_machine_instr(result, "CU42", mach_format::RRE, { reg_4_U, reg_4_U }, 722);
add_machine_instr(result, "CU41", mach_format::RRE, { reg_4_U, reg_4_U }, 725);
add_machine_instr(result, "CUTFU", mach_format::RRF_c, { reg_4_U, reg_4_U, mask_4_U }, 1, 728);
Expand Down Expand Up @@ -589,11 +589,11 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions()
add_machine_instr(result, "LLGHRL", mach_format::RIL_b, { reg_4_U, rel_addr_imm_32_S }, 764);
add_machine_instr(result, "LLHH", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 765);
add_machine_instr(result, "LLIHF", mach_format::RIL_a, { reg_4_U, imm_32_S }, 765);
add_machine_instr(result, "LLIHH", mach_format::RI_a, { reg_4_U, imm_16_S }, 765);
add_machine_instr(result, "LLIHL", mach_format::RI_a, { reg_4_U, imm_16_S }, 765);
add_machine_instr(result, "LLIHH", mach_format::RI_a, { reg_4_U, imm_16_U }, 765);
add_machine_instr(result, "LLIHL", mach_format::RI_a, { reg_4_U, imm_16_U }, 765);
add_machine_instr(result, "LLILF", mach_format::RIL_a, { reg_4_U, imm_32_S }, 765);
add_machine_instr(result, "LLILH", mach_format::RI_a, { reg_4_U, imm_16_S }, 765);
add_machine_instr(result, "LLILL", mach_format::RI_a, { reg_4_U, imm_16_S }, 765);
add_machine_instr(result, "LLILH", mach_format::RI_a, { reg_4_U, imm_16_U }, 765);
add_machine_instr(result, "LLILL", mach_format::RI_a, { reg_4_U, imm_16_U }, 765);
add_machine_instr(result, "LLGTR", mach_format::RRE, { reg_4_U, reg_4_U }, 765);
add_machine_instr(result, "LLGT", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 766);
add_machine_instr(result, "LLGTAT", mach_format::RXY_a, { reg_4_U, dxb_20_4x4_S }, 766);
Expand Down Expand Up @@ -962,8 +962,8 @@ hlasm_plugin::parser_library::context::instruction::get_machine_instructions()
add_machine_instr(result, "STPX", mach_format::S, { db_12_4_U }, 1121);
add_machine_instr(result, "STRAG", mach_format::SSE, { db_12_4_U, db_12_4_U }, 1121);
add_machine_instr(result, "STSI", mach_format::S, { db_12_4_U }, 1122);
add_machine_instr(result, "STOSM", mach_format::SI, { db_12_4_U, imm_8_S }, 1146);
add_machine_instr(result, "STNSM", mach_format::SI, { db_12_4_U, imm_8_S }, 1146);
add_machine_instr(result, "STOSM", mach_format::SI, { db_12_4_U, imm_8_U }, 1146);
add_machine_instr(result, "STNSM", mach_format::SI, { db_12_4_U, imm_8_U }, 1146);
add_machine_instr(result, "STURA", mach_format::RRE, { reg_4_U, reg_4_U }, 1147);
add_machine_instr(result, "STURG", mach_format::RRE, { reg_4_U, reg_4_U }, 1147);
add_machine_instr(result, "TAR", mach_format::RRE, { reg_4_U, reg_4_U }, 1147);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ symbol_attributes symbol_attributes::make_ccw_attrs()
return symbol_attributes(symbol_origin::ASM, ebcdic_encoding::to_ebcdic('W'), 8);
}

symbol_attributes hlasm_plugin::parser_library::context::symbol_attributes::make_cnop_attrs()
{
return symbol_attributes(symbol_origin::ASM, ebcdic_encoding::to_ebcdic('I'));
}

data_attr_kind symbol_attributes::transform_attr(unsigned char c)
{
c = (char)std::toupper(c);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct symbol_attributes
static symbol_attributes make_wxtrn_attrs();
static symbol_attributes make_org_attrs();
static symbol_attributes make_ccw_attrs();
static symbol_attributes make_cnop_attrs();

// helper function to transform char to enum
static data_attr_kind transform_attr(unsigned char c);
Expand Down
20 changes: 14 additions & 6 deletions parser_library/src/lexing/lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,24 +465,29 @@ bool lexer::is_ord_char() const { return ord_char(input_state_->c); }

bool lexer::is_space() const { return input_state_->c == ' ' || input_state_->c == '\n' || input_state_->c == '\r'; }

bool lexer::is_data_attribute() const
bool lexer::is_consuming_data_attribute() const
{
// Although there are more data attributes (N, K, D), only these 5 consume the apostrophe right away, so that it
// cannot denote the beginning of string
auto tmp = std::toupper(input_state_->c);
return tmp == 'D' || tmp == 'O' || tmp == 'N' || tmp == 'S' || tmp == 'K' || tmp == 'I' || tmp == 'L' || tmp == 'T';
return tmp == 'O' || tmp == 'S' || tmp == 'I' || tmp == 'L' || tmp == 'T';
}

void lexer::lex_word()
{
bool last_char_data_attr = false;
bool ord = is_ord_char() && (input_state_->c < '0' || input_state_->c > '9');
bool num = (input_state_->c >= '0' && input_state_->c <= '9');

size_t last_part_ord_len = 0;
size_t w_len = 0;
while (!is_space() && !eof() && !identifier_divider() && before_end())
{
ord &= is_ord_char();
bool curr_ord = is_ord_char();
last_part_ord_len = curr_ord ? last_part_ord_len + 1 : 0;
ord &= curr_ord;

num &= (input_state_->c >= '0' && input_state_->c <= '9');
last_char_data_attr = is_data_attribute();
last_char_data_attr = is_consuming_data_attribute();

if (creating_var_symbol_ && !ord && w_len > 0 && w_len <= 63)
{
Expand All @@ -503,7 +508,10 @@ void lexer::lex_word()
else
create_token(IDENTIFIER);

if (input_state_->c == '\'' && last_char_data_attr && !var_sym_tmp && w_len == 1
// We generate the ATTR token even when we created identifier, but it ends with exactly one ordinary symbol which is
// also data attr symbol. That is because macro parameter "L'ORD must generate ATTR as string cannot start
// with the apostrophe
if (input_state_->c == '\'' && last_char_data_attr && !var_sym_tmp && last_part_ord_len == 1
&& (unlimited_line_ || input_state_->char_position_in_line != end_))
{
start_token();
Expand Down
2 changes: 1 addition & 1 deletion parser_library/src/lexing/lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class lexer final : public antlr4::TokenSource
// is next input char an ord char?
bool is_ord_char() const;
bool is_space() const;
bool is_data_attribute() const;
bool is_consuming_data_attribute() const;
void set_unlimited_line(bool unlimited_lines);
// set lexer's input state to file position
void set_file_offset(position file_offset, bool process_allowed = false);
Expand Down
4 changes: 2 additions & 2 deletions parser_library/src/parsing/grammar/ca_expr_rules.g4
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ var_symbol returns [vs_ptr vs]
| created_set_symbol {$vs = std::move($created_set_symbol.vs);};

data_attribute returns [context::data_attr_kind attribute, std::variant<context::id_index, semantics::vs_ptr> value, range value_range]
: ORDSYMBOL attr data_attribute_value
: ORDSYMBOL (attr|apostrophe_as_attr) data_attribute_value
{
collector.add_hl_symbol(token_info(provider.get_range( $ORDSYMBOL), hl_scopes::data_attr_type));
collector.add_hl_symbol(token_info(provider.get_range($ORDSYMBOL), hl_scopes::data_attr_type));
$attribute = get_attribute($ORDSYMBOL->getText());
$value = std::move($data_attribute_value.value);
$value_range = provider.get_range( $data_attribute_value.ctx);
Expand Down
10 changes: 6 additions & 4 deletions parser_library/src/parsing/grammar/hlasmparser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,13 @@ comma
: COMMA {collector.add_hl_symbol(token_info(provider.get_range( $COMMA),hl_scopes::operator_symbol)); };
dot
: DOT {collector.add_hl_symbol(token_info(provider.get_range( $DOT),hl_scopes::operator_symbol)); };
apostrophe
: APOSTROPHE ;
attr
apostrophe
: APOSTROPHE;
attr
: ATTR {collector.add_hl_symbol(token_info(provider.get_range( $ATTR),hl_scopes::operator_symbol)); };
lpar
apostrophe_as_attr
: APOSTROPHE {collector.add_hl_symbol(token_info(provider.get_range($APOSTROPHE),hl_scopes::operator_symbol)); };
lpar
: LPAR { collector.add_hl_symbol(token_info(provider.get_range( $LPAR),hl_scopes::operator_symbol)); };
rpar
: RPAR {collector.add_hl_symbol(token_info(provider.get_range( $RPAR),hl_scopes::operator_symbol)); };
Expand Down
4 changes: 2 additions & 2 deletions parser_library/src/parsing/grammar/machine_expr_rules.g4
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ literal
: equals data_def;

mach_data_attribute returns [std::string attribute, id_index data = nullptr, range symbol_rng]
: ORDSYMBOL attr mach_data_attribute_value
: ORDSYMBOL (attr|apostrophe_as_attr) mach_data_attribute_value
{
collector.add_hl_symbol(token_info(provider.get_range( $ORDSYMBOL), hl_scopes::data_attr_type));
collector.add_hl_symbol(token_info(provider.get_range($ORDSYMBOL), hl_scopes::data_attr_type));
$attribute = $ORDSYMBOL->getText();
$data = $mach_data_attribute_value.data;
$symbol_rng = provider.get_range( $mach_data_attribute_value.ctx);
Expand Down
43 changes: 43 additions & 0 deletions parser_library/src/processing/instruction_sets/asm_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,14 @@ void asm_processor::process_external(rebuilt_statement stmt, external_type t)
}
}

std::optional<context::A_t> asm_processor::try_get_abs_value(const semantics::operand* op) const
{
auto expr_op = dynamic_cast<const semantics::simple_expr_operand*>(op);
if (!expr_op)
return std::nullopt;
return try_get_abs_value(expr_op);
}

std::optional<context::A_t> asm_processor::try_get_abs_value(const semantics::simple_expr_operand* op) const
{
if (op->has_dependencies(hlasm_ctx.ord_ctx))
Expand Down Expand Up @@ -632,6 +640,7 @@ asm_processor::process_table_t asm_processor::create_table(context::hlasm_contex
table.emplace(h_ctx.ids().add("CCW"), [this](rebuilt_statement stmt) { process_CCW(std::move(stmt)); });
table.emplace(h_ctx.ids().add("CCW0"), [this](rebuilt_statement stmt) { process_CCW(std::move(stmt)); });
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)); });

return table;
}
Expand Down Expand Up @@ -722,4 +731,38 @@ void asm_processor::process_CCW(rebuilt_statement stmt)
check(stmt, hlasm_ctx, checker_, *this);
}

void asm_processor::process_CNOP(rebuilt_statement stmt)
{
constexpr context::alignment CNOP_symbol_align = context::halfword;

fill_expression_loc_counters(stmt, CNOP_symbol_align);
find_sequence_symbol(stmt);

if (auto label = find_label_symbol(stmt); label != context::id_storage::empty_id)
{
if (hlasm_ctx.ord_ctx.symbol_defined(label))
add_diagnostic(diagnostic_op::error_E031("symbol", stmt.label_ref().field_range));
else
create_symbol(stmt.stmt_range_ref(),
label,
hlasm_ctx.ord_ctx.align(CNOP_symbol_align),
context::symbol_attributes::make_cnop_attrs());
}

check(stmt, hlasm_ctx, checker_, *this);

if (stmt.operands_ref().value.size() != 2)
return;


std::optional<int> byte_value = try_get_abs_value(stmt.operands_ref().value[0].get());
std::optional<int> boundary_value = try_get_abs_value(stmt.operands_ref().value[1].get());
// For now, the implementation ignores the instruction, if the operands have dependencies. Most uses of this
// instruction should by covered anyway. It will still generate the label correctly.
if (!byte_value.has_value() || !boundary_value.has_value())
return;

hlasm_ctx.ord_ctx.reserve_storage_area(0, context::alignment { (size_t)*byte_value, (size_t)*boundary_value });
}

} // namespace hlasm_plugin::parser_library::processing
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ class asm_processor : public low_language_processor
void process_OPSYN(rebuilt_statement stmt);
void process_AINSERT(rebuilt_statement stmt);
void process_CCW(rebuilt_statement stmt);
void process_CNOP(rebuilt_statement stmt);

template<checking::data_instr_type instr_type>
void process_data_instruction(rebuilt_statement stmt);

std::optional<context::A_t> try_get_abs_value(const semantics::operand* op) const;
std::optional<context::A_t> try_get_abs_value(const semantics::simple_expr_operand* op) const;

enum class external_type
Expand Down
37 changes: 33 additions & 4 deletions parser_library/test/context/data_attribute_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,19 +287,48 @@ TEST(data_attributes, T_macro_params)
TEST(data_attributes, T_var_to_ord_syms)
{
std::string input = R"(
LAB LR 1,1
&v1 setc 'LAB'
LAB LR 1,1
SYMC DC C''
SYMA DC A(0)

&v1 SETC 'LAB'
&arr(1) SETC 'SYMC','SYMA'

&t1 SETC t'&v1
&t2 SETC t'&arr(1)
&t3 SETC t'&arr(2)

&t1 setc t'&v1
)";

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

EXPECT_EQ(get_var_value<C_t>(a.hlasm_ctx(), "T1"), "I");
EXPECT_EQ(get_var_value<C_t>(a.hlasm_ctx(), "T2"), "C");
EXPECT_EQ(get_var_value<C_t>(a.hlasm_ctx(), "T3"), "A");

a.collect_diags();
ASSERT_EQ(a.diags().size(), (size_t)0);
ASSERT_EQ(a.diags().size(), 0U);
}

TEST(data_attributes, T_var_zero_subscript)
{
std::string input = R"(
SYMC DC C''
SYMA DC A(0)

&arr(1) SETC 'SYMC','SYMA'

&t1 SETC t'&arr(0)

)";

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

a.collect_diags();
ASSERT_EQ(a.diags().size(), 1U);
EXPECT_EQ(a.diags()[0].code, "E012");
}

TEST(data_attributes, D)
Expand Down
87 changes: 86 additions & 1 deletion parser_library/test/parsing/string_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,89 @@ TEST(parser, ca_string_double_ampersand)
auto it = ctx.ids().find("A");

ASSERT_EQ(ctx.get_var_sym(it)->access_set_symbol_base()->access_set_symbol<context::C_t>()->get_value(), "&&");
}
}

namespace {

struct test_param
{
std::string name;
std::string parameter;
std::string expected;
};

struct stringer
{
std::string operator()(::testing::TestParamInfo<test_param> p) { return p.param.name; }
};

class parser_string_fixture : public ::testing::TestWithParam<test_param>
{};

INSTANTIATE_TEST_SUITE_P(parser,
parser_string_fixture,
::testing::Values(test_param { "A_no_attr", "A'SYM 93'", "A'SYM 93'" },
test_param { "D_attr", "D'SYM 93'", "D'SYM 93'" },
test_param { "I_attr", "I'SYM 93'", "I'SYM" },
test_param { "K_attr", "K'SYM 93'", "K'SYM 93'" },
test_param { "L_attr", "L'SYM 93'", "L'SYM" },
test_param { "N_attr", "N'SYM 93'", "N'SYM 93'" },
test_param { "O_attr", "O'SYM 93'", "O'SYM" },
test_param { "S_attr", "S'SYM 93'", "S'SYM" },
test_param { "T_attr", "T'SYM 93'", "T'SYM" },
test_param { "attr_and_string", "S'SYM' STH'", "S'SYM' STH'" },
test_param { "literal_FD", "=FD'SYM STH'", "=FD'SYM STH'" },
test_param { "literal_FS", "=FS'SYM STH'", "=FS'SYM STH'" },
test_param { "number_before_attr_L", "=4L'SYM 93'", "=4L'SYM 93'" },
test_param { "quote_before_attr_L", "\"L'SYM 93'", "\"L'SYM" },
test_param { "quote_before_attr_D", "\"D'SYM 93'", "\"D'SYM 93'" },

// Invalid inputs are currently parsed as remark, therefore the variable symbol is empty.
test_param { "no_ending_apostrophe", "\"N'SYM", "" },
test_param { "no_ending_apostrophe_2", "\"L'SYM' STH", "" }),
stringer());
} // namespace

TEST_P(parser_string_fixture, basic)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add also negative tests?

{
std::string input = R"(
GBLC &PAR
MACRO
MAC &VAR
GBLC &PAR
&PAR SETC &VAR
MEND

MAC )" + GetParam().parameter;
analyzer a(input);
a.analyze();

a.collect_diags();
EXPECT_EQ(a.diags().size(), 0U);

auto par_value = get_var_value<C_t>(a.hlasm_ctx(), "PAR");
ASSERT_TRUE(par_value.has_value());
EXPECT_EQ(*par_value, GetParam().expected);
}


TEST(parser, incomplete_string)
{
std::string input = R"(
GBLC &PAR
MACRO
MAC &VAR
GBLC &PAR
&PAR SETC &VAR
MEND

MAC 'A 93)";
analyzer a(input);
a.analyze();

a.collect_diags();
EXPECT_EQ(a.diags().size(), 0U);

auto par_value = get_var_value<C_t>(a.hlasm_ctx(), "PAR");
ASSERT_TRUE(par_value.has_value());
}
Loading