diff --git a/parser_library/src/analyzer.cpp b/parser_library/src/analyzer.cpp index cd7ab877c..be1ac8b7d 100644 --- a/parser_library/src/analyzer.cpp +++ b/parser_library/src/analyzer.cpp @@ -47,7 +47,7 @@ analyzer::analyzer(const std::string& text, *parser_, tracer) { - parser_->initialize(&hlasm_ctx_ref_, &lsp_proc_); + parser_->initialize(&hlasm_ctx_ref_, &lsp_proc_, &lib_provider, &mngr_); parser_->setErrorHandler(std::make_shared()); parser_->removeErrorListeners(); parser_->addErrorListener(&listener_); diff --git a/parser_library/src/context/hlasm_context.cpp b/parser_library/src/context/hlasm_context.cpp index a608a2901..267921e33 100644 --- a/parser_library/src/context/hlasm_context.cpp +++ b/parser_library/src/context/hlasm_context.cpp @@ -19,6 +19,7 @@ #include "ebcdic_encoding.h" #include "expressions/conditional_assembly/terms/ca_constant.h" +#include "expressions/conditional_assembly/terms/ca_symbol_attribute.h" #include "instruction.h" namespace hlasm_plugin::parser_library::context { @@ -262,6 +263,45 @@ void hlasm_context::set_source_indices(size_t begin_index, size_t end_index, siz source_stack_.back().end_line = end_line; } +std::pair hlasm_context::get_begin_snapshot(bool ignore_macros) const +{ + context::source_position statement_position; + + bool is_in_macros = ignore_macros ? false : scope_stack_.size() > 1; + + if (!is_in_macros && current_copy_stack().empty()) + { + statement_position.file_offset = current_source().begin_index; + statement_position.file_line = current_source().current_instruction.pos.line; + } + else + { + statement_position.file_offset = current_source().end_index; + statement_position.file_line = current_source().end_line + 1; + } + + context::source_snapshot snapshot = current_source().create_snapshot(); + + if (snapshot.copy_frames.size() && is_in_macros) + ++snapshot.copy_frames.back().statement_offset; + + return std::make_pair(std::move(statement_position), std::move(snapshot)); +} + +std::pair hlasm_context::get_end_snapshot() const +{ + context::source_position statement_position; + statement_position.file_offset = current_source().end_index; + statement_position.file_line = current_source().end_line + 1; + + context::source_snapshot snapshot = current_source().create_snapshot(); + + if (snapshot.copy_frames.size()) + ++snapshot.copy_frames.back().statement_offset; + + return std::make_pair(std::move(statement_position), std::move(snapshot)); +} + void hlasm_context::push_statement_processing(const processing::processing_kind kind) { assert(!proc_stack_.empty()); @@ -322,6 +362,11 @@ const std::deque& hlasm_context::scope_stack() const { return scope_ const source_context& hlasm_context::current_source() const { return source_stack_.back(); } +const std::vector& hlasm_context::current_copy_stack() const +{ + return source_stack_.back().copy_stack; +} + std::vector& hlasm_context::current_copy_stack() { return source_stack_.back().copy_stack; } std::vector hlasm_context::whole_copy_stack() const @@ -366,11 +411,8 @@ var_sym_ptr hlasm_context::get_var_sym(id_index name) void hlasm_context::add_sequence_symbol(sequence_symbol_ptr seq_sym) { - if (curr_scope()->is_in_macro()) - throw std::runtime_error("adding sequence symbols to macro definition not allowed"); - - if (curr_scope()->sequence_symbols.find(seq_sym->name) == curr_scope()->sequence_symbols.end()) - curr_scope()->sequence_symbols.emplace(seq_sym->name, std::move(seq_sym)); + auto& opencode = scope_stack_.front(); + opencode.sequence_symbols.try_emplace(seq_sym->name, std::move(seq_sym)); } const sequence_symbol* hlasm_context::get_sequence_symbol(id_index name) const @@ -394,6 +436,14 @@ const sequence_symbol* hlasm_context::get_sequence_symbol(id_index name) const return nullptr; } +const sequence_symbol* hlasm_context::get_opencode_sequence_symbol(id_index name) const +{ + if (const auto& sym = scope_stack_.front().sequence_symbols.find(name); + sym != scope_stack_.front().sequence_symbols.end()) + return sym->second.get(); + return nullptr; +} + void hlasm_context::set_branch_counter(A_t value) { curr_scope()->branch_counter = value; @@ -541,6 +591,8 @@ C_t hlasm_context::get_type_attr(var_sym_ptr var_symbol, const std::vector get_begin_snapshot(bool ignore_macros) const; + std::pair get_end_snapshot() const; + // pushes new kind of statement processing void push_statement_processing(const processing::processing_kind kind); // pushes new kind of statement processing as well as new source @@ -107,6 +110,7 @@ class hlasm_context // gets macro nest const std::deque& scope_stack() const; // gets copy nest of current statement processing + const std::vector& current_copy_stack() const; std::vector& current_copy_stack(); // gets names of whole copy nest std::vector whole_copy_stack() const; @@ -139,6 +143,9 @@ class hlasm_context // return sequence symbol in current scope // returns nullptr if there is none in the current scope const sequence_symbol* get_sequence_symbol(id_index name) const; + // return opencode sequence symbol + // returns nullptr if there is none + const sequence_symbol* get_opencode_sequence_symbol(id_index name) const; void set_branch_counter(A_t value); A_t get_branch_counter() const; @@ -205,7 +212,7 @@ class hlasm_context return glob->second; } - set_sym_ptr val(std::make_shared>(id, is_scalar, true)); + auto val = std::make_shared>(id, is_scalar, true); globals_.insert({ id, val }); curr_scope()->variables.insert({ id, val }); diff --git a/parser_library/src/context/ordinary_assembly/ordinary_assembly_context.cpp b/parser_library/src/context/ordinary_assembly/ordinary_assembly_context.cpp index 5580bbd06..94517bb00 100644 --- a/parser_library/src/context/ordinary_assembly/ordinary_assembly_context.cpp +++ b/parser_library/src/context/ordinary_assembly/ordinary_assembly_context.cpp @@ -19,8 +19,7 @@ #include "alignment.h" -using namespace hlasm_plugin::parser_library; -using namespace hlasm_plugin::parser_library::context; +namespace hlasm_plugin::parser_library::context { void ordinary_assembly_context::create_private_section() { @@ -55,6 +54,15 @@ bool ordinary_assembly_context::create_symbol( return ok; } +void ordinary_assembly_context::add_symbol_reference(symbol sym) { symbol_refs_.try_emplace(sym.name, std::move(sym)); } + +const symbol* ordinary_assembly_context::get_symbol_reference(context::id_index name) const +{ + auto tmp = symbol_refs_.find(name); + + return tmp == symbol_refs_.end() ? nullptr : &tmp->second; +} + const symbol* ordinary_assembly_context::get_symbol(id_index name) const { auto tmp = symbols_.find(name); @@ -255,4 +263,6 @@ std::pair ordinary_assembly_context::reserve_storage_area_sp return std::make_pair(ret_addr, sp); } return std::make_pair(curr_section_->current_location_counter().reserve_storage_area(length, align).first, nullptr); -} \ No newline at end of file +} + +} // namespace hlasm_plugin::parser_library::context diff --git a/parser_library/src/context/ordinary_assembly/ordinary_assembly_context.h b/parser_library/src/context/ordinary_assembly/ordinary_assembly_context.h index dd0488efc..37d1cee39 100644 --- a/parser_library/src/context/ordinary_assembly/ordinary_assembly_context.h +++ b/parser_library/src/context/ordinary_assembly/ordinary_assembly_context.h @@ -25,9 +25,7 @@ #include "symbol_dependency_tables.h" -namespace hlasm_plugin { -namespace parser_library { -namespace context { +namespace hlasm_plugin::parser_library::context { // class holding complete information about the 'ordinary assembly' (assembler and machine instructions) // it contains 'sections' ordinary 'symbols' and all dependencies between them @@ -37,6 +35,8 @@ class ordinary_assembly_context : public dependency_solver std::vector> sections_; // list of visited symbols std::unordered_map symbols_; + // list of lookaheaded symbols + std::unordered_map symbol_refs_; section* curr_section_; @@ -57,6 +57,9 @@ class ordinary_assembly_context : public dependency_solver [[nodiscard]] bool create_symbol( id_index name, symbol_value value, symbol_attributes attributes, location symbol_location); + void add_symbol_reference(symbol sym); + const symbol* get_symbol_reference(context::id_index name) const; + // gets symbol by name virtual const symbol* get_symbol(id_index name) const override; symbol* get_symbol(id_index name); @@ -111,7 +114,6 @@ class ordinary_assembly_context : public dependency_solver std::pair reserve_storage_area_space(size_t length, alignment align); }; -} // namespace context -} // namespace parser_library -} // namespace hlasm_plugin +} // namespace hlasm_plugin::parser_library::context + #endif \ No newline at end of file diff --git a/parser_library/src/context/ordinary_assembly/symbol_attributes.h b/parser_library/src/context/ordinary_assembly/symbol_attributes.h index 32a75fb1d..eb0349ae3 100644 --- a/parser_library/src/context/ordinary_assembly/symbol_attributes.h +++ b/parser_library/src/context/ordinary_assembly/symbol_attributes.h @@ -44,7 +44,8 @@ enum class symbol_origin SECT, MACH, EQU, - DAT + DAT, + UNKNOWN }; // structure wrapping attributes of the symbol diff --git a/parser_library/src/context/source_snapshot.h b/parser_library/src/context/source_snapshot.h index 9c023b0aa..d50cfc8cc 100644 --- a/parser_library/src/context/source_snapshot.h +++ b/parser_library/src/context/source_snapshot.h @@ -20,9 +20,7 @@ #include "id_storage.h" #include "range.h" -namespace hlasm_plugin { -namespace parser_library { -namespace context { +namespace hlasm_plugin::parser_library::context { // helper structure representing position in source file struct source_position @@ -69,6 +67,24 @@ struct source_snapshot size_t end_line; std::vector copy_frames; + source_snapshot() + : begin_index(0) + , end_index(0) + , end_line(0) + {} + + source_snapshot(location instruction, + size_t begin_index, + size_t end_index, + size_t end_line, + std::vector copy_frames) + : instruction(std::move(instruction)) + , begin_index(begin_index) + , end_index(end_index) + , end_line(end_line) + , copy_frames(std::move(copy_frames)) + {} + bool operator==(const source_snapshot& oth) const { if (!(end_line == oth.end_line && begin_index == oth.begin_index && end_index == oth.end_index @@ -83,7 +99,6 @@ struct source_snapshot } }; -} // namespace context -} // namespace parser_library -} // namespace hlasm_plugin +} // namespace hlasm_plugin::parser_library::context + #endif diff --git a/parser_library/src/expressions/conditional_assembly/ca_expression.h b/parser_library/src/expressions/conditional_assembly/ca_expression.h index 1e37d584a..ea2330ef0 100644 --- a/parser_library/src/expressions/conditional_assembly/ca_expression.h +++ b/parser_library/src/expressions/conditional_assembly/ca_expression.h @@ -40,7 +40,7 @@ class ca_expression : public diagnosable_op_impl ca_expression(context::SET_t_enum expr_kind, range expr_range); // retrieves set of attributed symbols that are not yet defined - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver& solver) const = 0; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const = 0; // builds parts of the expression tree that could not be built during parsing virtual void resolve_expression_tree(context::SET_t_enum kind) = 0; diff --git a/parser_library/src/expressions/conditional_assembly/ca_operator_binary.cpp b/parser_library/src/expressions/conditional_assembly/ca_operator_binary.cpp index 9ea96285b..744c37ccb 100644 --- a/parser_library/src/expressions/conditional_assembly/ca_operator_binary.cpp +++ b/parser_library/src/expressions/conditional_assembly/ca_operator_binary.cpp @@ -30,10 +30,10 @@ ca_binary_operator::ca_binary_operator( , right_expr(std::move(right_expr)) {} -undef_sym_set ca_binary_operator::get_undefined_attributed_symbols(const context::dependency_solver& solver) const +undef_sym_set ca_binary_operator::get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const { - auto tmp = left_expr->get_undefined_attributed_symbols(solver); - tmp.merge(right_expr->get_undefined_attributed_symbols(solver)); + auto tmp = left_expr->get_undefined_attributed_symbols(eval_ctx); + tmp.merge(right_expr->get_undefined_attributed_symbols(eval_ctx)); return tmp; } diff --git a/parser_library/src/expressions/conditional_assembly/ca_operator_binary.h b/parser_library/src/expressions/conditional_assembly/ca_operator_binary.h index 1564ef27f..bdccd653b 100644 --- a/parser_library/src/expressions/conditional_assembly/ca_operator_binary.h +++ b/parser_library/src/expressions/conditional_assembly/ca_operator_binary.h @@ -29,7 +29,7 @@ class ca_binary_operator : public ca_expression ca_binary_operator(ca_expr_ptr left_expr, ca_expr_ptr right_expr, context::SET_t_enum expr_kind, range expr_range); - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver& solver) const override; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const override; virtual void resolve_expression_tree(context::SET_t_enum kind) override; diff --git a/parser_library/src/expressions/conditional_assembly/ca_operator_unary.cpp b/parser_library/src/expressions/conditional_assembly/ca_operator_unary.cpp index ae9cba74a..91d037a54 100644 --- a/parser_library/src/expressions/conditional_assembly/ca_operator_unary.cpp +++ b/parser_library/src/expressions/conditional_assembly/ca_operator_unary.cpp @@ -27,9 +27,9 @@ ca_unary_operator::ca_unary_operator(ca_expr_ptr expr, context::SET_t_enum expr_ , expr(std::move(expr)) {} -undef_sym_set ca_unary_operator::get_undefined_attributed_symbols(const context::dependency_solver& solver) const +undef_sym_set ca_unary_operator::get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const { - return expr->get_undefined_attributed_symbols(solver); + return expr->get_undefined_attributed_symbols(eval_ctx); } void ca_unary_operator::resolve_expression_tree(context::SET_t_enum kind) diff --git a/parser_library/src/expressions/conditional_assembly/ca_operator_unary.h b/parser_library/src/expressions/conditional_assembly/ca_operator_unary.h index a5a8a4541..9e4fdee4b 100644 --- a/parser_library/src/expressions/conditional_assembly/ca_operator_unary.h +++ b/parser_library/src/expressions/conditional_assembly/ca_operator_unary.h @@ -27,7 +27,7 @@ class ca_unary_operator : public ca_expression ca_unary_operator(ca_expr_ptr expr, context::SET_t_enum expr_kind, range expr_range); - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver& solver) const override; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const override; virtual void resolve_expression_tree(context::SET_t_enum kind) override; diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_constant.cpp b/parser_library/src/expressions/conditional_assembly/terms/ca_constant.cpp index 0ff93217d..838dae316 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_constant.cpp +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_constant.cpp @@ -23,10 +23,7 @@ ca_constant::ca_constant(context::A_t value, range expr_range) , value(value) {} -undef_sym_set ca_constant::get_undefined_attributed_symbols(const context::dependency_solver&) const -{ - return undef_sym_set(); -} +undef_sym_set ca_constant::get_undefined_attributed_symbols(const evaluation_context&) const { return undef_sym_set(); } void ca_constant::resolve_expression_tree(context::SET_t_enum kind) { diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_constant.h b/parser_library/src/expressions/conditional_assembly/terms/ca_constant.h index 415dfb49e..000feabfd 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_constant.h +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_constant.h @@ -32,7 +32,7 @@ class ca_constant : public ca_expression ca_constant(context::A_t value, range expr_range); - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver& solver) const override; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const override; virtual void resolve_expression_tree(context::SET_t_enum kind) override; diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_expr_list.cpp b/parser_library/src/expressions/conditional_assembly/terms/ca_expr_list.cpp index 996f000ef..a15537417 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_expr_list.cpp +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_expr_list.cpp @@ -28,11 +28,11 @@ ca_expr_list::ca_expr_list(std::vector expr_list, range expr_range) , expr_list(std::move(expr_list)) {} -undef_sym_set ca_expr_list::get_undefined_attributed_symbols(const context::dependency_solver& solver) const +undef_sym_set ca_expr_list::get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const { undef_sym_set tmp; for (auto&& expr : expr_list) - tmp.merge(expr->get_undefined_attributed_symbols(solver)); + tmp.merge(expr->get_undefined_attributed_symbols(eval_ctx)); return tmp; } diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_expr_list.h b/parser_library/src/expressions/conditional_assembly/terms/ca_expr_list.h index 2dbfa9efe..5e8d5ac8e 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_expr_list.h +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_expr_list.h @@ -30,7 +30,7 @@ class ca_expr_list : public ca_expression ca_expr_list(std::vector expr_list, range expr_range); - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver& solver) const override; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const override; virtual void resolve_expression_tree(context::SET_t_enum kind) override; diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_function.cpp b/parser_library/src/expressions/conditional_assembly/terms/ca_function.cpp index 3ce798363..fcfc0f85c 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_function.cpp +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_function.cpp @@ -45,13 +45,13 @@ ca_function::ca_function(context::id_index function_name, , duplication_factor(std::move(duplication_factor)) {} -undef_sym_set ca_function::get_undefined_attributed_symbols(const context::dependency_solver& solver) const +undef_sym_set ca_function::get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const { undef_sym_set ret; for (auto&& expr : parameters) - ret.merge(expr->get_undefined_attributed_symbols(solver)); + ret.merge(expr->get_undefined_attributed_symbols(eval_ctx)); if (duplication_factor) - ret.merge(duplication_factor->get_undefined_attributed_symbols(solver)); + ret.merge(duplication_factor->get_undefined_attributed_symbols(eval_ctx)); return ret; } diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_function.h b/parser_library/src/expressions/conditional_assembly/terms/ca_function.h index d5f84a791..77326a009 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_function.h +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_function.h @@ -40,7 +40,7 @@ class ca_function : public ca_expression ca_expr_ptr duplication_factor, range expr_range); - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver& solver) const override; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const override; virtual void resolve_expression_tree(context::SET_t_enum kind) override; diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_string.cpp b/parser_library/src/expressions/conditional_assembly/terms/ca_string.cpp index 5cd1c4100..391d49418 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_string.cpp +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_string.cpp @@ -32,15 +32,15 @@ ca_string::ca_string( , substring(std::move(substring)) {} -undef_sym_set ca_string::get_undefined_attributed_symbols(const context::dependency_solver& solver) const +undef_sym_set ca_string::get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const { undef_sym_set tmp; if (duplication_factor) - tmp = duplication_factor->get_undefined_attributed_symbols(solver); + tmp = duplication_factor->get_undefined_attributed_symbols(eval_ctx); if (substring.start) - tmp.merge(substring.start->get_undefined_attributed_symbols(solver)); + tmp.merge(substring.start->get_undefined_attributed_symbols(eval_ctx)); if (substring.count) - tmp.merge(substring.count->get_undefined_attributed_symbols(solver)); + tmp.merge(substring.count->get_undefined_attributed_symbols(eval_ctx)); return tmp; } diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_string.h b/parser_library/src/expressions/conditional_assembly/terms/ca_string.h index f21584254..30ae7dd36 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_string.h +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_string.h @@ -39,7 +39,7 @@ class ca_string : public ca_expression ca_string(semantics::concat_chain value, ca_expr_ptr duplication_factor, substring_t substring, range expr_range); - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver& solver) const override; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const override; virtual void resolve_expression_tree(context::SET_t_enum kind) override; diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_symbol.cpp b/parser_library/src/expressions/conditional_assembly/terms/ca_symbol.cpp index 4783239b8..9ff0aa9c7 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_symbol.cpp +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_symbol.cpp @@ -23,10 +23,7 @@ ca_symbol::ca_symbol(context::id_index symbol, range expr_range) , symbol(symbol) {} -undef_sym_set ca_symbol::get_undefined_attributed_symbols(const context::dependency_solver&) const -{ - return undef_sym_set(); -} +undef_sym_set ca_symbol::get_undefined_attributed_symbols(const evaluation_context&) const { return undef_sym_set(); } void ca_symbol::resolve_expression_tree(context::SET_t_enum kind) { diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_symbol.h b/parser_library/src/expressions/conditional_assembly/terms/ca_symbol.h index 210acce8a..b6a7bc755 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_symbol.h +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_symbol.h @@ -27,7 +27,7 @@ class ca_symbol : public ca_expression ca_symbol(context::id_index symbol, range expr_range); - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver& solver) const override; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const override; virtual void resolve_expression_tree(context::SET_t_enum kind) override; diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_symbol_attribute.cpp b/parser_library/src/expressions/conditional_assembly/terms/ca_symbol_attribute.cpp index 7f2300b3b..36236abb2 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_symbol_attribute.cpp +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_symbol_attribute.cpp @@ -17,6 +17,7 @@ #include "ca_var_sym.h" #include "context/ordinary_assembly/dependable.h" #include "expressions/evaluation_context.h" +#include "lexing/lexer.h" #include "processing/context_manager.h" namespace hlasm_plugin::parser_library::expressions { @@ -53,17 +54,42 @@ ca_symbol_attribute::ca_symbol_attribute(semantics::vs_ptr symbol, context::data , symbol(std::move(symbol)) {} -undef_sym_set ca_symbol_attribute::get_undefined_attributed_symbols(const context::dependency_solver& solver) const +undef_sym_set ca_symbol_attribute::get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const { if (std::holds_alternative(symbol)) { if (context::symbol_attributes::is_ordinary_attribute(attribute) - && !solver.get_symbol(std::get(symbol))) + && !eval_ctx.hlasm_ctx.ord_ctx.get_symbol(std::get(symbol)) + && !eval_ctx.hlasm_ctx.ord_ctx.get_symbol_reference(std::get(symbol))) return { std::get(symbol) }; return undef_sym_set(); } else if (std::holds_alternative(symbol)) - return ca_var_sym::get_undefined_attributed_symbols_vs(std::get(symbol), solver); + { + const auto& vs = std::get(symbol); + + auto undef_syms = ca_var_sym::get_undefined_attributed_symbols_vs(vs, eval_ctx); + + if (undef_syms.empty() && context::symbol_attributes::is_ordinary_attribute(attribute)) + { + context::SET_t substituted_name = vs->evaluate(eval_ctx); + processing::context_manager mngr(&eval_ctx); + + if (substituted_name.type != context::SET_t_enum::C_TYPE) + return {}; + + auto [valid, ord_name] = mngr.try_get_symbol_name(substituted_name.access_c()); + + if (!valid) + return {}; + + if (context::symbol_attributes::is_ordinary_attribute(attribute) + && !eval_ctx.hlasm_ctx.ord_ctx.get_symbol(ord_name) + && !eval_ctx.hlasm_ctx.ord_ctx.get_symbol_reference(ord_name)) + return { ord_name }; + } + return undef_syms; + } else { assert(false); @@ -109,18 +135,45 @@ context::SET_t ca_symbol_attribute::evaluate(const evaluation_context& eval_ctx) return context::SET_t(expr_kind); } +void ca_symbol_attribute::try_extract_leading_symbol(std::string& expr) +{ + std::string delims = "+-*/()"; + + // remove parentheses + size_t start = 0; + for (; start < expr.size() && expr[start] == '(' && expr[expr.size() - 1 - start] == ')'; ++start) {}; + expr.resize(expr.size() - start); + + // remove leading using prefixes + for (size_t i = start; i < expr.size(); ++i) + { + if (expr[i] == '.' && i != expr.size() - 1) + start = i + 1; + else if (!lexing::lexer::ord_char(expr[i])) + break; + } + expr.erase(0, start); + + // look for symbol in the rest + if (expr.front() >= '0' && expr.front() <= '9') + return; + for (size_t i = 0; i < expr.size(); ++i) + { + if (delims.find(expr[i]) != std::string::npos) + expr.resize(i); + else if (!lexing::lexer::ord_char(expr[i])) + return; + } +} + context::SET_t ca_symbol_attribute::get_ordsym_attr_value( context::id_index name, const evaluation_context& eval_ctx) const { - auto ord_symbol = eval_ctx.hlasm_ctx.ord_ctx.get_symbol(name); + const context::symbol* ord_symbol = eval_ctx.hlasm_ctx.ord_ctx.get_symbol(name); if (!ord_symbol) - { - auto found = eval_ctx.attr_provider.lookup_forward_attribute_references({ name }); + ord_symbol = eval_ctx.hlasm_ctx.ord_ctx.get_symbol_reference(name); - if (auto it = found.find(name); it != found.end()) - return retrieve_value(&it->second, eval_ctx); - } return retrieve_value(ord_symbol, eval_ctx); } @@ -243,6 +296,7 @@ context::SET_t ca_symbol_attribute::evaluate_substituted(context::id_index var_n return context::symbol_attributes::default_ca_value(attribute); } + try_extract_leading_symbol(substituted_name.access_c()); auto [valid, ord_name] = mngr.try_get_symbol_name(substituted_name.access_c()); if (!valid) diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_symbol_attribute.h b/parser_library/src/expressions/conditional_assembly/terms/ca_symbol_attribute.h index cae3c72cd..546b83788 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_symbol_attribute.h +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_symbol_attribute.h @@ -35,7 +35,7 @@ class ca_symbol_attribute : public ca_expression ca_symbol_attribute(context::id_index symbol, context::data_attr_kind attribute, range expr_range); ca_symbol_attribute(semantics::vs_ptr symbol, context::data_attr_kind attribute, range expr_range); - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver& solver) const override; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const override; virtual void resolve_expression_tree(context::SET_t_enum kind) override; @@ -45,6 +45,10 @@ class ca_symbol_attribute : public ca_expression virtual context::SET_t evaluate(const evaluation_context& eval_ctx) const override; + // if expr contains a symbol as a first term, the rest of the string is thrown away + // used for L'I'S'T' reference of variable symbol + static void try_extract_leading_symbol(std::string& expr); + private: context::SET_t get_ordsym_attr_value(context::id_index name, const evaluation_context& eval_ctx) const; context::SET_t retrieve_value(const context::symbol* ord_symbol, const evaluation_context& eval_ctx) const; diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_var_sym.cpp b/parser_library/src/expressions/conditional_assembly/terms/ca_var_sym.cpp index 1e1ffaac9..2e427779e 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_var_sym.cpp +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_var_sym.cpp @@ -26,18 +26,18 @@ ca_var_sym::ca_var_sym(semantics::vs_ptr symbol, range expr_range) {} undef_sym_set ca_var_sym::get_undefined_attributed_symbols_vs( - const semantics::vs_ptr& symbol, const context::dependency_solver& solver) + const semantics::vs_ptr& symbol, const evaluation_context& eval_ctx) { undef_sym_set tmp; for (auto&& expr : symbol->subscript) - tmp.merge(expr->get_undefined_attributed_symbols(solver)); + tmp.merge(expr->get_undefined_attributed_symbols(eval_ctx)); if (symbol->created) { auto created = symbol->access_created(); for (auto&& point : created->created_name) if (point->type == semantics::concat_type::VAR) - tmp.merge(get_undefined_attributed_symbols_vs(point->access_var()->symbol, solver)); + tmp.merge(get_undefined_attributed_symbols_vs(point->access_var()->symbol, eval_ctx)); } return tmp; } @@ -47,9 +47,9 @@ void ca_var_sym::resolve_expression_tree_vs(const semantics::vs_ptr&) // already resolved in parser } -undef_sym_set ca_var_sym::get_undefined_attributed_symbols(const context::dependency_solver& solver) const +undef_sym_set ca_var_sym::get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const { - return get_undefined_attributed_symbols_vs(symbol, solver); + return get_undefined_attributed_symbols_vs(symbol, eval_ctx); } void ca_var_sym::resolve_expression_tree(context::SET_t_enum kind) diff --git a/parser_library/src/expressions/conditional_assembly/terms/ca_var_sym.h b/parser_library/src/expressions/conditional_assembly/terms/ca_var_sym.h index 000d88c21..9293fc0cc 100644 --- a/parser_library/src/expressions/conditional_assembly/terms/ca_var_sym.h +++ b/parser_library/src/expressions/conditional_assembly/terms/ca_var_sym.h @@ -28,7 +28,7 @@ class ca_var_sym : public ca_expression ca_var_sym(semantics::vs_ptr symbol, range expr_range); - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver& solver) const override; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context& eval_ctx) const override; virtual void resolve_expression_tree(context::SET_t_enum kind) override; @@ -39,7 +39,7 @@ class ca_var_sym : public ca_expression virtual context::SET_t evaluate(const evaluation_context& eval_ctx) const override; static undef_sym_set get_undefined_attributed_symbols_vs( - const semantics::vs_ptr& symbol, const context::dependency_solver& solver); + const semantics::vs_ptr& symbol, const evaluation_context& eval_ctx); static void resolve_expression_tree_vs(const semantics::vs_ptr& symbol); private: diff --git a/parser_library/src/expressions/evaluation_context.h b/parser_library/src/expressions/evaluation_context.h index 3e3599eeb..fbd8fd6ee 100644 --- a/parser_library/src/expressions/evaluation_context.h +++ b/parser_library/src/expressions/evaluation_context.h @@ -17,7 +17,6 @@ #include "context/hlasm_context.h" #include "diagnosable_ctx.h" -#include "processing/attribute_provider.h" #include "workspaces/parse_lib_provider.h" namespace hlasm_plugin { @@ -28,15 +27,11 @@ namespace expressions { struct evaluation_context : diagnosable_ctx { context::hlasm_context& hlasm_ctx; - processing::attribute_provider& attr_provider; workspaces::parse_lib_provider& lib_provider; - evaluation_context(context::hlasm_context& hlasm_ctx, - processing::attribute_provider& attr_provider, - workspaces::parse_lib_provider& lib_provider) + evaluation_context(context::hlasm_context& hlasm_ctx, workspaces::parse_lib_provider& lib_provider) : diagnosable_ctx(hlasm_ctx) , hlasm_ctx(hlasm_ctx) - , attr_provider(attr_provider) , lib_provider(lib_provider) {} diff --git a/parser_library/src/lexing/token_stream.cpp b/parser_library/src/lexing/token_stream.cpp index 66ef85a06..875348a46 100644 --- a/parser_library/src/lexing/token_stream.cpp +++ b/parser_library/src/lexing/token_stream.cpp @@ -32,7 +32,7 @@ void token_stream::enable_hidden() { enabled_hidden_ = true; } void token_stream::disable_hidden() { enabled_hidden_ = false; } -void token_stream::rewind_input(lexer::stream_position pos, bool insert_EOLLN) +void token_stream::rewind_input(lexer::stream_position pos) { auto& lexer_tmp = dynamic_cast(*_tokenSource); @@ -50,9 +50,6 @@ void token_stream::rewind_input(lexer::stream_position pos, bool insert_EOLLN) _p = _tokens.size(); } - if (insert_EOLLN) - lexer_tmp.insert_EOLLN(); - _fetchedEOF = false; sync(_p); } diff --git a/parser_library/src/lexing/token_stream.h b/parser_library/src/lexing/token_stream.h index 771d4f935..d86dc9f5d 100644 --- a/parser_library/src/lexing/token_stream.h +++ b/parser_library/src/lexing/token_stream.h @@ -52,7 +52,7 @@ class token_stream : public antlr4::BufferedTokenStream std::string getText(const antlr4::misc::Interval& interval) override; - void rewind_input(lexer::stream_position pos, bool insert_EOLLN); + void rewind_input(lexer::stream_position pos); virtual void reset() override; // prepares this object to append more tokens diff --git a/parser_library/src/parsing/grammar/hlasmparser.g4 b/parser_library/src/parsing/grammar/hlasmparser.g4 index cf2c0bac0..e733e6660 100644 --- a/parser_library/src/parsing/grammar/hlasmparser.g4 +++ b/parser_library/src/parsing/grammar/hlasmparser.g4 @@ -171,7 +171,6 @@ lab_instr returns [std::optional op_text, range op_range] { $op_text = $operand_field_rest.ctx->getText(); $op_range = provider.get_range($operand_field_rest.ctx); - process_instruction(); } } EOLLN | SPACE? @@ -180,8 +179,6 @@ lab_instr returns [std::optional op_text, range op_range] collector.set_instruction_field(provider.get_range( _localctx)); collector.set_operand_remark_field(provider.get_range( _localctx)); ctx->set_source_indices(statement_start().file_offset, statement_end().file_offset, statement_end().file_line); - process_instruction(); - process_statement(); } EOLLN | EOF {finished_flag=true;}; diff --git a/parser_library/src/parsing/grammar/lookahead_rules.g4 b/parser_library/src/parsing/grammar/lookahead_rules.g4 index d4294b0e4..83777189e 100644 --- a/parser_library/src/parsing/grammar/lookahead_rules.g4 +++ b/parser_library/src/parsing/grammar/lookahead_rules.g4 @@ -22,8 +22,6 @@ look_lab_instr returns [std::optional op_text, range op_range] collector.set_instruction_field(provider.get_range($seq_symbol.ctx)); collector.set_operand_remark_field(provider.get_range($seq_symbol.ctx)); ctx->set_source_indices(statement_start().file_offset, statement_end().file_offset, statement_end().file_line); - process_instruction(); - process_statement(); } EOLLN | ORDSYMBOL? SPACE instruction operand_field_rest { @@ -34,7 +32,6 @@ look_lab_instr returns [std::optional op_text, range op_range] collector.set_label_field(id,nullptr,r); } ctx->set_source_indices(statement_start().file_offset, statement_end().file_offset, statement_end().file_line); - process_instruction(); $op_text = $operand_field_rest.ctx->getText(); $op_range = provider.get_range($operand_field_rest.ctx); @@ -45,8 +42,6 @@ look_lab_instr returns [std::optional op_text, range op_range] collector.set_instruction_field(provider.get_range(_localctx)); collector.set_operand_remark_field(provider.get_range(_localctx)); ctx->set_source_indices(statement_start().file_offset, statement_end().file_offset, statement_end().file_line); - process_instruction(); - process_statement(); } EOLLN | EOF {finished_flag=true;}; @@ -55,18 +50,20 @@ bad_look | DOT ~(ORDSYMBOL|EOLLN) ~EOLLN* | ORDSYMBOL ~(SPACE|EOLLN) ~EOLLN* | ORDSYMBOL SPACE - | SPACE?; + | SPACE + | DOT + | ; lookahead_operands_and_remarks : SPACE+ lookahead_operand_list remark_o { - op_rem line; - line.operands = std::move($lookahead_operand_list.operands); - process_statement(std::move(line), provider.get_range($lookahead_operand_list.ctx)); + range r = provider.get_range($lookahead_operand_list.ctx); + collector.set_operand_remark_field(std::move($lookahead_operand_list.operands), std::vector(), r); } EOLLN EOF | SPACE? { - process_statement({}, provider.get_range(_localctx)); + range r = provider.get_range(_localctx); + collector.set_operand_remark_field(operand_list(), std::vector(), r); } EOLLN EOF; lookahead_operand_list returns [operand_list operands] diff --git a/parser_library/src/parsing/grammar/macro_operand_rules.g4 b/parser_library/src/parsing/grammar/macro_operand_rules.g4 index ba7cadc96..a49de04b7 100644 --- a/parser_library/src/parsing/grammar/macro_operand_rules.g4 +++ b/parser_library/src/parsing/grammar/macro_operand_rules.g4 @@ -26,7 +26,7 @@ mac_op_o returns [operand_ptr op] : mac_entry? { if($mac_entry.ctx) - $op = std::make_unique(std::move($mac_entry.chain),provider.get_range($mac_entry.ctx)); + $op = std::make_unique(std::move($mac_entry.chain),provider.get_range($mac_entry.ctx)); else $op = std::make_unique(provider.original_range); }; diff --git a/parser_library/src/parsing/grammar/operand_field_rules.g4 b/parser_library/src/parsing/grammar/operand_field_rules.g4 index 162ffdf2a..de28f6b9c 100644 --- a/parser_library/src/parsing/grammar/operand_field_rules.g4 +++ b/parser_library/src/parsing/grammar/operand_field_rules.g4 @@ -36,25 +36,27 @@ operand_not_empty returns [operand_ptr op] //////////////////////////////////////// mach -op_rem_body_mach returns [op_rem line] +op_rem_body_mach : SPACE+ op_list_mach remark_o { - $line.operands = std::move($op_list_mach.operands); - $line.remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; - process_statement(std::move($line), provider.get_range($op_list_mach.ctx->getStart(),$remark_o.ctx->getStop())); + auto remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; + auto line_range = provider.get_range($op_list_mach.ctx->getStart(),$remark_o.ctx->getStop()); + collector.set_operand_remark_field(std::move($op_list_mach.operands), std::move(remarks), line_range); } EOLLN EOF | SPACE+ model_op remark_o { operand_ptr op; + std::vector operands; if($model_op.chain_opt) op = std::make_unique(std::move(*$model_op.chain_opt),provider.get_range( $model_op.ctx)); else op = std::make_unique(provider.get_range( $model_op.ctx)); - $line.operands.push_back(std::move(op)); - $line.remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; - process_statement(std::move($line), provider.get_range($model_op.ctx->getStart(),$remark_o.ctx->getStop())); + operands.push_back(std::move(op)); + auto remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; + auto line_range = provider.get_range($model_op.ctx->getStart(),$remark_o.ctx->getStop()); + collector.set_operand_remark_field(std::move(operands), std::move(remarks), line_range); } EOLLN EOF - | {process_statement(std::move($line), provider.get_range(_localctx));} EOLLN EOF; + | {collector.set_operand_remark_field(provider.get_range(_localctx));} EOLLN EOF; op_list_mach returns [std::vector operands] : operand_mach (comma operand_mach)* @@ -72,25 +74,27 @@ operand_mach returns [operand_ptr op] //////////////////////////////////////// dat -op_rem_body_dat returns [op_rem line] +op_rem_body_dat : SPACE+ op_list_dat remark_o { - $line.operands = std::move($op_list_dat.operands); - $line.remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; - process_statement(std::move($line), provider.get_range($op_list_dat.ctx->getStart(),$remark_o.ctx->getStop())); + auto remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; + auto line_range = provider.get_range($op_list_dat.ctx->getStart(),$remark_o.ctx->getStop()); + collector.set_operand_remark_field(std::move($op_list_dat.operands), std::move(remarks), line_range); } EOLLN EOF | SPACE+ model_op remark_o { operand_ptr op; + std::vector operands; if($model_op.chain_opt) op = std::make_unique(std::move(*$model_op.chain_opt),provider.get_range( $model_op.ctx)); else op = std::make_unique(provider.get_range( $model_op.ctx)); - $line.operands.push_back(std::move(op)); - $line.remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; - process_statement(std::move($line), provider.get_range($model_op.ctx->getStart(),$remark_o.ctx->getStop())); + operands.push_back(std::move(op)); + auto remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; + auto line_range = provider.get_range($model_op.ctx->getStart(),$remark_o.ctx->getStop()); + collector.set_operand_remark_field(std::move(operands), std::move(remarks), line_range); } EOLLN EOF - | {process_statement(std::move($line), provider.get_range(_localctx));} EOLLN EOF; + | {collector.set_operand_remark_field(provider.get_range(_localctx));} EOLLN EOF; op_list_dat returns [std::vector operands] : operand_dat (comma operand_dat)* @@ -108,25 +112,27 @@ operand_dat returns [operand_ptr op] //////////////////////////////////////// asm -op_rem_body_asm returns [op_rem line] +op_rem_body_asm : SPACE+ op_list_asm remark_o { - $line.operands = std::move($op_list_asm.operands); - $line.remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; - process_statement(std::move($line), provider.get_range($op_list_asm.ctx->getStart(),$remark_o.ctx->getStop())); + auto remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; + auto line_range = provider.get_range($op_list_asm.ctx->getStart(),$remark_o.ctx->getStop()); + collector.set_operand_remark_field(std::move($op_list_asm.operands), std::move(remarks), line_range); } EOLLN EOF | SPACE+ model_op remark_o { operand_ptr op; + std::vector operands; if($model_op.chain_opt) op = std::make_unique(std::move(*$model_op.chain_opt),provider.get_range( $model_op.ctx)); else op = std::make_unique(provider.get_range( $model_op.ctx)); - $line.operands.push_back(std::move(op)); - $line.remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; - process_statement(std::move($line), provider.get_range($model_op.ctx->getStart(),$remark_o.ctx->getStop())); + operands.push_back(std::move(op)); + auto remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; + auto line_range = provider.get_range($model_op.ctx->getStart(),$remark_o.ctx->getStop()); + collector.set_operand_remark_field(std::move(operands), std::move(remarks), line_range); } EOLLN EOF - | {process_statement(std::move($line), provider.get_range(_localctx));} EOLLN EOF; + | {collector.set_operand_remark_field(provider.get_range(_localctx));} EOLLN EOF; op_list_asm returns [std::vector operands] : operand_asm (comma operand_asm)* @@ -145,17 +151,19 @@ operand_asm returns [operand_ptr op] //////////////////////////////////////// ca -op_rem_body_ca returns [op_rem line] +op_rem_body_ca : SPACE+ op_rem_body_alt_ca { - process_statement(std::move($op_rem_body_alt_ca.line), provider.get_range($op_rem_body_alt_ca.ctx)); + auto line_range = provider.get_range($op_rem_body_alt_ca.ctx); + collector.set_operand_remark_field(std::move($op_rem_body_alt_ca.line.operands), std::move($op_rem_body_alt_ca.line.remarks), line_range); } EOLLN EOF | remark_o { - $line.remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; - process_statement(std::move($line), provider.get_range($remark_o.ctx)); + auto remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; + auto line_range = provider.get_range($remark_o.ctx); + collector.set_operand_remark_field(operand_list(), std::move(remarks), line_range); } EOLLN EOF - | {process_statement(std::move($line), provider.get_range(_localctx));} EOLLN EOF; + | {collector.set_operand_remark_field(provider.get_range(_localctx));} EOLLN EOF; op_rem_body_alt_ca returns [op_rem line] : alt_op_list_comma_ca cont_ca @@ -210,18 +218,18 @@ alt_operand_ca returns [operand_ptr op] //////////////////////////////////////// mac -op_rem_body_mac returns [op_rem line] +op_rem_body_mac returns [op_rem line, range line_range] : SPACE+ op_rem_body_alt_mac { - parse_macro_operands($op_rem_body_alt_mac.line); - process_statement(std::move($op_rem_body_alt_mac.line), provider.get_range($op_rem_body_alt_mac.ctx)); + $line = std::move($op_rem_body_alt_mac.line); + $line_range = provider.get_range($op_rem_body_alt_mac.ctx); } EOLLN EOF | remark_o { $line.remarks = $remark_o.value ? remark_list{*$remark_o.value} : remark_list{}; - process_statement(std::move($line), provider.get_range($remark_o.ctx)); + $line_range = provider.get_range($remark_o.ctx); } EOLLN EOF - | {process_statement(std::move($line), provider.get_range(_localctx));} EOLLN EOF; + | {$line_range = provider.get_range(_localctx);} EOLLN EOF; op_rem_body_alt_mac returns [op_rem line] : alt_op_list_comma_mac cont_mac @@ -283,27 +291,17 @@ op_rem_body_deferred : { collector.set_operand_remark_field(provider.get_empty_range(_localctx->getStart())); - collector.add_operands_hl_symbols(); - collector.add_remarks_hl_symbols(); - process_statement(); } EOLLN EOF - | SPACE {enable_hidden();} deferred_op_rem + | SPACE {enable_hidden();} deferred_op_rem {disable_hidden();} { auto r = provider.get_range( $deferred_op_rem.ctx); collector.set_operand_remark_field($deferred_op_rem.ctx->getText(),std::move($deferred_op_rem.remarks),r); - collector.add_operands_hl_symbols(); - collector.add_remarks_hl_symbols(); - process_statement(); - disable_hidden(); } EOLLN EOF; op_rem_body_noop : remark_o { collector.set_operand_remark_field(operand_list{},$remark_o.value ? remark_list{*$remark_o.value} : remark_list{}, provider.get_range( $remark_o.ctx)); - collector.add_operands_hl_symbols(); - collector.add_remarks_hl_symbols(); - process_statement(); } EOLLN EOF; //////////////////////////////////////// mach_r @@ -326,7 +324,7 @@ op_rem_body_mach_r returns [op_rem line] } EOLLN EOF | EOLLN EOF; -//////////////////////////////////////// dat +//////////////////////////////////////// dat_r op_rem_body_dat_r returns [op_rem line] : op_list_dat remark_o @@ -346,7 +344,7 @@ op_rem_body_dat_r returns [op_rem line] } EOLLN EOF | EOLLN EOF; -//////////////////////////////////////// asm +//////////////////////////////////////// asm_r op_rem_body_asm_r returns [op_rem line] : op_list_asm remark_o @@ -366,12 +364,11 @@ op_rem_body_asm_r returns [op_rem line] } EOLLN EOF | EOLLN EOF; -//////////////////////////////////////// mac +//////////////////////////////////////// mac_r op_rem_body_mac_r returns [op_rem line] : op_rem_body_alt_mac { - parse_macro_operands($op_rem_body_alt_mac.line); $line = std::move($op_rem_body_alt_mac.line); } EOLLN EOF | remark_o diff --git a/parser_library/src/parsing/parser_impl.cpp b/parser_library/src/parsing/parser_impl.cpp index 02ecfa270..1e9828221 100644 --- a/parser_library/src/parsing/parser_impl.cpp +++ b/parser_library/src/parsing/parser_impl.cpp @@ -34,17 +34,18 @@ parser_impl::parser_impl(antlr4::TokenStream* input) , processor(nullptr) , finished_flag(false) , provider() - , parent_(nullptr) - , last_line_processed_(false) - , line_end_pushed_(false) {} -void parser_impl::initialize(context::hlasm_context* hlasm_ctx, semantics::lsp_info_processor* lsp_prc) +void parser_impl::initialize(context::hlasm_context* hlasm_ctx, + semantics::lsp_info_processor* lsp_prc, + workspaces::parse_lib_provider* lib_provider, + processing::processing_state_listener* state_listener) { ctx = hlasm_ctx; lsp_proc = lsp_prc; finished_flag = false; - pushed_state_ = false; + lib_provider_ = lib_provider; + state_listener_ = state_listener; } bool parser_impl::is_last_line() const @@ -55,14 +56,10 @@ bool parser_impl::is_last_line() const void parser_impl::rewind_input(context::source_position pos) { finished_flag = false; - last_line_processed_ = false; _matchedEOF = false; - input.rewind_input(lexing::lexer::stream_position { pos.file_line, pos.file_offset }, line_end_pushed_); - line_end_pushed_ = false; + input.rewind_input(lexing::lexer::stream_position { pos.file_line, pos.file_offset }); } -void parser_impl::push_line_end() { line_end_pushed_ = true; } - context::source_position parser_impl::statement_start() const { auto pos = dynamic_cast(*_input->getTokenSource()).last_lln_begin_position(); @@ -93,11 +90,11 @@ std::pair parser_impl::parse_oper semantics::range_provider field_range, processing::processing_status status) { - if (!reparser_) - reparser_ = create_parser_holder(); + if (!rest_parser_) + rest_parser_ = create_parser_holder(); hlasm_ctx->metrics.reparsed_statements++; - parser_holder& h = *reparser_; + const parser_holder& h = *rest_parser_; std::optional sub; if (after_substitution) @@ -116,16 +113,7 @@ std::pair parser_impl::parse_oper h.parser->setErrorHandler(std::make_shared()); h.parser->removeErrorListeners(); h.parser->addErrorListener(&listener); - - // indicates that the reparse is done to resolve deferred ordinary symbols (and not to substitute) - if (!after_substitution) - { - lsp_proc->process_lsp_symbols(h.parser->collector.extract_lsp_symbols(), - ctx->ids().add(ctx->processing_stack().back().proc_location.file, true)); - } - h.parser->reset(); - h.parser->_matchedEOF = false; h.parser->collector.prepare_for_next_statement(); @@ -140,6 +128,7 @@ std::pair parser_impl::parse_oper { case processing::processing_form::MAC: line = std::move(h.parser->op_rem_body_mac_r()->line); + parse_macro_operands(line); break; case processing::processing_form::ASM: line = std::move(h.parser->op_rem_body_asm_r()->line); @@ -155,6 +144,13 @@ std::pair parser_impl::parse_oper } } + // indicates that the reparse reason is to resolve deferred operands (and not to substitute varsymbols) + if (!after_substitution) + { + lsp_proc->process_lsp_symbols(h.parser->collector.extract_lsp_symbols(), + ctx->ids().add(ctx->processing_stack().back().proc_location.file, true)); + } + collect_diags_from_child(listener); for (size_t i = 0; i < line.operands.size(); i++) @@ -183,14 +179,10 @@ std::pair parser_impl::parse_oper void parser_impl::collect_diags() const { - if (reparser_) - collect_diags_from_child(*reparser_->parser); if (rest_parser_) collect_diags_from_child(*rest_parser_->parser); } - - void parser_impl::enable_continuation() { input.enable_continuation(); } void parser_impl::disable_continuation() { input.disable_continuation(); } @@ -254,7 +246,7 @@ context::id_index parser_impl::parse_identifier(std::string value, range id_rang void parser_impl::parse_macro_operands(semantics::op_rem& line) { - if (line.operands.size() && MAC()) + if (line.operands.size()) { size_t string_size = line.operands.size(); std::vector ranges; @@ -317,23 +309,19 @@ void parser_impl::resolve_expression(expressions::ca_expr_ptr& expr) const } } -void parser_impl::process_instruction() +bool parser_impl::process_instruction() { + if (processor->kind == processing::processing_kind::ORDINARY + && try_trigger_attribute_lookahead(collector.current_instruction(), { *ctx, *lib_provider_ }, *state_listener_)) + return true; + ctx->set_source_position(collector.current_instruction().field_range.start); proc_status = processor->get_processing_status(collector.peek_instruction()); + return false; } -void parser_impl::process_statement() +bool parser_impl::process_statement() { - if (parent_) - { - parent_->collector.append_operand_field(std::move(collector)); - parent_->process_statement(); - return; - } - - // ctx->set_source_indices(statement_start().file_offset, statement_end().file_offset, statement_end().file_line); - bool hint = proc_status->first.form == processing::processing_form::DEFERRED; auto stmt(collector.extract_statement(hint, range(position(statement_start().file_line, 0)))); context::unique_stmt_ptr ptr; @@ -353,6 +341,10 @@ void parser_impl::process_statement() statement_range = dynamic_cast(ptr.get())->deferred_range_ref(); } + if (processor->kind == processing::processing_kind::ORDINARY + && try_trigger_attribute_lookahead(*ptr, { *ctx, *lib_provider_ }, *state_listener_)) + return true; + if (statement_range.start.line < statement_range.end.line) ctx->metrics.continued_statements++; else @@ -363,42 +355,19 @@ void parser_impl::process_statement() collector.prepare_for_next_statement(); processor->process_statement(std::move(ptr)); -} -void parser_impl::process_statement(semantics::op_rem line, range op_range) -{ - collector.set_operand_remark_field(std::move(line.operands), std::move(line.remarks), op_range); - collector.add_operands_hl_symbols(); - collector.add_remarks_hl_symbols(); - parent_->collector.append_operand_field(std::move(collector)); - parent_->process_statement(); + return false; } void parser_impl::process_next(processing::statement_processor& proc) { - if (collector.has_instruction()) - { - // lookahead of attribute ref during instruction processing - assert(proc.kind == processing::processing_kind::LOOKAHEAD); - push_state(); - } processor = &proc; + if (proc.kind == processing::processing_kind::LOOKAHEAD) - { - auto look_lab_instr = dynamic_cast(*this).look_lab_instr(); - if (!finished_flag && look_lab_instr->op_text) - parse_lookahead(std::move(*look_lab_instr->op_text), look_lab_instr->op_range); - } + process_lookahead(); else - { - bool state = pushed_state_; - auto lab_instr = dynamic_cast(*this).lab_instr(); - if (state != pushed_state_) - pop_state(); + process_ordinary(); - if (!finished_flag && lab_instr->op_text) - parse_rest(std::move(*lab_instr->op_text), lab_instr->op_range); - } processor = nullptr; collector.prepare_for_next_statement(); proc_status.reset(); @@ -473,39 +442,15 @@ void parser_impl::initialize( ctx = hlasm_ctx; provider = range_prov; proc_status = proc_stat; - pushed_state_ = false; -} - -void parser_impl::initialize(parser_impl* parent) -{ - ctx = parent->ctx; - provider = parent->provider; - proc_status = parent->proc_status; - parent_ = parent; - pushed_state_ = false; -} - -void parser_impl::push_state() -{ - collector.push_fields(); - processor_storage_ = processor; - pushed_state_ = true; -} - -void parser_impl::pop_state() -{ - collector.pop_fields(); - processor = processor_storage_; - pushed_state_ = false; } semantics::operand_list parser_impl::parse_macro_operands( std::string operands, range field_range, std::vector operand_ranges) { - if (!reparser_) - reparser_ = create_parser_holder(); + if (!rest_parser_) + rest_parser_ = create_parser_holder(); - parser_holder& h = *reparser_; + const parser_holder& h = *rest_parser_; semantics::range_provider tmp_provider(field_range, operand_ranges, semantics::adjusting_state::MACRO_REPARSE); @@ -525,22 +470,48 @@ semantics::operand_list parser_impl::parse_macro_operands( h.parser->addErrorListener(&listener); h.parser->reset(); - h.parser->_matchedEOF = false; h.parser->collector.prepare_for_next_statement(); auto list = std::move(h.parser->macro_ops()->list); - if (parent_) - collector.prepare_for_next_statement(); - collector.append_reparsed_symbols(std::move(h.parser->collector)); - collect_diags_from_child(listener); return list; } -void parser_impl::parse_rest(std::string text, range text_range) +void parser_impl::process_ordinary() +{ + auto lab_instr = dynamic_cast(*this).lab_instr(); + + if (!finished_flag && collector.has_instruction()) + { + bool attr_look_needed = process_instruction(); + + if (attr_look_needed) + return; + + if (!lab_instr->op_text) + process_statement(); + else + parse_operands(std::move(*lab_instr->op_text), lab_instr->op_range); + } +} + +void parser_impl::process_lookahead() +{ + auto look_lab_instr = dynamic_cast(*this).look_lab_instr(); + if (!finished_flag) + { + process_instruction(); + if (!look_lab_instr->op_text) + process_statement(); + else + parse_lookahead_operands(std::move(*look_lab_instr->op_text), look_lab_instr->op_range); + } +} + +void parser_impl::parse_operands(const std::string& text, range text_range) { if (!rest_parser_) rest_parser_ = create_parser_holder(); @@ -553,16 +524,16 @@ void parser_impl::parse_rest(std::string text, range text_range) h.lex->reset(); h.lex->set_file_offset(text_range.start); + h.lex->set_unlimited_line(false); h.stream->reset(); - h.parser->initialize(this); + h.parser->initialize(ctx, provider, *proc_status); h.parser->setErrorHandler(std::make_shared()); h.parser->removeErrorListeners(); h.parser->addErrorListener(&listener); h.parser->reset(); - h.parser->_matchedEOF = false; h.parser->collector.prepare_for_next_statement(); @@ -583,9 +554,15 @@ void parser_impl::parse_rest(std::string text, range text_range) case processing::processing_form::CA: h.parser->op_rem_body_ca(); break; - case processing::processing_form::MAC: - h.parser->op_rem_body_mac(); - break; + case processing::processing_form::MAC: { + auto rule = h.parser->op_rem_body_mac(); + auto line = std::move(rule->line); + auto line_range = rule->line_range; + parse_macro_operands(line); + h.parser->collector.set_operand_remark_field( + std::move(line.operands), std::move(line.remarks), line_range); + } + break; case processing::processing_form::ASM: h.parser->op_rem_body_asm(); break; @@ -600,15 +577,19 @@ void parser_impl::parse_rest(std::string text, range text_range) } } - collect_diags_from_child(listener); + if (format.form != processing::processing_form::IGNORED) + { + collector.append_operand_field(std::move(h.parser->collector)); + process_statement(); + } - collector.append_operand_field(std::move(h.parser->collector)); + collect_diags_from_child(listener); } -void parser_impl::parse_lookahead(std::string text, range text_range) +void parser_impl::parse_lookahead_operands(const std::string& text, range text_range) { - if (!reparser_) - reparser_ = create_parser_holder(); + if (!rest_parser_) + rest_parser_ = create_parser_holder(); if (proc_status->first.form == processing::processing_form::IGNORED) { @@ -616,6 +597,7 @@ void parser_impl::parse_lookahead(std::string text, range text_range) return; } + // optimization : if statement has no label and is not COPY, do not even parse operands if (!collector.has_label()) { if (collector.current_instruction().type == semantics::instruction_si_type::ORD) @@ -630,7 +612,7 @@ void parser_impl::parse_lookahead(std::string text, range text_range) } } - parser_holder& h = *reparser_; + const parser_holder& h = *rest_parser_; parser_error_listener_ctx listener(*ctx, std::nullopt); @@ -642,21 +624,21 @@ void parser_impl::parse_lookahead(std::string text, range text_range) h.stream->reset(); - h.parser->initialize(this); + h.parser->initialize(ctx, provider, *proc_status); h.parser->setErrorHandler(std::make_shared()); h.parser->removeErrorListeners(); h.parser->addErrorListener(&listener); h.parser->reset(); - h.parser->_matchedEOF = false; h.parser->collector.prepare_for_next_statement(); h.parser->lookahead_operands_and_remarks(); - listener.diags().clear(); + h.parser->collector.clear_hl_lsp_symbols(); + collector.append_operand_field(std::move(h.parser->collector)); - collector.prepare_for_next_statement(); + process_statement(); } antlr4::misc::IntervalSet parser_impl::getExpectedTokens() @@ -669,4 +651,4 @@ antlr4::misc::IntervalSet parser_impl::getExpectedTokens() parser_holder::~parser_holder() {} -} // namespace hlasm_plugin::parser_library::parsing \ No newline at end of file +} // namespace hlasm_plugin::parser_library::parsing diff --git a/parser_library/src/parsing/parser_impl.h b/parser_library/src/parsing/parser_impl.h index 2d4fe33b2..c65155b59 100644 --- a/parser_library/src/parsing/parser_impl.h +++ b/parser_library/src/parsing/parser_impl.h @@ -51,11 +51,13 @@ class parser_impl : public antlr4::Parser, public: parser_impl(antlr4::TokenStream* input); - void initialize(context::hlasm_context* hlasm_ctx, semantics::lsp_info_processor* lsp_prc); + void initialize(context::hlasm_context* hlasm_ctx, + semantics::lsp_info_processor* lsp_prc, + workspaces::parse_lib_provider* lib_provider, + processing::processing_state_listener* state_listener); bool is_last_line() const; virtual void rewind_input(context::source_position pos) override; - virtual void push_line_end() override; context::source_position statement_start() const; context::source_position statement_end() const; @@ -85,9 +87,9 @@ class parser_impl : public antlr4::Parser, void resolve_expression(std::vector& expr, context::SET_t_enum type) const; void resolve_expression(expressions::ca_expr_ptr& expr) const; - void process_instruction(); - void process_statement(); - void process_statement(semantics::op_rem line, range op_range); + // process methods return true if attribute lookahead needed + bool process_instruction(); + bool process_statement(); virtual void process_next(processing::statement_processor& processor) override; virtual bool finished() const override; @@ -113,30 +115,24 @@ class parser_impl : public antlr4::Parser, bool UNKNOWN(); private: + std::unique_ptr rest_parser_; + workspaces::parse_lib_provider* lib_provider_; + processing::processing_state_listener* state_listener_; + void initialize(context::hlasm_context* hlasm_ctx, semantics::range_provider range_prov, processing::processing_status proc_stat); - parser_impl* parent_; - void initialize(parser_impl* parent); - - void push_state(); - void pop_state(); - bool pushed_state_; - processing::statement_processor* processor_storage_; semantics::operand_list parse_macro_operands( std::string operands, range field_range, std::vector operand_ranges); - void parse_rest(std::string text, range text_range); - void parse_lookahead(std::string text, range text_range); + void process_ordinary(); + void process_lookahead(); - virtual antlr4::misc::IntervalSet getExpectedTokens() override; - - std::unique_ptr reparser_; - std::unique_ptr rest_parser_; + void parse_operands(const std::string& text, range text_range); + void parse_lookahead_operands(const std::string& text, range text_range); - bool last_line_processed_; - bool line_end_pushed_; + virtual antlr4::misc::IntervalSet getExpectedTokens() override; }; // structure containing parser components diff --git a/parser_library/src/processing/attribute_provider.h b/parser_library/src/processing/attribute_provider.h deleted file mode 100644 index ceacf7ef0..000000000 --- a/parser_library/src/processing/attribute_provider.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Broadcom. - * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Broadcom, Inc. - initial API and implementation - */ - -#ifndef PROCESSING_ATTRIBUTE_PROVIDER_H -#define PROCESSING_ATTRIBUTE_PROVIDER_H - -#include -#include - -#include "context/id_storage.h" -#include "context/ordinary_assembly/symbol.h" -#include "context/ordinary_assembly/symbol_attributes.h" -#include "range.h" - -namespace hlasm_plugin { -namespace parser_library { -namespace processing { - -// interface for providing values of yet undefined symbol attributes -class attribute_provider -{ -public: - using forward_reference_storage = std::set; - using resolved_reference_storage = std::unordered_map; - - virtual const resolved_reference_storage& lookup_forward_attribute_references( - forward_reference_storage references) = 0; - -protected: - resolved_reference_storage resolved_symbols; -}; - -} // namespace processing -} // namespace parser_library -} // namespace hlasm_plugin - -#endif diff --git a/parser_library/src/processing/branching_provider.h b/parser_library/src/processing/branching_provider.h index 8507f7e80..96fff0462 100644 --- a/parser_library/src/processing/branching_provider.h +++ b/parser_library/src/processing/branching_provider.h @@ -17,6 +17,7 @@ #include "context/id_storage.h" #include "context/ordinary_assembly/dependant.h" +#include "range.h" namespace hlasm_plugin { namespace parser_library { diff --git a/parser_library/src/processing/context_manager.cpp b/parser_library/src/processing/context_manager.cpp index 0622e2dce..4bb321f3f 100644 --- a/parser_library/src/processing/context_manager.cpp +++ b/parser_library/src/processing/context_manager.cpp @@ -98,14 +98,14 @@ context::id_index context_manager::get_symbol_name(const std::string& symbol, ra context_manager::name_result context_manager::try_get_symbol_name(const std::string& symbol) const { - size_t i; - for (i = 0; i < symbol.size(); ++i) - if (!lexing::lexer::ord_char(symbol[i]) || !(i != 0 || !isdigit(symbol[i]))) - break; - - if (i == 0 || i > 63) + if (symbol.empty() || symbol.size() > 63 || isdigit(symbol.front())) return std::make_pair(false, context::id_storage::empty_id); - return std::make_pair(true, hlasm_ctx.ids().add(symbol.substr(0, i))); + + for (const auto& c : symbol) + if (!lexing::lexer::ord_char(c)) + return std::make_pair(false, context::id_storage::empty_id); + + return std::make_pair(true, hlasm_ctx.ids().add(symbol)); } bool context_manager::test_symbol_for_read( diff --git a/parser_library/src/processing/instruction_sets/asm_processor.cpp b/parser_library/src/processing/instruction_sets/asm_processor.cpp index 49a91b925..ec77ee8ae 100644 --- a/parser_library/src/processing/instruction_sets/asm_processor.cpp +++ b/parser_library/src/processing/instruction_sets/asm_processor.cpp @@ -21,9 +21,7 @@ #include "postponed_statement_impl.h" #include "processing/context_manager.h" -using namespace hlasm_plugin::parser_library; -using namespace processing; -using namespace workspaces; +namespace hlasm_plugin::parser_library::processing { void asm_processor::process_sect(const context::section_kind kind, rebuilt_statement stmt) { @@ -159,8 +157,8 @@ void asm_processor::process_EQU(rebuilt_statement stmt) if (cycle_ok) { - auto r = stmt.stmt_range_ref(); - add_dependency(r, + const auto& stmt_range = stmt.stmt_range_ref(); + add_dependency(stmt_range, symbol_name, &*expr_op->expression, std::make_unique(std::move(stmt), hlasm_ctx.processing_stack())); @@ -502,11 +500,10 @@ void asm_processor::process_OPSYN(rebuilt_statement stmt) } asm_processor::asm_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, - parse_lib_provider& lib_provider, + workspaces::parse_lib_provider& lib_provider, statement_fields_parser& parser) - : low_language_processor(hlasm_ctx, attr_provider, branch_provider, lib_provider, parser) + : low_language_processor(hlasm_ctx, branch_provider, lib_provider, parser) , table_(create_table(hlasm_ctx)) {} @@ -514,7 +511,7 @@ void asm_processor::process(context::shared_stmt_ptr stmt) { process(preprocess( void asm_processor::process_copy(const semantics::complete_statement& stmt, context::hlasm_context& hlasm_ctx, - parse_lib_provider& lib_provider, + workspaces::parse_lib_provider& lib_provider, diagnosable_ctx* diagnoser) { auto& expr = stmt.operands_ref().value.front()->access_asm()->access_expr()->expression; @@ -532,7 +529,7 @@ void asm_processor::process_copy(const semantics::complete_statement& stmt, if (tmp == hlasm_ctx.copy_members().end()) { bool result = lib_provider.parse_library( - *sym_expr->value, hlasm_ctx, library_data { processing_kind::COPY, sym_expr->value }); + *sym_expr->value, hlasm_ctx, workspaces::library_data { processing_kind::COPY, sym_expr->value }); if (!result) { @@ -618,3 +615,5 @@ void asm_processor::process(rebuilt_statement statement) check(statement, hlasm_ctx, checker_, *this); } } + +} // namespace hlasm_plugin::parser_library::processing diff --git a/parser_library/src/processing/instruction_sets/asm_processor.h b/parser_library/src/processing/instruction_sets/asm_processor.h index 8bed4a5ab..29ad52e15 100644 --- a/parser_library/src/processing/instruction_sets/asm_processor.h +++ b/parser_library/src/processing/instruction_sets/asm_processor.h @@ -30,7 +30,6 @@ class asm_processor : public low_language_processor public: asm_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, workspaces::parse_lib_provider& lib_provider, statement_fields_parser& parser); diff --git a/parser_library/src/processing/instruction_sets/ca_processor.cpp b/parser_library/src/processing/instruction_sets/ca_processor.cpp index 250dc773f..308e42e27 100644 --- a/parser_library/src/processing/instruction_sets/ca_processor.cpp +++ b/parser_library/src/processing/instruction_sets/ca_processor.cpp @@ -21,11 +21,10 @@ using namespace processing; using namespace workspaces; ca_processor::ca_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, parse_lib_provider& lib_provider, processing_state_listener& listener) - : instruction_processor(hlasm_ctx, attr_provider, branch_provider, lib_provider) + : instruction_processor(hlasm_ctx, branch_provider, lib_provider) , table_(create_table(hlasm_ctx)) , listener_(listener) {} diff --git a/parser_library/src/processing/instruction_sets/ca_processor.h b/parser_library/src/processing/instruction_sets/ca_processor.h index 12fbb2f40..8b3d523f5 100644 --- a/parser_library/src/processing/instruction_sets/ca_processor.h +++ b/parser_library/src/processing/instruction_sets/ca_processor.h @@ -32,7 +32,6 @@ class ca_processor : public instruction_processor public: ca_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, workspaces::parse_lib_provider& lib_provider, processing_state_listener& listener); @@ -148,4 +147,5 @@ inline void ca_processor::process_GBL_LCL(const semantics::complete_statement& s } } // namespace hlasm_plugin::parser_library::processing + #endif \ No newline at end of file diff --git a/parser_library/src/processing/instruction_sets/instruction_processor.h b/parser_library/src/processing/instruction_sets/instruction_processor.h index 80983cd9d..79fd775ee 100644 --- a/parser_library/src/processing/instruction_sets/instruction_processor.h +++ b/parser_library/src/processing/instruction_sets/instruction_processor.h @@ -21,7 +21,6 @@ #include "context/hlasm_context.h" #include "diagnosable_ctx.h" #include "expressions/evaluation_context.h" -#include "processing/attribute_provider.h" #include "processing/branching_provider.h" #include "processing/statement.h" #include "workspaces/parse_lib_provider.h" @@ -41,22 +40,19 @@ class instruction_processor : public diagnosable_ctx protected: context::hlasm_context& hlasm_ctx; - attribute_provider& attr_provider; branching_provider& branch_provider; workspaces::parse_lib_provider& lib_provider; expressions::evaluation_context eval_ctx; instruction_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, workspaces::parse_lib_provider& lib_provider) : diagnosable_ctx(hlasm_ctx) , hlasm_ctx(hlasm_ctx) - , attr_provider(attr_provider) , branch_provider(branch_provider) , lib_provider(lib_provider) - , eval_ctx { hlasm_ctx, attr_provider, lib_provider } + , eval_ctx { hlasm_ctx, lib_provider } {} }; diff --git a/parser_library/src/processing/instruction_sets/low_language_processor.cpp b/parser_library/src/processing/instruction_sets/low_language_processor.cpp index fa2db8540..4611b90a8 100644 --- a/parser_library/src/processing/instruction_sets/low_language_processor.cpp +++ b/parser_library/src/processing/instruction_sets/low_language_processor.cpp @@ -24,11 +24,10 @@ using namespace processing; using namespace workspaces; low_language_processor::low_language_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, parse_lib_provider& lib_provider, statement_fields_parser& parser) - : instruction_processor(hlasm_ctx, attr_provider, branch_provider, lib_provider) + : instruction_processor(hlasm_ctx, branch_provider, lib_provider) , parser(parser) {} diff --git a/parser_library/src/processing/instruction_sets/low_language_processor.h b/parser_library/src/processing/instruction_sets/low_language_processor.h index 4091a3cda..27aa6eb1b 100644 --- a/parser_library/src/processing/instruction_sets/low_language_processor.h +++ b/parser_library/src/processing/instruction_sets/low_language_processor.h @@ -34,7 +34,6 @@ class low_language_processor : public instruction_processor statement_fields_parser& parser; low_language_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, workspaces::parse_lib_provider& lib_provider, statement_fields_parser& parser); diff --git a/parser_library/src/processing/instruction_sets/mach_processor.cpp b/parser_library/src/processing/instruction_sets/mach_processor.cpp index 791a3e865..2c7107e7f 100644 --- a/parser_library/src/processing/instruction_sets/mach_processor.cpp +++ b/parser_library/src/processing/instruction_sets/mach_processor.cpp @@ -26,11 +26,10 @@ using namespace hlasm_plugin::parser_library::processing; using namespace hlasm_plugin::parser_library::workspaces; mach_processor::mach_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, parse_lib_provider& lib_provider, statement_fields_parser& parser) - : low_language_processor(hlasm_ctx, attr_provider, branch_provider, lib_provider, parser) + : low_language_processor(hlasm_ctx, branch_provider, lib_provider, parser) {} void mach_processor::process(context::shared_stmt_ptr stmt) diff --git a/parser_library/src/processing/instruction_sets/mach_processor.h b/parser_library/src/processing/instruction_sets/mach_processor.h index f57603134..cd2b388d9 100644 --- a/parser_library/src/processing/instruction_sets/mach_processor.h +++ b/parser_library/src/processing/instruction_sets/mach_processor.h @@ -28,7 +28,6 @@ class mach_processor : public low_language_processor public: mach_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, workspaces::parse_lib_provider& lib_provider, statement_fields_parser& parser); diff --git a/parser_library/src/processing/instruction_sets/macro_processor.cpp b/parser_library/src/processing/instruction_sets/macro_processor.cpp index 5abd1bdaa..f286088cb 100644 --- a/parser_library/src/processing/instruction_sets/macro_processor.cpp +++ b/parser_library/src/processing/instruction_sets/macro_processor.cpp @@ -22,10 +22,9 @@ namespace hlasm_plugin::parser_library::processing { macro_processor::macro_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, workspaces::parse_lib_provider& lib_provider) - : instruction_processor(hlasm_ctx, attr_provider, branch_provider, lib_provider) + : instruction_processor(hlasm_ctx, branch_provider, lib_provider) {} void macro_processor::process(context::shared_stmt_ptr stmt) @@ -229,7 +228,7 @@ std::vector macro_processor::get_operand_args(const resolved continue; } - auto tmp = op->access_mac(); + auto tmp = op->access_mac()->access_chain(); assert(tmp); auto& tmp_chain = tmp->chain; diff --git a/parser_library/src/processing/instruction_sets/macro_processor.h b/parser_library/src/processing/instruction_sets/macro_processor.h index bc71b97ad..5703e9620 100644 --- a/parser_library/src/processing/instruction_sets/macro_processor.h +++ b/parser_library/src/processing/instruction_sets/macro_processor.h @@ -34,7 +34,6 @@ class macro_processor : public instruction_processor { public: macro_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, workspaces::parse_lib_provider& lib_provider); virtual void process(context::unique_stmt_ptr stmt) override; diff --git a/parser_library/src/processing/opencode_provider.h b/parser_library/src/processing/opencode_provider.h index 14e9e50e8..5820286b7 100644 --- a/parser_library/src/processing/opencode_provider.h +++ b/parser_library/src/processing/opencode_provider.h @@ -29,11 +29,6 @@ class opencode_provider : public statement_provider // rewinds position in file virtual void rewind_input(context::source_position pos) = 0; - // pushes the logical line ending to currently evaluated statement - // so other statements can be processed within evaluation of current - // ending is poped with first rewind_input - virtual void push_line_end() = 0; - opencode_provider() : statement_provider(processing::statement_provider_kind::OPEN) {} diff --git a/parser_library/src/processing/processing_manager.cpp b/parser_library/src/processing/processing_manager.cpp index 3365451be..a637dc4e2 100644 --- a/parser_library/src/processing/processing_manager.cpp +++ b/parser_library/src/processing/processing_manager.cpp @@ -25,15 +25,13 @@ #include "statement_providers/copy_statement_provider.h" #include "statement_providers/macro_statement_provider.h" -using namespace hlasm_plugin::parser_library; -using namespace hlasm_plugin::parser_library::processing; -using namespace hlasm_plugin::parser_library::workspaces; +namespace hlasm_plugin::parser_library::processing { processing_manager::processing_manager(std::unique_ptr base_provider, context::hlasm_context& hlasm_ctx, - const library_data data, + const workspaces::library_data data, std::string file_name, - parse_lib_provider& lib_provider, + workspaces::parse_lib_provider& lib_provider, statement_fields_parser& parser, processing_tracer* tracer) : diagnosable_ctx(hlasm_ctx) @@ -46,9 +44,9 @@ processing_manager::processing_manager(std::unique_ptr base_p switch (data.proc_kind) { case processing_kind::ORDINARY: - provs_.emplace_back(std::make_unique(hlasm_ctx, parser)); + provs_.emplace_back(std::make_unique(hlasm_ctx, parser, lib_provider, *this)); procs_.emplace_back( - std::make_unique(hlasm_ctx, *this, *this, lib_provider, *this, parser, tracer_)); + std::make_unique(hlasm_ctx, *this, lib_provider, *this, parser, tracer_)); break; case processing_kind::COPY: hlasm_ctx.push_statement_processing(processing_kind::COPY, std::move(file_name)); @@ -64,7 +62,7 @@ processing_manager::processing_manager(std::unique_ptr base_p break; } - provs_.emplace_back(std::make_unique(hlasm_ctx, parser)); + provs_.emplace_back(std::make_unique(hlasm_ctx, parser, lib_provider, *this)); provs_.emplace_back(std::move(base_provider)); } @@ -119,8 +117,22 @@ void processing_manager::start_processing(std::atomic* cancel) } } +bool processing_manager::attr_lookahead_active() const +{ + auto look_pr = dynamic_cast(&*procs_.back()); + return look_pr && look_pr->action == lookahead_action::ORD; +} + statement_provider& processing_manager::find_provider() { + if (attr_lookahead_active()) + { + auto& opencode_prov = **(provs_.end() - 1); + auto& copy_prov = **(provs_.end() - 2); + auto& prov = !copy_prov.finished() ? copy_prov : opencode_prov; + return prov; + } + for (auto& prov : provs_) { if (!prov->finished()) @@ -157,6 +169,11 @@ void processing_manager::finish_macro_definition(macrodef_processing_result resu void processing_manager::start_lookahead(lookahead_start_data start) { + // jump to the statement where the previous lookahead stopped + if (hlasm_ctx_.current_source().end_index < lookahead_stop_.end_index) + perform_opencode_jump( + context::source_position(lookahead_stop_.end_line + 1, lookahead_stop_.end_index), lookahead_stop_); + hlasm_ctx_.push_statement_processing(processing_kind::LOOKAHEAD); procs_.emplace_back( std::make_unique(hlasm_ctx_, *this, *this, lib_provider_, std::move(start))); @@ -164,16 +181,25 @@ void processing_manager::start_lookahead(lookahead_start_data start) void processing_manager::finish_lookahead(lookahead_processing_result result) { - if (result.success) - jump_in_statements(result.symbol_name, result.symbol_range); - else + lookahead_stop_ = hlasm_ctx_.current_source().create_snapshot(); + + if (result.action == lookahead_action::SEQ) { - perform_opencode_jump(result.statement_position, std::move(result.snapshot)); + if (result.success) + jump_in_statements(result.symbol_name, result.symbol_range); + else + { + perform_opencode_jump(result.statement_position, std::move(result.snapshot)); - empty_processor tmp(hlasm_ctx_); // skip next statement - find_provider().process_next(tmp); + add_diagnostic(diagnostic_op::error_E047(*result.symbol_name, result.symbol_range)); + } + } + else + { + if (hlasm_ctx_.current_scope().this_macro) + --hlasm_ctx_.current_scope().this_macro->current_statement; - add_diagnostic(diagnostic_op::error_E047(*result.symbol_name, result.symbol_range)); + perform_opencode_jump(result.statement_position, std::move(result.snapshot)); } } @@ -200,9 +226,9 @@ void processing_manager::jump_in_statements(context::id_index target, range symb } else { - auto open_symbol = create_opencode_sequence_symbol(nullptr, range()); - start_lookahead(lookahead_start_data( - target, symbol_range, std::move(open_symbol->statement_position), std::move(open_symbol->snapshot))); + auto&& [statement_position, snapshot] = hlasm_ctx_.get_end_snapshot(); + start_lookahead( + lookahead_start_data(target, symbol_range, std::move(statement_position), std::move(snapshot))); } } else @@ -226,10 +252,10 @@ void processing_manager::jump_in_statements(context::id_index target, range symb void processing_manager::register_sequence_symbol(context::id_index target, range symbol_range) { - if (hlasm_ctx_.is_in_macro()) + if (!attr_lookahead_active() && hlasm_ctx_.is_in_macro()) return; - auto symbol = hlasm_ctx_.get_sequence_symbol(target); + auto symbol = hlasm_ctx_.get_opencode_sequence_symbol(target); auto new_symbol = create_opencode_sequence_symbol(target, symbol_range); if (!symbol) @@ -248,20 +274,7 @@ std::unique_ptr processing_manager::create_op auto symbol_pos = symbol_range.start; location loc(symbol_pos, hlasm_ctx_.processing_stack().back().proc_location.file); - context::source_position statement_position; - - if (hlasm_ctx_.current_source().copy_stack.empty()) - { - statement_position.file_offset = hlasm_ctx_.current_source().begin_index; - statement_position.file_line = (size_t)hlasm_ctx_.current_source().current_instruction.pos.line; - } - else - { - statement_position.file_offset = hlasm_ctx_.current_source().end_index; - statement_position.file_line = hlasm_ctx_.current_source().end_line + 1; - } - - auto snapshot = hlasm_ctx_.current_source().create_snapshot(); + auto&& [statement_position, snapshot] = hlasm_ctx_.get_begin_snapshot(attr_lookahead_active()); return std::make_unique(name, loc, statement_position, std::move(snapshot)); } @@ -274,61 +287,6 @@ void processing_manager::perform_opencode_jump( hlasm_ctx_.apply_source_snapshot(std::move(snapshot)); } -const attribute_provider::resolved_reference_storage& processing_manager::lookup_forward_attribute_references( - attribute_provider::forward_reference_storage references) -{ - if (references.empty()) - return resolved_symbols; - - bool all_resolved = true; - for (auto ref : references) - all_resolved &= resolved_symbols.find(ref) != resolved_symbols.end(); - - if (all_resolved) - return resolved_symbols; - - lookahead_processor proc(hlasm_ctx_, *this, *this, lib_provider_, lookahead_start_data(std::move(references))); - - context::source_snapshot snapshot = hlasm_ctx_.current_source().create_snapshot(); - if (!snapshot.copy_frames.empty()) - ++snapshot.copy_frames.back().statement_offset; - - context::source_position statement_position( - (size_t)hlasm_ctx_.current_source().end_line + 1, hlasm_ctx_.current_source().end_index); - - if (attr_lookahead_stop_ && hlasm_ctx_.current_source().end_index < attr_lookahead_stop_->end_index) - perform_opencode_jump( - context::source_position(attr_lookahead_stop_->end_line + 1, attr_lookahead_stop_->end_index), - *attr_lookahead_stop_); - - opencode_prov_.push_line_end(); - - while (true) - { - // macro statement provider is not relevant in attribute lookahead - // provs_.size() is always more than 2, it results from calling constructor - auto& opencode_prov = **(provs_.end() - 1); - auto& copy_prov = **(provs_.end() - 2); - auto& prov = !copy_prov.finished() ? copy_prov : opencode_prov; - - if (prov.finished() || proc.finished()) - break; - - prov.process_next(proc); - } - - attr_lookahead_stop_ = hlasm_ctx_.current_source().create_snapshot(); - - perform_opencode_jump(statement_position, std::move(snapshot)); - - auto ret = proc.collect_found_refereces(); - - for (auto& sym : ret) - resolved_symbols.insert(std::move(sym)); - - return resolved_symbols; -} - void processing_manager::collect_diags() const { for (auto& proc : procs_) @@ -336,3 +294,5 @@ void processing_manager::collect_diags() const collect_diags_from_child(dynamic_cast(*provs_.back())); } + +} // namespace hlasm_plugin::parser_library::processing diff --git a/parser_library/src/processing/processing_manager.h b/parser_library/src/processing/processing_manager.h index fa253efbb..fa100322f 100644 --- a/parser_library/src/processing/processing_manager.h +++ b/parser_library/src/processing/processing_manager.h @@ -18,7 +18,6 @@ #include #include -#include "attribute_provider.h" #include "branching_provider.h" #include "opencode_provider.h" #include "processing_state_listener.h" @@ -34,10 +33,7 @@ namespace processing { // is constructed with base statement provider and has stack of statement processors which take statements from // providers and go through the code creating other providers and processors it holds those providers and processors and // manages the whole processing -class processing_manager : public processing_state_listener, - public branching_provider, - public attribute_provider, - public diagnosable_ctx +class processing_manager : public processing_state_listener, public branching_provider, public diagnosable_ctx { public: processing_manager(std::unique_ptr base_provider, @@ -56,11 +52,16 @@ class processing_manager : public processing_state_listener, private: context::hlasm_context& hlasm_ctx_; workspaces::parse_lib_provider& lib_provider_; + opencode_provider& opencode_prov_; std::vector procs_; std::vector provs_; - opencode_provider& opencode_prov_; + context::source_snapshot lookahead_stop_; + + processing_tracer* tracer_ = nullptr; + + bool attr_lookahead_active() const; statement_provider& find_provider(); void finish_processor(); @@ -77,13 +78,7 @@ class processing_manager : public processing_state_listener, std::unique_ptr create_opencode_sequence_symbol( context::id_index name, range symbol_range); - std::optional attr_lookahead_stop_; - virtual const attribute_provider::resolved_reference_storage& lookup_forward_attribute_references( - attribute_provider::forward_reference_storage references) override; - void perform_opencode_jump(context::source_position statement_position, context::source_snapshot snapshot); - - processing_tracer* tracer_ = nullptr; }; } // namespace processing diff --git a/parser_library/src/processing/statement_processors/lookahead_processing_info.h b/parser_library/src/processing/statement_processors/lookahead_processing_info.h index 1aefbb117..cd7162d3a 100644 --- a/parser_library/src/processing/statement_processors/lookahead_processing_info.h +++ b/parser_library/src/processing/statement_processors/lookahead_processing_info.h @@ -15,12 +15,12 @@ #ifndef PROCESSING_LOOKAHEAD_PROCESSING_INFO_H #define PROCESSING_LOOKAHEAD_PROCESSING_INFO_H +#include + +#include "context/ordinary_assembly/symbol.h" #include "context/source_snapshot.h" -#include "processing/attribute_provider.h" -namespace hlasm_plugin { -namespace parser_library { -namespace processing { +namespace hlasm_plugin::parser_library::processing { enum class lookahead_action { @@ -51,10 +51,14 @@ struct lookahead_start_data {} // ORD action - processing::attribute_provider::forward_reference_storage targets; + std::set targets; - lookahead_start_data(processing::attribute_provider::forward_reference_storage targets) + lookahead_start_data(std::set targets, + context::source_position statement_position, + context::source_snapshot snapshot) : action(lookahead_action::ORD) + , statement_position(statement_position) + , snapshot(std::move(snapshot)) , target(nullptr) , targets(targets) {} @@ -63,6 +67,7 @@ struct lookahead_start_data // result of lookahead_processor struct lookahead_processing_result { + lookahead_action action; bool success; context::source_position statement_position; @@ -71,10 +76,9 @@ struct lookahead_processing_result context::id_index symbol_name; range symbol_range; - processing::attribute_provider::resolved_reference_storage resolved_refs; - lookahead_processing_result(lookahead_start_data&& initial_data) - : success(false) + : action(initial_data.action) + , success(false) , statement_position(initial_data.statement_position) , snapshot(std::move(initial_data.snapshot)) , symbol_name(initial_data.target) @@ -82,19 +86,13 @@ struct lookahead_processing_result {} lookahead_processing_result(context::id_index target, range target_range) - : success(true) + : action(lookahead_action::SEQ) + , success(true) , symbol_name(target) , symbol_range(target_range) {} - - lookahead_processing_result(processing::attribute_provider::resolved_reference_storage targets) - : success(true) - , symbol_name(nullptr) - , resolved_refs(std::move(targets)) - {} }; -} // namespace processing -} // namespace parser_library -} // namespace hlasm_plugin +} // namespace hlasm_plugin::parser_library::processing + #endif diff --git a/parser_library/src/processing/statement_processors/lookahead_processor.cpp b/parser_library/src/processing/statement_processors/lookahead_processor.cpp index 3377e9349..d34f7c376 100644 --- a/parser_library/src/processing/statement_processors/lookahead_processor.cpp +++ b/parser_library/src/processing/statement_processors/lookahead_processor.cpp @@ -19,8 +19,7 @@ #include "ordinary_processor.h" #include "processing/instruction_sets/asm_processor.h" -using namespace hlasm_plugin::parser_library; -using namespace hlasm_plugin::parser_library::processing; +namespace hlasm_plugin::parser_library::processing { processing_status lookahead_processor::get_processing_status(const semantics::instruction_si& instruction) const { @@ -52,6 +51,9 @@ void lookahead_processor::end_processing() { hlasm_ctx.pop_statement_processing(); + for (auto&& symbol_name : to_find_) + register_attr_ref(symbol_name, context::symbol_attributes(context::symbol_origin::UNKNOWN)); + listener_.finish_lookahead(std::move(result_)); finished_flag_ = true; @@ -64,12 +66,6 @@ bool lookahead_processor::terminal_condition(const statement_provider_kind prov_ bool lookahead_processor::finished() { return finished_flag_; } -attribute_provider::resolved_reference_storage lookahead_processor::collect_found_refereces() -{ - finished_flag_ = true; - return std::move(result_.resolved_refs); -} - void lookahead_processor::collect_diags() const {} lookahead_processor::lookahead_processor(context::hlasm_context& hlasm_ctx, @@ -181,14 +177,12 @@ void lookahead_processor::assign_EQU_attributes(context::id_index symbol_name, c if (len_symbol != nullptr && len_symbol->kind() != context::symbol_value_kind::UNDEF) length_attr = len_symbol->attributes().length(); } + else + length_attr = 1; } } - result_.resolved_refs.try_emplace(symbol_name, - symbol_name, - context::symbol_value(), - context::symbol_attributes(context::symbol_origin::DAT, t_attr, length_attr), - location()); + register_attr_ref(symbol_name, context::symbol_attributes(context::symbol_origin::DAT, t_attr, length_attr)); } void lookahead_processor::assign_data_def_attributes(context::id_index symbol_name, const resolved_statement& statement) @@ -219,20 +213,12 @@ void lookahead_processor::assign_data_def_attributes(context::id_index symbol_na scale = value->get_scale_attribute(); } - result_.resolved_refs.try_emplace(symbol_name, - symbol_name, - context::symbol_value(), - context::symbol_attributes(context::symbol_origin::DAT, type, len, scale), - location()); + register_attr_ref(symbol_name, context::symbol_attributes(context::symbol_origin::DAT, type, len, scale)); } void lookahead_processor::assign_section_attributes(context::id_index symbol_name, const resolved_statement&) { - result_.resolved_refs.try_emplace(symbol_name, - symbol_name, - context::symbol_value(), - context::symbol_attributes::make_section_attrs(), - location()); + register_attr_ref(symbol_name, context::symbol_attributes::make_section_attrs()); } void lookahead_processor::assign_machine_attributes(context::id_index symbol_name, const resolved_statement& statement) @@ -243,12 +229,9 @@ void lookahead_processor::assign_machine_attributes(context::id_index symbol_nam ? context::instruction::machine_instructions.find(mnem_tmp->second.instruction) : context::instruction::machine_instructions.find(*statement.opcode_ref().value); - result_.resolved_refs.try_emplace(symbol_name, - symbol_name, - context::symbol_value(), + register_attr_ref(symbol_name, context::symbol_attributes::make_machine_attrs( - (context::symbol_attributes::len_attr)tmp_instr->second->size_for_alloc / 8), - location()); + (context::symbol_attributes::len_attr)tmp_instr->second->size_for_alloc / 8)); } void lookahead_processor::assign_assembler_attributes( @@ -261,19 +244,16 @@ void lookahead_processor::assign_assembler_attributes( func(symbol_name, statement); } else - { - result_.resolved_refs.try_emplace(symbol_name, - symbol_name, - context::symbol_value(), - context::symbol_attributes(context::symbol_origin::MACH, 'M'_ebcdic), - location()); - } + register_attr_ref(symbol_name, context::symbol_attributes(context::symbol_origin::MACH, 'M'_ebcdic)); } void lookahead_processor::process_statement(const context::hlasm_statement& statement) { if (macro_nest_ == 0) - find_target(statement); + { + find_seq(dynamic_cast(statement)); + find_ord(dynamic_cast(statement)); + } auto resolved = statement.access_resolved(); @@ -294,27 +274,11 @@ void lookahead_processor::process_statement(const context::hlasm_statement& stat } } -void lookahead_processor::find_target(const context::hlasm_statement& statement) -{ - switch (action) - { - case lookahead_action::SEQ: - find_seq(dynamic_cast(statement)); - break; - case lookahead_action::ORD: - find_ord(dynamic_cast(statement)); - break; - default: - assert(false); - break; - } -} - void lookahead_processor::find_seq(const semantics::core_statement& statement) { if (statement.label_ref().type == semantics::label_si_type::SEQ) { - auto symbol = std::get(statement.label_ref().value); + const auto& symbol = std::get(statement.label_ref().value); branch_provider_.register_sequence_symbol(symbol.name, symbol.symbol_range); @@ -347,12 +311,9 @@ void lookahead_processor::find_ord(const resolved_statement& statement) case context::instruction_type::CA: case context::instruction_type::UNDEF: case context::instruction_type::MAC: - result_.resolved_refs.try_emplace(id, - id, - context::symbol_value(), + register_attr_ref(id, context::symbol_attributes(context::symbol_origin::MACH, - statement.opcode_ref().type == context::instruction_type::CA ? 'U'_ebcdic : 'M'_ebcdic), - location()); + statement.opcode_ref().type == context::instruction_type::CA ? 'U'_ebcdic : 'M'_ebcdic)); break; case context::instruction_type::MACH: assign_machine_attributes(id, statement); @@ -365,5 +326,12 @@ void lookahead_processor::find_ord(const resolved_statement& statement) break; } - finished_flag_ = to_find_.empty(); + finished_flag_ = action == lookahead_action::ORD && to_find_.empty(); } + +void lookahead_processor::register_attr_ref(context::id_index name, context::symbol_attributes attributes) +{ + hlasm_ctx.ord_ctx.add_symbol_reference(context::symbol(name, context::symbol_value(), attributes, location())); +} + +} // namespace hlasm_plugin::parser_library::processing diff --git a/parser_library/src/processing/statement_processors/lookahead_processor.h b/parser_library/src/processing/statement_processors/lookahead_processor.h index 85981e129..a2e4777e0 100644 --- a/parser_library/src/processing/statement_processors/lookahead_processor.h +++ b/parser_library/src/processing/statement_processors/lookahead_processor.h @@ -21,9 +21,7 @@ #include "statement_processor.h" #include "workspaces/parse_lib_provider.h" -namespace hlasm_plugin { -namespace parser_library { -namespace processing { +namespace hlasm_plugin::parser_library::processing { // processor used for lookahead, hence finding desired symbol class lookahead_processor : public statement_processor @@ -38,7 +36,7 @@ class lookahead_processor : public statement_processor processing_state_listener& listener_; workspaces::parse_lib_provider& lib_provider_; - processing::attribute_provider::forward_reference_storage to_find_; + std::set to_find_; context::id_index target_; public: @@ -57,8 +55,6 @@ class lookahead_processor : public statement_processor virtual bool terminal_condition(const statement_provider_kind kind) const override; virtual bool finished() override; - attribute_provider::resolved_reference_storage collect_found_refereces(); - virtual void collect_diags() const override; private: @@ -78,12 +74,12 @@ class lookahead_processor : public statement_processor void process_statement(const context::hlasm_statement& statement); - void find_target(const context::hlasm_statement& statement); void find_seq(const semantics::core_statement& statement); void find_ord(const resolved_statement& statement); + + void register_attr_ref(context::id_index name, context::symbol_attributes attributes); }; -} // namespace processing -} // namespace parser_library -} // namespace hlasm_plugin +} // namespace hlasm_plugin::parser_library::processing + #endif diff --git a/parser_library/src/processing/statement_processors/macrodef_processor.cpp b/parser_library/src/processing/statement_processors/macrodef_processor.cpp index e4110ee12..9e941664c 100644 --- a/parser_library/src/processing/statement_processors/macrodef_processor.cpp +++ b/parser_library/src/processing/statement_processors/macrodef_processor.cpp @@ -273,7 +273,7 @@ void macrodef_processor::process_prototype_operand( continue; } - auto tmp = op->access_mac(); + auto tmp = op->access_mac()->access_chain(); assert(tmp); auto& tmp_chain = tmp->chain; diff --git a/parser_library/src/processing/statement_processors/ordinary_processor.cpp b/parser_library/src/processing/statement_processors/ordinary_processor.cpp index d19471110..d124d1bab 100644 --- a/parser_library/src/processing/statement_processors/ordinary_processor.cpp +++ b/parser_library/src/processing/statement_processors/ordinary_processor.cpp @@ -23,18 +23,17 @@ using namespace hlasm_plugin::parser_library::processing; using namespace hlasm_plugin::parser_library::workspaces; ordinary_processor::ordinary_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, parse_lib_provider& lib_provider, processing_state_listener& state_listener, statement_fields_parser& parser, processing_tracer* tracer) : statement_processor(processing_kind::ORDINARY, hlasm_ctx) - , eval_ctx { hlasm_ctx, attr_provider, lib_provider } - , ca_proc_(hlasm_ctx, attr_provider, branch_provider, lib_provider, state_listener) - , mac_proc_(hlasm_ctx, attr_provider, branch_provider, lib_provider) - , asm_proc_(hlasm_ctx, attr_provider, branch_provider, lib_provider, parser) - , mach_proc_(hlasm_ctx, attr_provider, branch_provider, lib_provider, parser) + , eval_ctx { hlasm_ctx, lib_provider } + , ca_proc_(hlasm_ctx, branch_provider, lib_provider, state_listener) + , mac_proc_(hlasm_ctx, branch_provider, lib_provider) + , asm_proc_(hlasm_ctx, branch_provider, lib_provider, parser) + , mach_proc_(hlasm_ctx, branch_provider, lib_provider, parser) , finished_flag_(false) , tracer_(tracer) {} diff --git a/parser_library/src/processing/statement_processors/ordinary_processor.h b/parser_library/src/processing/statement_processors/ordinary_processor.h index c26112b28..6af849407 100644 --- a/parser_library/src/processing/statement_processors/ordinary_processor.h +++ b/parser_library/src/processing/statement_processors/ordinary_processor.h @@ -44,7 +44,6 @@ class ordinary_processor : public statement_processor public: ordinary_processor(context::hlasm_context& hlasm_ctx, - attribute_provider& attr_provider, branching_provider& branch_provider, workspaces::parse_lib_provider& lib_provider, processing_state_listener& state_listener, diff --git a/parser_library/src/processing/statement_providers/common_statement_provider.cpp b/parser_library/src/processing/statement_providers/common_statement_provider.cpp deleted file mode 100644 index 1d3fb697f..000000000 --- a/parser_library/src/processing/statement_providers/common_statement_provider.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2019 Broadcom. - * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Broadcom, Inc. - initial API and implementation - */ - -#include "common_statement_provider.h" - -using namespace hlasm_plugin::parser_library; -using namespace hlasm_plugin::parser_library::processing; - -common_statement_provider::common_statement_provider( - const statement_provider_kind kind, context::hlasm_context& hlasm_ctx, statement_fields_parser& parser) - : statement_provider(kind) - , hlasm_ctx(hlasm_ctx) - , parser(parser) -{} - -void common_statement_provider::preprocess_deferred( - statement_processor& processor, context::cached_statement_storage& cache) -{ - const auto& def_stmt = *cache.get_base()->access_deferred(); - - auto status = processor.get_processing_status(def_stmt.instruction_ref()); - - if (status.first.form == processing_form::DEFERRED) - { - processor.process_statement(cache.get_base()); - } - else if (!cache.contains(status.first.form)) - { - context::cached_statement_storage::cache_entry_t ptr; - auto def_impl = std::dynamic_pointer_cast(cache.get_base()); - - if (status.first.occurence == operand_occurence::ABSENT || status.first.form == processing_form::UNKNOWN - || status.first.form == processing_form::IGNORED) - { - semantics::operands_si op(def_stmt.deferred_range_ref(), semantics::operand_list()); - semantics::remarks_si rem(def_stmt.deferred_range_ref(), {}); - - ptr = std::make_shared(def_impl, std::move(op), std::move(rem)); - } - else - { - auto [op, rem] = parser.parse_operand_field(&hlasm_ctx, - def_stmt.deferred_ref(), - false, - semantics::range_provider(def_stmt.deferred_range_ref(), semantics::adjusting_state::NONE), - status); - - ptr = std::make_shared(def_impl, std::move(op), std::move(rem)); - } - - cache.insert(status.first.form, ptr); - context::unique_stmt_ptr resolved = std::make_unique(ptr, status.second, status.first); - processor.process_statement(std::move(resolved)); - } - else - { - auto ptr = cache.get(status.first.form); - context::unique_stmt_ptr resolved = std::make_unique(ptr, status.second, status.first); - processor.process_statement(std::move(resolved)); - } -} diff --git a/parser_library/src/processing/statement_providers/common_statement_provider.h b/parser_library/src/processing/statement_providers/common_statement_provider.h deleted file mode 100644 index 930b12768..000000000 --- a/parser_library/src/processing/statement_providers/common_statement_provider.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2019 Broadcom. - * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Broadcom, Inc. - initial API and implementation - */ - -#ifndef PROCESSING_COMMON_STATEMENT_PROVIDER_H -#define PROCESSING_COMMON_STATEMENT_PROVIDER_H - -#include "context/hlasm_context.h" -#include "processing/statement_fields_parser.h" -#include "statement_provider.h" - - -namespace hlasm_plugin { -namespace parser_library { -namespace processing { - -// common class for more complicated statement providers -class common_statement_provider : public statement_provider -{ -public: - common_statement_provider( - const statement_provider_kind kind, context::hlasm_context& hlasm_ctx, statement_fields_parser& parser); - -protected: - context::hlasm_context& hlasm_ctx; - statement_fields_parser& parser; - - void preprocess_deferred(statement_processor& processor, context::cached_statement_storage& cache); -}; - -} // namespace processing -} // namespace parser_library -} // namespace hlasm_plugin -#endif diff --git a/parser_library/src/processing/statement_providers/copy_statement_provider.cpp b/parser_library/src/processing/statement_providers/copy_statement_provider.cpp index 51581ce34..9101f2b3f 100644 --- a/parser_library/src/processing/statement_providers/copy_statement_provider.cpp +++ b/parser_library/src/processing/statement_providers/copy_statement_provider.cpp @@ -14,40 +14,29 @@ #include "copy_statement_provider.h" -using namespace hlasm_plugin::parser_library; -using namespace hlasm_plugin::parser_library::processing; +namespace hlasm_plugin::parser_library::processing { -copy_statement_provider::copy_statement_provider(context::hlasm_context& hlasm_ctx, statement_fields_parser& parser) - : common_statement_provider(statement_provider_kind::COPY, hlasm_ctx, parser) +copy_statement_provider::copy_statement_provider(context::hlasm_context& hlasm_ctx, + statement_fields_parser& parser, + workspaces::parse_lib_provider& lib_provider, + processing::processing_state_listener& listener) + : members_statement_provider(statement_provider_kind::COPY, hlasm_ctx, parser, lib_provider, listener) {} -void copy_statement_provider::process_next(statement_processor& processor) -{ - if (finished()) - throw std::runtime_error("provider already finished"); +bool copy_statement_provider::finished() const { return hlasm_ctx.current_copy_stack().empty(); } +context::cached_statement_storage* copy_statement_provider::get_next() +{ auto& invo = hlasm_ctx.current_copy_stack().back(); ++invo.current_statement; if ((size_t)invo.current_statement == invo.cached_definition.size()) { hlasm_ctx.leave_copy_member(); - return; + return nullptr; } - auto& cache = invo.cached_definition[invo.current_statement]; - - switch (cache.get_base()->kind) - { - case context::statement_kind::RESOLVED: - processor.process_statement(cache.get_base()); - break; - case context::statement_kind::DEFERRED: - preprocess_deferred(processor, cache); - break; - default: - break; - } + return &invo.cached_definition[invo.current_statement]; } -bool copy_statement_provider::finished() const { return hlasm_ctx.current_copy_stack().empty(); } +} // namespace hlasm_plugin::parser_library::processing diff --git a/parser_library/src/processing/statement_providers/copy_statement_provider.h b/parser_library/src/processing/statement_providers/copy_statement_provider.h index 78d85a7df..11ed28891 100644 --- a/parser_library/src/processing/statement_providers/copy_statement_provider.h +++ b/parser_library/src/processing/statement_providers/copy_statement_provider.h @@ -15,24 +15,25 @@ #ifndef PROCESSING_COPY_STATEMENT_PROVIDER_H #define PROCESSING_COPY_STATEMENT_PROVIDER_H -#include "common_statement_provider.h" +#include "members_statement_provider.h" -namespace hlasm_plugin { -namespace parser_library { -namespace processing { +namespace hlasm_plugin::parser_library::processing { // statement provider providing statements of copy members -class copy_statement_provider : public common_statement_provider +class copy_statement_provider : public members_statement_provider { public: - copy_statement_provider(context::hlasm_context& hlasm_ctx, statement_fields_parser& parser); - - virtual void process_next(statement_processor& processor) override; + copy_statement_provider(context::hlasm_context& hlasm_ctx, + statement_fields_parser& parser, + workspaces::parse_lib_provider& lib_provider, + processing::processing_state_listener& listener); virtual bool finished() const override; + +protected: + virtual context::cached_statement_storage* get_next() override; }; -} // namespace processing -} // namespace parser_library -} // namespace hlasm_plugin +} // namespace hlasm_plugin::parser_library::processing + #endif diff --git a/parser_library/src/processing/statement_providers/macro_statement_provider.cpp b/parser_library/src/processing/statement_providers/macro_statement_provider.cpp index 11157e407..9b025ebc1 100644 --- a/parser_library/src/processing/statement_providers/macro_statement_provider.cpp +++ b/parser_library/src/processing/statement_providers/macro_statement_provider.cpp @@ -16,18 +16,19 @@ #include "processing/processing_manager.h" -using namespace hlasm_plugin::parser_library; -using namespace hlasm_plugin::parser_library::processing; +namespace hlasm_plugin::parser_library::processing { -macro_statement_provider::macro_statement_provider(context::hlasm_context& hlasm_ctx, statement_fields_parser& parser) - : common_statement_provider(statement_provider_kind::MACRO, hlasm_ctx, parser) +macro_statement_provider::macro_statement_provider(context::hlasm_context& hlasm_ctx, + statement_fields_parser& parser, + workspaces::parse_lib_provider& lib_provider, + processing::processing_state_listener& listener) + : members_statement_provider(statement_provider_kind::MACRO, hlasm_ctx, parser, lib_provider, listener) {} -void macro_statement_provider::process_next(statement_processor& processor) -{ - if (finished()) - throw std::runtime_error("provider already finished"); +bool macro_statement_provider::finished() const { return hlasm_ctx.scope_stack().size() == 1; } +context::cached_statement_storage* macro_statement_provider::get_next() +{ auto& invo = hlasm_ctx.scope_stack().back().this_macro; assert(invo); @@ -35,22 +36,10 @@ void macro_statement_provider::process_next(statement_processor& processor) if ((size_t)invo->current_statement == invo->cached_definition.size()) { hlasm_ctx.leave_macro(); - return; + return nullptr; } - auto& cache = invo->cached_definition[invo->current_statement]; - - switch (cache.get_base()->kind) - { - case context::statement_kind::RESOLVED: - processor.process_statement(cache.get_base()); - break; - case context::statement_kind::DEFERRED: - preprocess_deferred(processor, cache); - break; - default: - break; - } + return &invo->cached_definition[invo->current_statement]; } -bool macro_statement_provider::finished() const { return hlasm_ctx.scope_stack().size() == 1; } +} // namespace hlasm_plugin::parser_library::processing diff --git a/parser_library/src/processing/statement_providers/macro_statement_provider.h b/parser_library/src/processing/statement_providers/macro_statement_provider.h index 4d8cd04f1..a786f508d 100644 --- a/parser_library/src/processing/statement_providers/macro_statement_provider.h +++ b/parser_library/src/processing/statement_providers/macro_statement_provider.h @@ -15,21 +15,25 @@ #ifndef PROCESSING_MACRO_STATEMENT_PROVIDER_H #define PROCESSING_MACRO_STATEMENT_PROVIDER_H -#include "common_statement_provider.h" +#include "members_statement_provider.h" namespace hlasm_plugin { namespace parser_library { namespace processing { // statement provider providing statements of macro defintion -class macro_statement_provider : public common_statement_provider +class macro_statement_provider : public members_statement_provider { public: - macro_statement_provider(context::hlasm_context& hlasm_ctx, statement_fields_parser& parser); - - virtual void process_next(statement_processor& processor) override; + macro_statement_provider(context::hlasm_context& hlasm_ctx, + statement_fields_parser& parser, + workspaces::parse_lib_provider& lib_provider, + processing::processing_state_listener& listener); virtual bool finished() const override; + +protected: + virtual context::cached_statement_storage* get_next() override; }; } // namespace processing diff --git a/parser_library/src/processing/statement_providers/members_statement_provider.cpp b/parser_library/src/processing/statement_providers/members_statement_provider.cpp new file mode 100644 index 000000000..d5029a8a3 --- /dev/null +++ b/parser_library/src/processing/statement_providers/members_statement_provider.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2019 Broadcom. + * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + */ + +#include "members_statement_provider.h" + +namespace hlasm_plugin::parser_library::processing { + +members_statement_provider::members_statement_provider(const statement_provider_kind kind, + context::hlasm_context& hlasm_ctx, + statement_fields_parser& parser, + workspaces::parse_lib_provider& lib_provider, + processing::processing_state_listener& listener) + : statement_provider(kind) + , hlasm_ctx(hlasm_ctx) + , parser(parser) + , lib_provider(lib_provider) + , listener(listener) +{} + +void members_statement_provider::process_next(statement_processor& processor) +{ + if (finished()) + throw std::runtime_error("provider already finished"); + + auto cache = get_next(); + + if (!cache) + return; + + if (processor.kind == processing_kind::ORDINARY + && try_trigger_attribute_lookahead(retrieve_instruction(*cache), { hlasm_ctx, lib_provider }, listener)) + return; + + switch (cache->get_base()->kind) + { + case context::statement_kind::RESOLVED: + do_process_statement(processor, cache->get_base()); + break; + case context::statement_kind::DEFERRED: + preprocess_deferred(processor, *cache); + break; + default: + assert(false); + break; + } +} + +const semantics::instruction_si& members_statement_provider::retrieve_instruction( + context::cached_statement_storage& cache) const +{ + switch (cache.get_base()->kind) + { + case context::statement_kind::RESOLVED: + return cache.get_base()->access_resolved()->instruction_ref(); + case context::statement_kind::DEFERRED: + return cache.get_base()->access_deferred()->instruction_ref(); + default: + assert(false); + throw std::runtime_error("unexpected statement_kind enum value"); + } +} + +void members_statement_provider::fill_cache(context::cached_statement_storage& cache, + const semantics::deferred_statement& def_stmt, + const processing_status& status) +{ + context::cached_statement_storage::cache_entry_t ptr; + auto def_impl = std::dynamic_pointer_cast(cache.get_base()); + + if (status.first.occurence == operand_occurence::ABSENT || status.first.form == processing_form::UNKNOWN + || status.first.form == processing_form::IGNORED) + { + semantics::operands_si op(def_stmt.deferred_range_ref(), semantics::operand_list()); + semantics::remarks_si rem(def_stmt.deferred_range_ref(), {}); + + ptr = std::make_shared(def_impl, std::move(op), std::move(rem)); + } + else + { + auto [op, rem] = parser.parse_operand_field(&hlasm_ctx, + def_stmt.deferred_ref(), + false, + semantics::range_provider(def_stmt.deferred_range_ref(), semantics::adjusting_state::NONE), + status); + + ptr = std::make_shared(def_impl, std::move(op), std::move(rem)); + } + cache.insert(status.first.form, ptr); +} + +void members_statement_provider::preprocess_deferred( + statement_processor& processor, context::cached_statement_storage& cache) +{ + const auto& def_stmt = *cache.get_base()->access_deferred(); + + auto status = processor.get_processing_status(def_stmt.instruction_ref()); + + if (status.first.form == processing_form::DEFERRED) + { + do_process_statement(processor, cache.get_base()); + return; + } + + if (!cache.contains(status.first.form)) + fill_cache(cache, def_stmt, status); + + context::unique_stmt_ptr cached = + std::make_unique(cache.get(status.first.form), status.second, status.first); + + do_process_statement(processor, std::move(cached)); +} + +} // namespace hlasm_plugin::parser_library::processing diff --git a/parser_library/src/processing/statement_providers/members_statement_provider.h b/parser_library/src/processing/statement_providers/members_statement_provider.h new file mode 100644 index 000000000..39137593d --- /dev/null +++ b/parser_library/src/processing/statement_providers/members_statement_provider.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019 Broadcom. + * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + */ + +#ifndef PROCESSING_MEMBERS_STATEMENT_PROVIDER_H +#define PROCESSING_MEMBERS_STATEMENT_PROVIDER_H + +#include "context/cached_statement.h" +#include "context/hlasm_context.h" +#include "expressions/evaluation_context.h" +#include "processing/processing_state_listener.h" +#include "processing/statement_fields_parser.h" +#include "statement_provider.h" + +namespace hlasm_plugin::parser_library::processing { + +// common class for copy and macro statement providers (provider of copy and macro members) +class members_statement_provider : public statement_provider +{ +public: + members_statement_provider(const statement_provider_kind kind, + context::hlasm_context& hlasm_ctx, + statement_fields_parser& parser, + workspaces::parse_lib_provider& lib_provider, + processing::processing_state_listener& listener); + + virtual void process_next(statement_processor& processor) override; + +protected: + context::hlasm_context& hlasm_ctx; + statement_fields_parser& parser; + workspaces::parse_lib_provider& lib_provider; + processing::processing_state_listener& listener; + + virtual context::cached_statement_storage* get_next() = 0; + +private: + const semantics::instruction_si& retrieve_instruction(context::cached_statement_storage& cache) const; + + void fill_cache(context::cached_statement_storage& cache, + const semantics::deferred_statement& def_stmt, + const processing_status& status); + + void preprocess_deferred(statement_processor& processor, context::cached_statement_storage& cache); + + template + void do_process_statement(statement_processor& processor, T statement) + { + if (processor.kind == processing_kind::ORDINARY + && try_trigger_attribute_lookahead(*statement, { hlasm_ctx, lib_provider }, listener)) + return; + + processor.process_statement(std::move(statement)); + } +}; + +} // namespace hlasm_plugin::parser_library::processing + +#endif diff --git a/parser_library/src/processing/statement_providers/statement_provider.cpp b/parser_library/src/processing/statement_providers/statement_provider.cpp new file mode 100644 index 000000000..0bdf806b4 --- /dev/null +++ b/parser_library/src/processing/statement_providers/statement_provider.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2019 Broadcom. + * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + */ + +#include "statement_provider.h" + +#include "expressions/conditional_assembly/terms/ca_var_sym.h" + +namespace hlasm_plugin::parser_library::processing { + +statement_provider::statement_provider(const statement_provider_kind kind) + : kind(kind) +{} + +bool statement_provider::try_trigger_attribute_lookahead(const semantics::instruction_si& instruction, + expressions::evaluation_context eval_ctx, + processing::processing_state_listener& listener) +{ + auto references = process_instruction(instruction, eval_ctx); + + if (references.empty()) + return false; + + trigger_attribute_lookahead(std::move(references), eval_ctx, listener); + + return true; +} + +bool statement_provider::try_trigger_attribute_lookahead(const context::hlasm_statement& statement, + expressions::evaluation_context eval_ctx, + processing::processing_state_listener& listener) +{ + const semantics::label_si* label; + std::set references; + + if (statement.kind == context::statement_kind::DEFERRED) + { + auto def_stmt = statement.access_deferred(); + label = &def_stmt->label_ref(); + } + else + { + auto res_stmt = statement.access_resolved(); + label = &res_stmt->label_ref(); + + references.merge(process_operands(res_stmt->operands_ref(), eval_ctx)); + } + + references.merge(process_label(*label, eval_ctx)); + + if (references.empty()) + return false; + + trigger_attribute_lookahead(std::move(references), eval_ctx, listener); + + return true; +} + +void statement_provider::trigger_attribute_lookahead(std::set references, + const expressions::evaluation_context& eval_ctx, + processing::processing_state_listener& listener) +{ + auto&& [statement_position, snapshot] = eval_ctx.hlasm_ctx.get_begin_snapshot(false); + + listener.start_lookahead(lookahead_start_data(std::move(references), statement_position, std::move(snapshot))); +} + +std::set statement_provider::process_label( + const semantics::label_si& label, const expressions::evaluation_context& eval_ctx) +{ + switch (label.type) + { + case semantics::label_si_type::CONC: + return semantics::concatenation_point::get_undefined_attributed_symbols( + std::get(label.value), eval_ctx); + case semantics::label_si_type::VAR: + return expressions::ca_var_sym::get_undefined_attributed_symbols_vs( + std::get(label.value), eval_ctx); + default: + return {}; + } +} + +std::set statement_provider::process_instruction( + const semantics::instruction_si& instruction, const expressions::evaluation_context& eval_ctx) +{ + if (instruction.type != semantics::instruction_si_type::CONC) + return {}; + + const auto& chain = std::get(instruction.value); + + return semantics::concatenation_point::get_undefined_attributed_symbols(chain, eval_ctx); +} + +std::set statement_provider::process_operands( + const semantics::operands_si& operands, const expressions::evaluation_context& eval_ctx) +{ + std::set ret; + for (const auto& op : operands.value) + { + switch (op->type) + { + case semantics::operand_type::MODEL: + ret.merge(semantics::concatenation_point::get_undefined_attributed_symbols( + op->access_model()->chain, eval_ctx)); + break; + case semantics::operand_type::MAC: + if (op->access_mac()->kind == semantics::mac_kind::CHAIN) + ret.merge(semantics::concatenation_point::get_undefined_attributed_symbols( + op->access_mac()->access_chain()->chain, eval_ctx)); + break; + case semantics::operand_type::CA: + ret.merge(op->access_ca()->get_undefined_attributed_symbols(eval_ctx)); + break; + default: + break; + } + } + return ret; +} + +} // namespace hlasm_plugin::parser_library::processing diff --git a/parser_library/src/processing/statement_providers/statement_provider.h b/parser_library/src/processing/statement_providers/statement_provider.h index ab78291d1..923f34d8e 100644 --- a/parser_library/src/processing/statement_providers/statement_provider.h +++ b/parser_library/src/processing/statement_providers/statement_provider.h @@ -15,13 +15,12 @@ #ifndef PROCESSING_STATEMENT_PROVIDER_H #define PROCESSING_STATEMENT_PROVIDER_H +#include "expressions/evaluation_context.h" +#include "processing/processing_state_listener.h" #include "processing/statement_processors/statement_processor.h" #include "statement_provider_kind.h" - -namespace hlasm_plugin { -namespace parser_library { -namespace processing { +namespace hlasm_plugin::parser_library::processing { class statement_provider; using provider_ptr = std::unique_ptr; @@ -33,9 +32,7 @@ class statement_provider public: const statement_provider_kind kind; - statement_provider(const statement_provider_kind kind) - : kind(kind) - {} + explicit statement_provider(const statement_provider_kind kind); // processes next statement with help of a processor virtual void process_next(statement_processor& processor) = 0; @@ -44,9 +41,28 @@ class statement_provider virtual bool finished() const = 0; virtual ~statement_provider() = default; + +protected: + static bool try_trigger_attribute_lookahead(const semantics::instruction_si& instruction, + expressions::evaluation_context eval_ctx, + processing::processing_state_listener& listener); + static bool try_trigger_attribute_lookahead(const context::hlasm_statement& statement, + expressions::evaluation_context eval_ctx, + processing::processing_state_listener& listener); + +private: + static void trigger_attribute_lookahead(std::set references, + const expressions::evaluation_context& eval_ctx, + processing::processing_state_listener& listener); + + static std::set process_label( + const semantics::label_si& label, const expressions::evaluation_context& eval_ctx); + static std::set process_instruction( + const semantics::instruction_si& instruction, const expressions::evaluation_context& eval_ctx); + static std::set process_operands( + const semantics::operands_si& operands, const expressions::evaluation_context& eval_ctx); }; -} // namespace processing -} // namespace parser_library -} // namespace hlasm_plugin +} // namespace hlasm_plugin::parser_library::processing + #endif diff --git a/parser_library/src/semantics/collector.cpp b/parser_library/src/semantics/collector.cpp index 6f084e1ee..201b5540f 100644 --- a/parser_library/src/semantics/collector.cpp +++ b/parser_library/src/semantics/collector.cpp @@ -22,19 +22,17 @@ using namespace hlasm_plugin::parser_library::semantics; collector::collector() - : lbl_(lbls_) - , instr_(instrs_) - , lsp_symbols_extracted_(false) + : lsp_symbols_extracted_(false) , hl_symbols_extracted_(false) {} -const label_si& collector::current_label() { return **lbl_; } +const label_si& collector::current_label() { return *lbl_; } -bool collector::has_label() const { return lbl_->has_value(); } +bool collector::has_label() const { return lbl_.has_value(); } -const instruction_si& collector::current_instruction() { return **instr_; } +const instruction_si& collector::current_instruction() { return *instr_; } -bool collector::has_instruction() const { return instr_->has_value(); } +bool collector::has_instruction() const { return instr_.has_value(); } const operands_si& collector::current_operands() { return *op_; } @@ -42,28 +40,28 @@ const remarks_si& collector::current_remarks() { return *rem_; } void collector::set_label_field(range symbol_range) { - if (*lbl_) + if (lbl_) throw std::runtime_error("field already assigned"); - lbl_->emplace(symbol_range); + lbl_.emplace(symbol_range); } void collector::set_label_field(std::string label, range symbol_range) { - if (*lbl_) + if (lbl_) throw std::runtime_error("field already assigned"); - lbl_->emplace(symbol_range, std::move(label), label_si::mac_flag()); + lbl_.emplace(symbol_range, std::move(label), label_si::mac_flag()); } void collector::set_label_field(seq_sym sequence_symbol, range symbol_range) { - if (*lbl_) + if (lbl_) throw std::runtime_error("field already assigned"); - lbl_->emplace(symbol_range, std::move(sequence_symbol)); + lbl_.emplace(symbol_range, std::move(sequence_symbol)); } void collector::set_label_field(const std::string* label, antlr4::ParserRuleContext* parser_ctx, range symbol_range) { - if (*lbl_) + if (lbl_) throw std::runtime_error("field already assigned"); // recognise, whether label consists only of ORDSYMBOL token if (!parser_ctx @@ -71,50 +69,50 @@ void collector::set_label_field(const std::string* label, antlr4::ParserRuleCont && parser_ctx->getStart()->getType() == lexing::lexer::Tokens::ORDSYMBOL)) { add_lsp_symbol(label, symbol_range, context::symbol_type::ord); - lbl_->emplace(symbol_range, *label); + lbl_.emplace(symbol_range, *label); } // otherwise it is macro label parameter else { - lbl_->emplace(symbol_range, *label, label_si::mac_flag()); + lbl_.emplace(symbol_range, *label, label_si::mac_flag()); } } void collector::set_label_field(concat_chain label, range symbol_range) { - if (*lbl_) + if (lbl_) throw std::runtime_error("field already assigned"); concatenation_point::clear_concat_chain(label); if (label.size() == 1 && label[0]->type == concat_type::VAR) // label is variable symbol { - lbl_->emplace(symbol_range, std::move(label[0]->access_var()->symbol)); + lbl_.emplace(symbol_range, std::move(label[0]->access_var()->symbol)); } else // label is concatenation { - lbl_->emplace(symbol_range, std::move(label)); + lbl_.emplace(symbol_range, std::move(label)); } } void collector::set_instruction_field(range symbol_range) { - if (*instr_) + if (instr_) throw std::runtime_error("field already assigned"); - instr_->emplace(symbol_range); + instr_.emplace(symbol_range); } void collector::set_instruction_field(context::id_index instr, range symbol_range) { - if (*instr_) + if (instr_) throw std::runtime_error("field already assigned"); - instr_->emplace(symbol_range, instr); + instr_.emplace(symbol_range, instr); } void collector::set_instruction_field(concat_chain instr, range symbol_range) { - if (*instr_) + if (instr_) throw std::runtime_error("field already assigned"); concatenation_point::clear_concat_chain(instr); - instr_->emplace(symbol_range, std::move(instr)); + instr_.emplace(symbol_range, std::move(instr)); } void collector::set_operand_remark_field(range symbol_range) @@ -124,6 +122,8 @@ void collector::set_operand_remark_field(range symbol_range) op_.emplace(symbol_range, operand_list()); rem_.emplace(symbol_range, std::vector()); def_.emplace("", symbol_range); + + add_operand_remark_hl_symbols(); } void collector::set_operand_remark_field(std::string deferred, std::vector remarks, range symbol_range) @@ -132,6 +132,8 @@ void collector::set_operand_remark_field(std::string deferred, std::vectoroperand_range, hl_scopes::operand)); + for (auto&& operand : current_operands().value) + if (operand) + add_hl_symbol(token_info(operand->operand_range, hl_scopes::operand)); } -} -void collector::add_remarks_hl_symbols() -{ - if (!rem_) - return; - for (auto remark : current_remarks().value) + if (rem_) { - add_hl_symbol(token_info(remark, hl_scopes::remark)); + for (const auto& remark : current_remarks().value) + add_hl_symbol(token_info(remark, hl_scopes::remark)); } } -void collector::append_reparsed_symbols(collector&& c) -{ - for (auto& sym : c.hl_symbols_) - hl_symbols_.push_back(std::move(sym)); - - size_t i; - for (i = 0; i < lsp_symbols_.size() && lsp_symbols_[i].type != context::symbol_type::instruction; ++i) - ; - - if (i != lsp_symbols_.size()) - while (lsp_symbols_.size() != i + 1) - lsp_symbols_.pop_back(); - - for (auto& s : c.lsp_symbols_) - lsp_symbols_.push_back(std::move(s)); -} - void collector::append_operand_field(collector&& c) { if (c.op_) @@ -211,14 +193,14 @@ void collector::append_operand_field(collector&& c) lsp_symbols_.push_back(std::move(symbol)); } -const instruction_si& collector::peek_instruction() { return **instr_; } +const instruction_si& collector::peek_instruction() { return *instr_; } std::variant collector::extract_statement(bool deferred_hint, range default_range) { - if (!*lbl_) - lbl_->emplace(default_range); - if (!*instr_) - instr_->emplace(default_range); + if (!lbl_) + lbl_.emplace(default_range); + if (!instr_) + instr_.emplace(default_range); if (!rem_) rem_.emplace(default_range, remark_list {}); @@ -227,27 +209,27 @@ std::variant collector::extract_statement(b if (deferred_hint) { if (!def_) - def_.emplace("", instr_->value().field_range); - return statement_si_deferred(range_provider::union_range(lbl_->value().field_range, def_->second), - std::move(**lbl_), - std::move(**instr_), + def_.emplace("", instr_.value().field_range); + return statement_si_deferred(range_provider::union_range(lbl_.value().field_range, def_->second), + std::move(*lbl_), + std::move(*instr_), std::move(def_.value().first), def_.value().second); } else { if (!op_) - op_.emplace(instr_->value().field_range, operand_list {}); + op_.emplace(instr_.value().field_range, operand_list {}); // foreach operand substitute null with empty for (size_t i = 0; i < op_->value.size(); i++) { if (!op_->value[i]) - op_->value[i] = std::make_unique(instr_->value().field_range); + op_->value[i] = std::make_unique(instr_.value().field_range); } - range r = range_provider::union_range(lbl_->value().field_range, op_->field_range); - return statement_si(r, std::move(**lbl_), std::move(**instr_), std::move(*op_), std::move(*rem_)); + range r = range_provider::union_range(lbl_.value().field_range, op_->field_range); + return statement_si(r, std::move(*lbl_), std::move(*instr_), std::move(*op_), std::move(*rem_)); } } @@ -271,8 +253,8 @@ std::vector collector::extract_hl_symbols() void collector::prepare_for_next_statement() { - lbl_->reset(); - instr_->reset(); + lbl_.reset(); + instr_.reset(); op_.reset(); rem_.reset(); def_.reset(); @@ -282,21 +264,3 @@ void collector::prepare_for_next_statement() lsp_symbols_extracted_ = false; hl_symbols_extracted_ = false; } - -void collector::push_fields() -{ - if (instr_ == instrs_ + 1) - throw std::runtime_error("fields already pushed"); - ++instr_; - ++lbl_; -} - -void collector::pop_fields() -{ - if (instr_ == instrs_) - throw std::runtime_error("fields already popped"); - instr_->reset(); - lbl_->reset(); - --instr_; - --lbl_; -} diff --git a/parser_library/src/semantics/collector.h b/parser_library/src/semantics/collector.h index b1b7e4535..a99db71d9 100644 --- a/parser_library/src/semantics/collector.h +++ b/parser_library/src/semantics/collector.h @@ -55,10 +55,7 @@ class collector void add_lsp_symbol(const std::string* name, range symbol_range, context::symbol_type type); void add_hl_symbol(token_info symbol); void clear_hl_lsp_symbols(); - void add_operands_hl_symbols(); - void add_remarks_hl_symbols(); - void append_reparsed_symbols(collector&& c); void append_operand_field(collector&& c); const instruction_si& peek_instruction(); @@ -67,14 +64,9 @@ class collector std::vector extract_hl_symbols(); void prepare_for_next_statement(); - void push_fields(); - void pop_fields(); - private: - std::optional lbls_[2]; - std::optional* lbl_; - std::optional instrs_[2]; - std::optional* instr_; + std::optional lbl_; + std::optional instr_; std::optional op_; std::optional rem_; std::optional> def_; @@ -82,6 +74,8 @@ class collector std::vector hl_symbols_; bool lsp_symbols_extracted_; bool hl_symbols_extracted_; + + void add_operand_remark_hl_symbols(); }; } // namespace semantics diff --git a/parser_library/src/semantics/concatenation.cpp b/parser_library/src/semantics/concatenation.cpp index fcbc7c5da..d68b9f46a 100644 --- a/parser_library/src/semantics/concatenation.cpp +++ b/parser_library/src/semantics/concatenation.cpp @@ -15,6 +15,7 @@ #include "concatenation.h" #include "concatenation_term.h" +#include "expressions/conditional_assembly/terms/ca_var_sym.h" namespace hlasm_plugin::parser_library::semantics { @@ -171,4 +172,28 @@ var_sym_conc* concatenation_point::contains_var_sym( return nullptr; } +std::set concatenation_point::get_undefined_attributed_symbols( + const concat_chain& chain, const expressions::evaluation_context& eval_ctx) +{ + std::set ret; + for (auto it = chain.begin(); it != chain.end(); ++it) + { + auto&& point = *it; + switch (point->type) + { + case concat_type::VAR: + ret.merge(expressions::ca_var_sym::get_undefined_attributed_symbols_vs( + point->access_var()->symbol, eval_ctx)); + break; + case concat_type::SUB: + for (const auto& ch : point->access_sub()->list) + ret.merge(get_undefined_attributed_symbols(ch, eval_ctx)); + break; + default: + break; + } + } + return ret; +} + } // namespace hlasm_plugin::parser_library::semantics diff --git a/parser_library/src/semantics/concatenation.h b/parser_library/src/semantics/concatenation.h index 4eace56eb..4bbf4434a 100644 --- a/parser_library/src/semantics/concatenation.h +++ b/parser_library/src/semantics/concatenation.h @@ -16,10 +16,12 @@ #define SEMANTICS_CONCATENATION_H #include +#include #include #include #include "context/common_types.h" +#include "context/id_storage.h" // this file is a composition of structures that create concat_chain // concat_chain is used to represent model statement fields @@ -63,6 +65,9 @@ struct concatenation_point static var_sym_conc* contains_var_sym(concat_chain::const_iterator begin, concat_chain::const_iterator end); + static std::set get_undefined_attributed_symbols( + const concat_chain& chain, const expressions::evaluation_context& eval_ctx); + const concat_type type; concatenation_point(const concat_type type); diff --git a/parser_library/src/semantics/operand.cpp b/parser_library/src/semantics/operand.cpp index 2178b405d..12ff78536 100644 --- a/parser_library/src/semantics/operand.cpp +++ b/parser_library/src/semantics/operand.cpp @@ -14,6 +14,8 @@ #include "operand.h" +#include "expressions/conditional_assembly/terms/ca_var_sym.h" + namespace hlasm_plugin::parser_library::semantics { //***************** operand ********************* @@ -67,7 +69,7 @@ expr_machine_operand* machine_operand::access_expr() address_machine_operand* machine_operand::access_address() { - return kind == mach_kind::EXPR ? static_cast(this) : nullptr; + return kind == mach_kind::ADDR ? static_cast(this) : nullptr; } std::unique_ptr make_check_operand(expressions::mach_evaluate_info info, @@ -147,7 +149,7 @@ address_machine_operand::address_machine_operand(expressions::mach_expr_ptr disp , state(std::move(state)) {} -bool address_machine_operand::has_dependencies(hlasm_plugin::parser_library::expressions::mach_evaluate_info info) const +bool address_machine_operand::has_dependencies(expressions::mach_evaluate_info info) const { if (first_par) { @@ -319,8 +321,7 @@ using_instr_assembler_operand::using_instr_assembler_operand( , end(std::move(end)) {} -bool using_instr_assembler_operand::has_dependencies( - hlasm_plugin::parser_library::expressions::mach_evaluate_info info) const +bool using_instr_assembler_operand::has_dependencies(expressions::mach_evaluate_info info) const { return base->get_dependencies(info).contains_dependencies() || end->get_dependencies(info).contains_dependencies(); } @@ -359,10 +360,7 @@ complex_assembler_operand::complex_assembler_operand( , value(identifier, std::move(values), operand_range) {} -bool complex_assembler_operand::has_dependencies(hlasm_plugin::parser_library::expressions::mach_evaluate_info) const -{ - return false; -} +bool complex_assembler_operand::has_dependencies(expressions::mach_evaluate_info) const { return false; } bool complex_assembler_operand::has_error(expressions::mach_evaluate_info) const { return false; } @@ -439,26 +437,49 @@ var_ca_operand::var_ca_operand(vs_ptr variable_symbol, range operand_range) , variable_symbol(std::move(variable_symbol)) {} +std::set var_ca_operand::get_undefined_attributed_symbols( + const expressions::evaluation_context& eval_ctx) +{ + return expressions::ca_var_sym::get_undefined_attributed_symbols_vs(variable_symbol, eval_ctx); +} + expr_ca_operand::expr_ca_operand(expressions::ca_expr_ptr expression, range operand_range) : ca_operand(ca_kind::EXPR, std::move(operand_range)) , expression(std::move(expression)) {} +std::set expr_ca_operand::get_undefined_attributed_symbols( + const expressions::evaluation_context& eval_ctx) +{ + return expression->get_undefined_attributed_symbols(eval_ctx); +} + seq_ca_operand::seq_ca_operand(seq_sym sequence_symbol, range operand_range) : ca_operand(ca_kind::SEQ, std::move(operand_range)) , sequence_symbol(std::move(sequence_symbol)) {} +std::set seq_ca_operand::get_undefined_attributed_symbols(const expressions::evaluation_context&) +{ + return std::set(); +} + branch_ca_operand::branch_ca_operand(seq_sym sequence_symbol, expressions::ca_expr_ptr expression, range operand_range) : ca_operand(ca_kind::BRANCH, std::move(operand_range)) , sequence_symbol(std::move(sequence_symbol)) , expression(std::move(expression)) {} +std::set branch_ca_operand::get_undefined_attributed_symbols( + const expressions::evaluation_context& eval_ctx) +{ + return expression->get_undefined_attributed_symbols(eval_ctx); +} + -macro_operand::macro_operand(concat_chain chain, range operand_range) - : operand(operand_type::MAC, std::move(operand_range)) +macro_operand_chain::macro_operand_chain(concat_chain chain, range operand_range) + : macro_operand(mac_kind::CHAIN, std::move(operand_range)) , chain(std::move(chain)) {} @@ -572,8 +593,23 @@ std::unique_ptr string_assembler_operand::get_operand_value(e void string_assembler_operand::collect_diags() const {} macro_operand_string::macro_operand_string(std::string value, const range operand_range) - : operand(operand_type::MAC, operand_range) + : macro_operand(mac_kind::STRING, operand_range) , value(std::move(value)) {} -} // namespace hlasm_plugin::parser_library::semantics \ No newline at end of file +macro_operand_chain* macro_operand::access_chain() +{ + return kind == mac_kind::CHAIN ? static_cast(this) : nullptr; +} + +macro_operand_string* macro_operand::access_string() +{ + return kind == mac_kind::STRING ? static_cast(this) : nullptr; +} + +macro_operand::macro_operand(mac_kind kind, range operand_range) + : operand(operand_type::MAC, std::move(operand_range)) + , kind(kind) +{} + +} // namespace hlasm_plugin::parser_library::semantics diff --git a/parser_library/src/semantics/operand.h b/parser_library/src/semantics/operand.h index 416728bdf..1165c7085 100644 --- a/parser_library/src/semantics/operand.h +++ b/parser_library/src/semantics/operand.h @@ -25,9 +25,7 @@ // the file contains structures representing operands in the operand field of statement -namespace hlasm_plugin { -namespace parser_library { -namespace semantics { +namespace hlasm_plugin::parser_library::semantics { enum class operand_type { @@ -87,7 +85,7 @@ struct operand // structure for empty operands -struct empty_operand final : public operand +struct empty_operand final : operand { empty_operand(const range operand_range); }; @@ -95,7 +93,7 @@ struct empty_operand final : public operand // operand that contains variable symbol thus is 'model operand' -struct model_operand final : public operand +struct model_operand final : operand { model_operand(concat_chain chain, const range operand_range); @@ -105,7 +103,7 @@ struct model_operand final : public operand // operands that can return value and have dependencies -struct evaluable_operand : public operand, public diagnosable_op_impl +struct evaluable_operand : operand, diagnosable_op_impl { evaluable_operand(const operand_type type, const range operand_range); @@ -121,7 +119,7 @@ struct evaluable_operand : public operand, public diagnosable_op_impl // operand representing simple expression -struct simple_expr_operand : public virtual evaluable_operand +struct simple_expr_operand : virtual evaluable_operand { simple_expr_operand(expressions::mach_expr_ptr expression); @@ -144,7 +142,7 @@ struct expr_machine_operand; struct address_machine_operand; // machine instruction operand -struct machine_operand : public virtual evaluable_operand +struct machine_operand : virtual evaluable_operand { machine_operand(const mach_kind kind); @@ -161,7 +159,7 @@ struct machine_operand : public virtual evaluable_operand // machine expression operand -struct expr_machine_operand final : public machine_operand, public simple_expr_operand +struct expr_machine_operand final : machine_operand, simple_expr_operand { expr_machine_operand(expressions::mach_expr_ptr expression, const range operand_range); @@ -178,7 +176,7 @@ struct expr_machine_operand final : public machine_operand, public simple_expr_o // machine address operand -struct address_machine_operand final : public machine_operand +struct address_machine_operand final : machine_operand { address_machine_operand(expressions::mach_expr_ptr displacement, expressions::mach_expr_ptr first_par, @@ -218,7 +216,7 @@ struct complex_assembler_operand; struct string_assembler_operand; // assembler instruction operand -struct assembler_operand : public virtual evaluable_operand +struct assembler_operand : virtual evaluable_operand { assembler_operand(const asm_kind kind); @@ -232,7 +230,7 @@ struct assembler_operand : public virtual evaluable_operand // assembler expression operand -struct expr_assembler_operand final : public assembler_operand, public simple_expr_operand +struct expr_assembler_operand final : assembler_operand, simple_expr_operand { private: std::string value_; @@ -252,7 +250,7 @@ struct expr_assembler_operand final : public assembler_operand, public simple_ex // USING instruction operand -struct using_instr_assembler_operand final : public assembler_operand +struct using_instr_assembler_operand final : assembler_operand { using_instr_assembler_operand( expressions::mach_expr_ptr base, expressions::mach_expr_ptr end, const range operand_range); @@ -274,7 +272,7 @@ struct using_instr_assembler_operand final : public assembler_operand // complex assembler operand (i.e. 'OVERRIDE(A,B,C)') -struct complex_assembler_operand final : public assembler_operand +struct complex_assembler_operand final : assembler_operand { struct component_value_t { @@ -291,7 +289,7 @@ struct complex_assembler_operand final : public assembler_operand range op_range; }; - struct int_value_t final : public component_value_t + struct int_value_t final : component_value_t { int_value_t(int value, range range) : component_value_t(range) @@ -303,7 +301,7 @@ struct complex_assembler_operand final : public assembler_operand } int value; }; - struct string_value_t final : public component_value_t + struct string_value_t final : component_value_t { // string_value_t(std::string value) : value(std::move(value)) {} string_value_t(std::string value, range range) @@ -316,7 +314,7 @@ struct complex_assembler_operand final : public assembler_operand } std::string value; }; - struct composite_value_t final : public component_value_t + struct composite_value_t final : component_value_t { composite_value_t(std::string identifier, std::vector> values, range range) : component_value_t(range) @@ -354,7 +352,7 @@ struct complex_assembler_operand final : public assembler_operand // assembler string operand -struct string_assembler_operand : public assembler_operand +struct string_assembler_operand : assembler_operand { string_assembler_operand(std::string value, const range operand_range); @@ -372,7 +370,7 @@ struct string_assembler_operand : public assembler_operand }; // data definition operand -struct data_def_operand final : public evaluable_operand +struct data_def_operand final : evaluable_operand { data_def_operand(expressions::data_definition data_def, const range operand_range); @@ -407,7 +405,7 @@ struct seq_ca_operand; struct branch_ca_operand; // coditional assembly instruction operand -struct ca_operand : public operand +struct ca_operand : operand { ca_operand(const ca_kind kind, const range operand_range); @@ -420,61 +418,97 @@ struct ca_operand : public operand branch_ca_operand* access_branch(); const branch_ca_operand* access_branch() const; + virtual std::set get_undefined_attributed_symbols( + const expressions::evaluation_context& eval_ctx) = 0; + const ca_kind kind; }; // CA variable symbol operand -struct var_ca_operand final : public ca_operand +struct var_ca_operand final : ca_operand { var_ca_operand(vs_ptr variable_symbol, const range operand_range); + virtual std::set get_undefined_attributed_symbols( + const expressions::evaluation_context& eval_ctx) override; + vs_ptr variable_symbol; }; // CA expression operand -struct expr_ca_operand final : public ca_operand +struct expr_ca_operand final : ca_operand { expr_ca_operand(expressions::ca_expr_ptr expression, const range operand_range); + + virtual std::set get_undefined_attributed_symbols( + const expressions::evaluation_context& eval_ctx) override; + expressions::ca_expr_ptr expression; }; // CA sequence symbol operand -struct seq_ca_operand final : public ca_operand +struct seq_ca_operand final : ca_operand { seq_ca_operand(seq_sym sequence_symbol, const range operand_range); + + virtual std::set get_undefined_attributed_symbols( + const expressions::evaluation_context& eval_ctx) override; + seq_sym sequence_symbol; }; // CA branching operand (i.e. (5).here) -struct branch_ca_operand final : public ca_operand +struct branch_ca_operand final : ca_operand { branch_ca_operand(seq_sym sequence_symbol, expressions::ca_expr_ptr expression, const range operand_range); + + virtual std::set get_undefined_attributed_symbols( + const expressions::evaluation_context& eval_ctx) override; + seq_sym sequence_symbol; expressions::ca_expr_ptr expression; }; +enum class mac_kind +{ + CHAIN, + STRING +}; + +struct macro_operand_chain; +struct macro_operand_string; + +struct macro_operand : operand +{ + const mac_kind kind; + + macro_operand_chain* access_chain(); + macro_operand_string* access_string(); + +protected: + macro_operand(mac_kind kind, range operand_range); +}; // macro instruction operand -struct macro_operand final : public operand +struct macro_operand_chain final : macro_operand { - macro_operand(concat_chain chain, const range operand_range); + macro_operand_chain(concat_chain chain, const range operand_range); concat_chain chain; }; // macro instruction operand -struct macro_operand_string final : public operand +struct macro_operand_string final : macro_operand { macro_operand_string(std::string value, const range operand_range); std::string value; }; -} // namespace semantics -} // namespace parser_library -} // namespace hlasm_plugin +} // namespace hlasm_plugin::parser_library::semantics + #endif diff --git a/parser_library/test/common_testing.h b/parser_library/test/common_testing.h index 7f2317e49..3b5e98572 100644 --- a/parser_library/test/common_testing.h +++ b/parser_library/test/common_testing.h @@ -38,17 +38,6 @@ using namespace hlasm_plugin::parser_library::expressions; const size_t size_t_zero = static_cast(0); -// mock for attribute provider that has empty functionality -class empty_attribute_provider : public attribute_provider -{ - virtual const attribute_provider::resolved_reference_storage& lookup_forward_attribute_references( - attribute_provider::forward_reference_storage references) - { - (void)references; - return resolved_symbols; - } -}; - inline std::pair try_parse_sll( hlasm_plugin::parser_library::parsing::hlasmparser& h_parser) { diff --git a/parser_library/test/context/context_test.cpp b/parser_library/test/context/context_test.cpp index eec20ae16..8284e7e82 100644 --- a/parser_library/test/context/context_test.cpp +++ b/parser_library/test/context/context_test.cpp @@ -553,8 +553,8 @@ TEST(context, id_check) EXPECT_TRUE(mngr.try_get_symbol_name("LIST").first); EXPECT_TRUE(mngr.try_get_symbol_name("T_A").first); EXPECT_TRUE(mngr.try_get_symbol_name("T1").first); - EXPECT_TRUE(mngr.try_get_symbol_name("a1-").first); + EXPECT_FALSE(mngr.try_get_symbol_name("a1-").first); EXPECT_FALSE(mngr.try_get_symbol_name("*1").first); EXPECT_FALSE(mngr.try_get_symbol_name("1av").first); } diff --git a/parser_library/test/expressions/ca_constant_test.cpp b/parser_library/test/expressions/ca_constant_test.cpp index 07e60a881..a68a9effd 100644 --- a/parser_library/test/expressions/ca_constant_test.cpp +++ b/parser_library/test/expressions/ca_constant_test.cpp @@ -24,10 +24,13 @@ using namespace hlasm_plugin::parser_library; TEST(ca_constant, undefined_attributes) { - dep_sol_mock m; + context::hlasm_context ctx; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; + ca_constant c(1, range()); - ASSERT_EQ(c.get_undefined_attributed_symbols(m).size(), 0U); + ASSERT_EQ(c.get_undefined_attributed_symbols(eval_ctx).size(), 0U); } class collectable_mock : public diagnosable_op_impl diff --git a/parser_library/test/expressions/ca_expr_list_test.cpp b/parser_library/test/expressions/ca_expr_list_test.cpp index ef360b24e..c526d0d30 100644 --- a/parser_library/test/expressions/ca_expr_list_test.cpp +++ b/parser_library/test/expressions/ca_expr_list_test.cpp @@ -30,9 +30,8 @@ using namespace hlasm_plugin::parser_library; TEST(ca_expr_list, unknown_function_to_operator) { context::hlasm_context ctx; - attr_prov_mock attr; lib_prov_mock lib; - evaluation_context eval_ctx { ctx, attr, lib }; + evaluation_context eval_ctx { ctx, lib }; std::string name = "AND"; auto c = std::make_unique(1, range()); @@ -59,9 +58,8 @@ TEST(ca_expr_list, unknown_function_to_operator) TEST(ca_expr_list, resolve_C_type) { context::hlasm_context ctx; - attr_prov_mock attr; lib_prov_mock lib; - evaluation_context eval_ctx { ctx, attr, lib }; + evaluation_context eval_ctx { ctx, lib }; std::string name = "UPPER"; auto sym = std::make_unique(&name, range()); @@ -98,8 +96,10 @@ TEST(ca_expr_list, get_undefined_attributed_symbols) // (L'X 'low') ca_expr_list expr_list(std::move(list), range()); - dep_sol_mock m; - auto res = expr_list.get_undefined_attributed_symbols(m); + context::hlasm_context ctx; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; + auto res = expr_list.get_undefined_attributed_symbols(eval_ctx); ASSERT_TRUE(res.size()); } diff --git a/parser_library/test/expressions/ca_function_test.cpp b/parser_library/test/expressions/ca_function_test.cpp index 7731fb482..c30608651 100644 --- a/parser_library/test/expressions/ca_function_test.cpp +++ b/parser_library/test/expressions/ca_function_test.cpp @@ -61,10 +61,7 @@ class set_expr : public ca_expression , value(std::move(value)) {} - virtual undef_sym_set get_undefined_attributed_symbols(const context::dependency_solver&) const override - { - return {}; - }; + virtual undef_sym_set get_undefined_attributed_symbols(const evaluation_context&) const override { return {}; }; virtual void resolve_expression_tree(context::SET_t_enum) override {} @@ -79,9 +76,8 @@ class ca_func : public ::testing::TestWithParam { protected: context::hlasm_context ctx; - attr_prov_mock attr; lib_prov_mock lib; - evaluation_context eval_ctx { ctx, attr, lib }; + evaluation_context eval_ctx { ctx, lib }; context::SET_t get_result() { diff --git a/parser_library/test/expressions/ca_operator_test.cpp b/parser_library/test/expressions/ca_operator_test.cpp index 7526d8ad0..c6d36175c 100644 --- a/parser_library/test/expressions/ca_operator_test.cpp +++ b/parser_library/test/expressions/ca_operator_test.cpp @@ -59,9 +59,8 @@ class ca_op : public ::testing::TestWithParam { protected: hlasm_context ctx; - attr_prov_mock attr; lib_prov_mock prov; - evaluation_context eval_ctx { ctx, attr, prov }; + evaluation_context eval_ctx { ctx, prov }; SET_t get_result() { diff --git a/parser_library/test/expressions/ca_string_test.cpp b/parser_library/test/expressions/ca_string_test.cpp index 4274b32d8..174e5a6fe 100644 --- a/parser_library/test/expressions/ca_string_test.cpp +++ b/parser_library/test/expressions/ca_string_test.cpp @@ -25,7 +25,9 @@ using namespace hlasm_plugin::parser_library; TEST(ca_string, undefined_attributes) { - dep_sol_mock m; + context::hlasm_context ctx; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; concat_chain value; value.push_back(std::make_unique("gfds")); @@ -39,7 +41,7 @@ TEST(ca_string, undefined_attributes) ca_string s(std::move(value), std::move(dupl), std::move(substr), range()); - auto res = s.get_undefined_attributed_symbols(m); + auto res = s.get_undefined_attributed_symbols(eval_ctx); ASSERT_EQ(res.size(), 0U); } @@ -79,14 +81,12 @@ TEST(ca_string, test) ca_string s(std::move(value), std::move(dupl), ca_string::substring_t(), range()); context::hlasm_context ctx; - attr_prov_mock a; - lib_prov_mock l; - - evaluation_context eval { ctx, a, l }; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; - auto res = s.evaluate(eval); + auto res = s.evaluate(eval_ctx); - ASSERT_EQ(eval.diags().size(), 0U); + ASSERT_EQ(eval_ctx.diags().size(), 0U); EXPECT_EQ(res.access_c(), ""); } @@ -101,14 +101,12 @@ TEST_P(ca_string_suite, dupl) ca_string s(std::move(value), std::move(dupl), ca_string::substring_t(), range()); context::hlasm_context ctx; - attr_prov_mock a; - lib_prov_mock l; - - evaluation_context eval { ctx, a, l }; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; - auto res = s.evaluate(eval); + auto res = s.evaluate(eval_ctx); - ASSERT_EQ(eval.diags().size(), GetParam().error); + ASSERT_EQ(eval_ctx.diags().size(), GetParam().error); if (!GetParam().error) EXPECT_EQ(res.access_c(), GetParam().result); diff --git a/parser_library/test/expressions/ca_symbol_attribute_test.cpp b/parser_library/test/expressions/ca_symbol_attribute_test.cpp index ffe57b5d6..c801f2957 100644 --- a/parser_library/test/expressions/ca_symbol_attribute_test.cpp +++ b/parser_library/test/expressions/ca_symbol_attribute_test.cpp @@ -14,6 +14,7 @@ #include "gmock/gmock.h" +#include "ebcdic_encoding.h" #include "expr_mocks.h" #include "expressions/conditional_assembly/terms/ca_constant.h" #include "expressions/conditional_assembly/terms/ca_symbol_attribute.h" @@ -25,7 +26,10 @@ using namespace hlasm_plugin::parser_library; TEST(ca_symbol_attr, undefined_attributes) { - dep_sol_mock m; + context::hlasm_context ctx; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; + std::string name = "n"; std::vector subscript; @@ -35,15 +39,13 @@ TEST(ca_symbol_attr, undefined_attributes) ca_symbol_attribute attr(std::move(vs), context::data_attr_kind::D, range()); - auto res = attr.get_undefined_attributed_symbols(m); + auto res = attr.get_undefined_attributed_symbols(eval_ctx); ASSERT_EQ(res.size(), 0U); } -ca_symbol_attribute create_var_sym_attr(context::data_attr_kind kind, context::id_storage& ids) +ca_symbol_attribute create_var_sym_attr(context::data_attr_kind kind, context::id_index name) { - auto name = ids.add("n"); - auto vs = std::make_unique(name, std::vector {}, range()); return ca_symbol_attribute(std::move(vs), kind, range()); @@ -52,49 +54,116 @@ ca_symbol_attribute create_var_sym_attr(context::data_attr_kind kind, context::i TEST(ca_symbol_attr, evaluate_undef_varsym) { context::hlasm_context ctx; - attr_prov_mock a; - lib_prov_mock l; - - evaluation_context eval { ctx, a, l }; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; - auto res = create_var_sym_attr(context::data_attr_kind::D, ctx.ids()).evaluate(eval); + auto res = create_var_sym_attr(context::data_attr_kind::D, ctx.ids().add("n")).evaluate(eval_ctx); - ASSERT_EQ(eval.diags().size(), 1U); - EXPECT_EQ(eval.diags().front().code, "E010"); + ASSERT_EQ(eval_ctx.diags().size(), 1U); + EXPECT_EQ(eval_ctx.diags().front().code, "E010"); } TEST(ca_symbol_attr, evaluate_substituted_varsym_not_char) { context::hlasm_context ctx; - attr_prov_mock a; - lib_prov_mock l; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; + auto name = ctx.ids().add("n"); auto var = ctx.create_local_variable(name, true); var->access_set_symbol()->set_value(12); - evaluation_context eval { ctx, a, l }; - - auto res = create_var_sym_attr(context::data_attr_kind::L, ctx.ids()).evaluate(eval); + auto res = create_var_sym_attr(context::data_attr_kind::L, name).evaluate(eval_ctx); - ASSERT_EQ(eval.diags().size(), 1U); - EXPECT_EQ(eval.diags().front().code, "E066"); + ASSERT_EQ(eval_ctx.diags().size(), 1U); + EXPECT_EQ(eval_ctx.diags().front().code, "E066"); } TEST(ca_symbol_attr, evaluate_substituted_varsym_char_not_sym) { context::hlasm_context ctx; - attr_prov_mock a; - lib_prov_mock l; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; + auto name = ctx.ids().add("n"); auto var = ctx.create_local_variable(name, true); var->access_set_symbol()->set_value("(abc"); - evaluation_context eval { ctx, a, l }; + auto res = create_var_sym_attr(context::data_attr_kind::L, name).evaluate(eval_ctx); + + ASSERT_EQ(eval_ctx.diags().size(), 1U); + EXPECT_EQ(eval_ctx.diags().front().code, "E065"); +} + +struct attr_test_param +{ + std::string value; + context::data_attr_kind attr; + context::SET_t result; + std::string name; +}; + +std::ostream& operator<<(std::ostream& os, const attr_test_param& param) +{ + os << param.value; + return os; +} + +struct stringer +{ + std::string operator()(::testing::TestParamInfo p) { return p.param.name; } +}; + +class ca_attr : public ::testing::TestWithParam +{ +protected: + context::hlasm_context ctx; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; +}; + +INSTANTIATE_TEST_SUITE_P(ca_attr_suite, + ca_attr, + ::testing::Values(attr_test_param { "C-A", context::data_attr_kind::T, "w", "T_mach_expr" }, + attr_test_param { "C(R1)", context::data_attr_kind::T, "w", "T_address" }, + attr_test_param { "C'TEXT'", context::data_attr_kind::T, "N", "T_self_def_term" }, + attr_test_param { "C'T''T'", context::data_attr_kind::T, "N", "T_self_def_term_apo" }, + attr_test_param { "C'TEXT'", context::data_attr_kind::L, 1, "L_self_def_term" }, + attr_test_param { "(C)", context::data_attr_kind::L, 10, "T_mach_expr_pars" }, + attr_test_param { "4(,R15)", context::data_attr_kind::T, "U", "T_mach_expr_number" }, + attr_test_param { "A.C", context::data_attr_kind::L, 10, "L_using_prefix" }, + attr_test_param { "T'C", context::data_attr_kind::T, "U", "T_attribute" }), + stringer()); + +TEST_P(ca_attr, test) +{ + auto name = ctx.ids().add("VAR"); + + (void)ctx.ord_ctx.create_symbol(ctx.ids().add("C"), + context::symbol_value(), + context::symbol_attributes(context::symbol_origin::EQU, 'w'_ebcdic, 10), + location()); + + (void)ctx.ord_ctx.create_symbol(ctx.ids().add("T"), + context::symbol_value(), + context::symbol_attributes(context::symbol_origin::EQU, 'w'_ebcdic, 10), + location()); + + auto var = ctx.create_local_variable(name, true); + var->access_set_symbol()->set_value(GetParam().value); + + auto result = create_var_sym_attr(GetParam().attr, name).evaluate(eval_ctx); - auto res = create_var_sym_attr(context::data_attr_kind::L, ctx.ids()).evaluate(eval); + ASSERT_EQ(result.type, GetParam().result.type); - ASSERT_EQ(eval.diags().size(), 1U); - EXPECT_EQ(eval.diags().front().code, "E065"); + if (result.type == context::SET_t_enum::A_TYPE) + EXPECT_EQ(result.access_a(), GetParam().result.access_a()); + else if (result.type == context::SET_t_enum::B_TYPE) + EXPECT_EQ(result.access_b(), GetParam().result.access_b()); + else if (result.type == context::SET_t_enum::C_TYPE) + EXPECT_EQ(result.access_c(), GetParam().result.access_c()); + else + FAIL(); } diff --git a/parser_library/test/expressions/ca_symbol_test.cpp b/parser_library/test/expressions/ca_symbol_test.cpp index 2e04dcee2..4c8a8845b 100644 --- a/parser_library/test/expressions/ca_symbol_test.cpp +++ b/parser_library/test/expressions/ca_symbol_test.cpp @@ -17,6 +17,7 @@ #include "diagnostic_adder.h" #include "expr_mocks.h" #include "expressions/conditional_assembly/terms/ca_symbol.h" +#include "expressions/evaluation_context.h" using namespace hlasm_plugin::parser_library::expressions; using namespace hlasm_plugin::parser_library::semantics; @@ -24,12 +25,14 @@ using namespace hlasm_plugin::parser_library; TEST(ca_symbol, undefined_attributes) { - dep_sol_mock m; + context::hlasm_context ctx; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; std::string name = "n"; ca_symbol sym(&name, range()); - auto res = sym.get_undefined_attributed_symbols(m); + auto res = sym.get_undefined_attributed_symbols(eval_ctx); ASSERT_EQ(res.size(), 0U); } diff --git a/parser_library/test/expressions/ca_var_sym_test.cpp b/parser_library/test/expressions/ca_var_sym_test.cpp index 3b507bab0..10236e3db 100644 --- a/parser_library/test/expressions/ca_var_sym_test.cpp +++ b/parser_library/test/expressions/ca_var_sym_test.cpp @@ -25,7 +25,10 @@ using namespace hlasm_plugin::parser_library; TEST(ca_var_sym_basic, undefined_attributes) { - dep_sol_mock m; + context::hlasm_context ctx; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; + std::string name = "n"; std::vector subscript; @@ -35,14 +38,17 @@ TEST(ca_var_sym_basic, undefined_attributes) ca_var_sym var(std::move(vs), range()); - auto res = var.get_undefined_attributed_symbols(m); + auto res = var.get_undefined_attributed_symbols(eval_ctx); ASSERT_EQ(res.size(), 0U); } TEST(ca_var_sym_created, undefined_attributes) { - dep_sol_mock m; + context::hlasm_context ctx; + lib_prov_mock lib; + evaluation_context eval_ctx { ctx, lib }; + std::string name = "n"; concat_chain created_name; std::vector subscript; @@ -55,7 +61,7 @@ TEST(ca_var_sym_created, undefined_attributes) ca_var_sym var(std::move(vs), range()); - auto res = var.get_undefined_attributed_symbols(m); + auto res = var.get_undefined_attributed_symbols(eval_ctx); ASSERT_EQ(res.size(), 0U); } diff --git a/parser_library/test/expressions/expr_mocks.h b/parser_library/test/expressions/expr_mocks.h index 2e1973076..6c9f4d81b 100644 --- a/parser_library/test/expressions/expr_mocks.h +++ b/parser_library/test/expressions/expr_mocks.h @@ -16,7 +16,6 @@ #ifndef HLASMPLUGIN_PARSERLIBRARY_TEST_EXPR_MOCK_H #define HLASMPLUGIN_PARSERLIBRARY_TEST_EXPR_MOCK_H -#include "processing/attribute_provider.h" #include "workspaces/parse_lib_provider.h" using namespace hlasm_plugin::parser_library; @@ -26,15 +25,6 @@ class dep_sol_mock : public context::dependency_solver virtual const context::symbol* get_symbol(context::id_index) const { return nullptr; }; }; -class attr_prov_mock : public processing::attribute_provider -{ - virtual const resolved_reference_storage& lookup_forward_attribute_references(forward_reference_storage) override - { - static resolved_reference_storage st; - return st; - } -}; - class lib_prov_mock : public workspaces::parse_lib_provider { virtual workspaces::parse_result parse_library( diff --git a/parser_library/test/processing/lookahead_test.cpp b/parser_library/test/processing/lookahead_test.cpp index 66f8f5b1a..4c024b751 100644 --- a/parser_library/test/processing/lookahead_test.cpp +++ b/parser_library/test/processing/lookahead_test.cpp @@ -15,6 +15,7 @@ #include "gtest/gtest.h" #include "../common_testing.h" +#include "../expressions/expr_mocks.h" // tests for lookahead feature: // forward/backward jums @@ -192,7 +193,40 @@ TEST(attribute_lookahead, lookup_triggered) analyzer a(input); auto& expr = a.parser().expr()->ca_expr; - EXPECT_EQ(expr->get_undefined_attributed_symbols(a.context().ord_ctx).size(), (size_t)1); + lib_prov_mock lib; + evaluation_context eval_ctx { a.context(), lib }; + + EXPECT_EQ(expr->get_undefined_attributed_symbols(eval_ctx).size(), (size_t)1); + + EXPECT_EQ(a.diags().size(), (size_t)0); +} + +TEST(attribute_lookahead, nested_lookup_triggered) +{ + std::string input("L'&V1(L'&V2)"); + analyzer a(input); + auto& expr = a.parser().expr()->ca_expr; + + lib_prov_mock lib; + evaluation_context eval_ctx { a.context(), lib }; + + auto v1 = a.context().create_local_variable(a.context().ids().add("V1"), false); + v1->access_set_symbol()->set_value("A", 0); + auto v2 = a.context().create_local_variable(a.context().ids().add("V2"), true); + v2->access_set_symbol()->set_value("B"); + + auto res = expr->get_undefined_attributed_symbols(eval_ctx); + ASSERT_EQ(res.size(), (size_t)1); + EXPECT_TRUE(res.find(a.context().ids().add("B")) != res.end()); + + a.context().ord_ctx.add_symbol_reference(context::symbol(a.context().ids().add("B"), + context::symbol_value(), + context::symbol_attributes(context::symbol_origin::EQU, 'U'_ebcdic, 1), + location())); + + res = expr->get_undefined_attributed_symbols(eval_ctx); + ASSERT_EQ(res.size(), (size_t)1); + EXPECT_TRUE(res.find(a.context().ids().add("A")) != res.end()); EXPECT_EQ(a.diags().size(), (size_t)0); } @@ -203,13 +237,16 @@ TEST(attribute_lookahead, lookup_not_triggered) analyzer a(input); auto& expr = a.parser().expr()->ca_expr; + lib_prov_mock lib; + evaluation_context eval_ctx { a.context(), lib }; + // define symbol with undefined length auto tmp = a.context().ord_ctx.create_symbol( a.context().ids().add("X"), symbol_value(), symbol_attributes(symbol_origin::DAT, 200), {}); ASSERT_TRUE(tmp); // although length is undefined the actual symbol is defined so no lookup should happen - EXPECT_EQ(expr->get_undefined_attributed_symbols(a.context().ord_ctx).size(), (size_t)0); + EXPECT_EQ(expr->get_undefined_attributed_symbols(eval_ctx).size(), (size_t)0); EXPECT_EQ(a.diags().size(), (size_t)0); } @@ -220,7 +257,10 @@ TEST(attribute_lookahead, lookup_of_two_refs) analyzer a(input); auto& expr = a.parser().expr()->ca_expr; - EXPECT_EQ(expr->get_undefined_attributed_symbols(a.context().ord_ctx).size(), (size_t)2); + lib_prov_mock lib; + evaluation_context eval_ctx { a.context(), lib }; + + EXPECT_EQ(expr->get_undefined_attributed_symbols(eval_ctx).size(), (size_t)2); EXPECT_EQ(a.diags().size(), (size_t)0); } @@ -231,7 +271,10 @@ TEST(attribute_lookahead, lookup_of_two_refs_but_one_symbol) analyzer a(input); auto& expr = a.parser().expr()->ca_expr; - EXPECT_EQ(expr->get_undefined_attributed_symbols(a.context().ord_ctx).size(), (size_t)1); + lib_prov_mock lib; + evaluation_context eval_ctx { a.context(), lib }; + + EXPECT_EQ(expr->get_undefined_attributed_symbols(eval_ctx).size(), (size_t)1); EXPECT_EQ(a.diags().size(), (size_t)0); } @@ -295,7 +338,7 @@ X EQU 1,10,C'T' EXPECT_EQ(a.diags().size(), (size_t)1); } -TEST(EQU_attribute_lookahead, unresolvable_attribute_referece) +TEST(EQU_attribute_lookahead, unresolvable_attribute_reference) { std::string input( R"( @@ -314,7 +357,8 @@ X EQU 1,Y+11,C'T' ->get_value(), 1); - EXPECT_EQ(a.diags().size(), (size_t)2); + EXPECT_EQ(a.diags().size(), (size_t)1); + EXPECT_EQ(a.diags().front().diag_range.start.line, (size_t)2); } TEST(EQU_attribute_lookahead, errorous_but_resolable_statement_incorrect_operand) @@ -862,6 +906,26 @@ A EQU 1,2,1 EXPECT_EQ(a.diags().size(), (size_t)0); } +TEST(attribute_lookahead, lookahead_from_instruction_field_macro) +{ + std::string input( + R"( + MACRO + M +&A(1) SETC 'LR','SAM64','LR' + &A(L'A) + MEND + M +A EQU 1,2,1 +)"); + + analyzer a(input); + a.analyze(); + a.collect_diags(); + + EXPECT_EQ(a.diags().size(), (size_t)0); +} + TEST(EQU_attribute_lookahead, location_counter_use) { std::string input( @@ -872,13 +936,14 @@ X EQU 1,*-Y AIF (L'A EQ 4).NO B LR 1,1 -A DC AL(*-B)(*) +A DC AL(*-B+2)(*) )"); analyzer a(input); a.analyze(); a.collect_diags(); - ASSERT_EQ(a.diags().size(), (size_t)2); + ASSERT_EQ(a.diags().size(), (size_t)1); EXPECT_EQ(a.diags().front().severity, diagnostic_severity::warning); + EXPECT_EQ(a.diags().front().diag_range.start.line, (size_t)5); } diff --git a/parser_library/test/res/input/macro_model.in b/parser_library/test/res/input/macro_model.in index 36de9c534..b9c26e752 100644 --- a/parser_library/test/res/input/macro_model.in +++ b/parser_library/test/res/input/macro_model.in @@ -3,7 +3,7 @@ m &v DC FD'&V' mend - m +'string with space' m macro xxxxxxxx &p1=,&p2=,&p3=,&p4=,&p5=,&ppp6=,&p7= diff --git a/parser_library/test/semantics/operand_test.cpp b/parser_library/test/semantics/operand_test.cpp new file mode 100644 index 000000000..8065b6fcd --- /dev/null +++ b/parser_library/test/semantics/operand_test.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2019 Broadcom. + * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + */ + +#include "gmock/gmock.h" + +#include "semantics/operand.h" + +using namespace hlasm_plugin::parser_library::semantics; +using namespace hlasm_plugin::parser_library; + +bool access_op(operand_type type, operand* o) +{ + auto asm_op = o->access_asm(); + if ((type == operand_type::ASM) != (asm_op != nullptr)) // equivalence negation + return false; + auto ca_op = o->access_ca(); + if ((type == operand_type::CA) != (ca_op != nullptr)) + return false; + auto dat_op = o->access_data_def(); + if ((type == operand_type::DAT) != (dat_op != nullptr)) + return false; + auto mac_op = o->access_mac(); + if ((type == operand_type::MAC) != (mac_op != nullptr)) + return false; + auto mach_op = o->access_mach(); + if ((type == operand_type::MACH) != (mach_op != nullptr)) + return false; + auto model_op = o->access_model(); + if ((type == operand_type::MODEL) != (model_op != nullptr)) + return false; + + return true; +} + +bool access_mach_op(mach_kind kind, machine_operand* o) +{ + auto expr_op = o->access_expr(); + if ((kind == mach_kind::EXPR) != (expr_op != nullptr)) + return false; + auto addr_op = o->access_address(); + if ((kind == mach_kind::ADDR) != (addr_op != nullptr)) + return false; + + operand* op = o; + return access_op(operand_type::MACH, op); +} + +bool access_asm_op(asm_kind kind, assembler_operand* o) +{ + auto expr_op = o->access_expr(); + if ((kind == asm_kind::EXPR) != (expr_op != nullptr)) + return false; + auto base_op = o->access_base_end(); + if ((kind == asm_kind::BASE_END) != (base_op != nullptr)) + return false; + auto complex_op = o->access_complex(); + if ((kind == asm_kind::COMPLEX) != (complex_op != nullptr)) + return false; + auto string_op = o->access_string(); + if ((kind == asm_kind::STRING) != (string_op != nullptr)) + return false; + + operand* op = o; + return access_op(operand_type::ASM, op); +} + +bool access_ca_op(ca_kind kind, ca_operand* o) +{ + auto var_op = o->access_var(); + if ((kind == ca_kind::VAR) != (var_op != nullptr)) + return false; + auto expr_op = o->access_expr(); + if ((kind == ca_kind::EXPR) != (expr_op != nullptr)) + return false; + auto seq_op = o->access_seq(); + if ((kind == ca_kind::SEQ) != (seq_op != nullptr)) + return false; + auto branch_op = o->access_branch(); + if ((kind == ca_kind::BRANCH) != (branch_op != nullptr)) + return false; + + operand* op = o; + return access_op(operand_type::CA, op); +} + +bool access_mac_op(mac_kind kind, macro_operand* o) +{ + auto chain_op = o->access_chain(); + if ((kind == mac_kind::CHAIN) != (chain_op != nullptr)) + return false; + auto string_op = o->access_string(); + if ((kind == mac_kind::STRING) != (string_op != nullptr)) + return false; + + operand* op = o; + return access_op(operand_type::MAC, op); +} + +TEST(operand, access_operand) +{ + // model operand + model_operand mo({}, range()); + EXPECT_TRUE(access_op(operand_type::MODEL, &mo)); + + // machine operand + // expr + expr_machine_operand emo(nullptr, range()); + EXPECT_TRUE(access_mach_op(mach_kind::EXPR, &emo)); + // addr + address_machine_operand amo(nullptr, nullptr, nullptr, range(), checking::operand_state::FIRST_OMITTED); + EXPECT_TRUE(access_mach_op(mach_kind::ADDR, &amo)); + + // assembler operand + // expr + expr_assembler_operand eao(nullptr, "", range()); + EXPECT_TRUE(access_asm_op(asm_kind::EXPR, &eao)); + // base end + using_instr_assembler_operand uao(nullptr, nullptr, range()); + EXPECT_TRUE(access_asm_op(asm_kind::BASE_END, &uao)); + // complex + complex_assembler_operand cao("", {}, range()); + EXPECT_TRUE(access_asm_op(asm_kind::COMPLEX, &cao)); + // string + string_assembler_operand sao("", range()); + EXPECT_TRUE(access_asm_op(asm_kind::STRING, &sao)); + + // datadef operand + data_def_operand ddo({}, range()); + EXPECT_TRUE(access_op(operand_type::DAT, &ddo)); + + // ca operand + // var + var_ca_operand vco(nullptr, range()); + EXPECT_TRUE(access_ca_op(ca_kind::VAR, &vco)); + // expr + expr_ca_operand eco(nullptr, range()); + EXPECT_TRUE(access_ca_op(ca_kind::EXPR, &eco)); + // seq + seq_ca_operand sco({}, range()); + EXPECT_TRUE(access_ca_op(ca_kind::SEQ, &sco)); + // branch + branch_ca_operand bco({}, nullptr, range()); + EXPECT_TRUE(access_ca_op(ca_kind::BRANCH, &bco)); + + // macro operand + // chain + macro_operand_chain moc({}, range()); + EXPECT_TRUE(access_mac_op(mac_kind::CHAIN, &moc)); + // string + macro_operand_string mos("", range()); + EXPECT_TRUE(access_mac_op(mac_kind::STRING, &mos)); +}