Skip to content

Commit

Permalink
feat: DB2 preprocessor statements highlighting and parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
jirimosinger authored Jan 6, 2023
1 parent 9938bc2 commit 73b545f
Show file tree
Hide file tree
Showing 26 changed files with 1,624 additions and 521 deletions.
2 changes: 1 addition & 1 deletion clients/vscode-hlasmplugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
- Command for downloading copybooks allows selections of data sets which should be downloaded
- Code actions for an unknown operation code
- Quick fixes for typos in instruction and macro names added to the code actions
- Endevor and CICS preprocessor statements highlighting and parsing
- Endevor, CICS and DB2 preprocessor statements highlighting and parsing
- Instruction suggestions are included in the completion list
- Support for the SYSCLOCK system variable
- Implement step out support in the macro tracer
Expand Down
21 changes: 18 additions & 3 deletions parser_library/src/diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2348,18 +2348,33 @@ diagnostic_op diagnostic_op::error_DB004(const range& range)
{
return diagnostic_op(diagnostic_severity::error,
"DB004",
std::string("DB2 preprocessor - requested SQL TYPE not recognized"),
std::string(
"DB2 preprocessor - requested 'SQL TYPE IS' not recognized (operands either missing or not recognized)"),
range);
}

diagnostic_op diagnostic_op::error_DB005(const range& range)
diagnostic_op diagnostic_op::warn_DB005(const range& range)
{
return diagnostic_op(diagnostic_severity::warning,
"DB005",
std::string("DB2 preprocessor - continuation detected on SQL TYPE statement"),
std::string("DB2 preprocessor - continuation detected on 'SQL TYPE' statement"),
range);
}

diagnostic_op diagnostic_op::warn_DB006(const range& range)
{
return diagnostic_op(diagnostic_severity::warning,
"DB006",
std::string("DB2 preprocessor - requested 'SQL TYPE' not recognized (operand 'IS' either missing or split)"),
range);
}

diagnostic_op diagnostic_op::warn_DB007(const range& range)
{
return diagnostic_op(
diagnostic_severity::warning, "DB007", std::string("DB2 preprocessor - missing INCLUDE member"), range);
}

diagnostic_op diagnostic_op::warn_CIC001(const range& range)
{
return diagnostic_op(diagnostic_severity::warning,
Expand Down
6 changes: 5 additions & 1 deletion parser_library/src/diagnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,11 @@ struct diagnostic_op

static diagnostic_op error_DB004(const range& range);

static diagnostic_op error_DB005(const range& range);
static diagnostic_op warn_DB005(const range& range);

static diagnostic_op warn_DB006(const range& range);

static diagnostic_op warn_DB007(const range& range);

static diagnostic_op warn_CIC001(const range& range);

Expand Down
54 changes: 34 additions & 20 deletions parser_library/src/lexing/logical_line.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
#define HLASMPLUGIN_HLASMPARSERLIBRARY_LOGICAL_LINE_H

#include <cassert>
#include <limits>
#include <cstddef>
#include <cstdlib>
#include <iterator>
#include <memory>
#include <string_view>
#include <utility>
#include <vector>

namespace hlasm_plugin::parser_library::lexing {
Expand Down Expand Up @@ -63,7 +66,7 @@ struct logical_line
bool so_si_continuation;
bool missing_next_line;

void clear()
void clear() noexcept
{
segments.clear();
continuation_error = false;
Expand All @@ -83,26 +86,26 @@ struct logical_line
using reference = const char&;

const_iterator() = default;
const_iterator(segment_iterator segment, column_iterator col, const logical_line* ll)
: m_segment(segment)
, m_col(col)
const_iterator(segment_iterator segment_it, column_iterator col_it, const logical_line* ll) noexcept
: m_segment_it(segment_it)
, m_col_it(col_it)
, m_logical_line(ll)
{}

reference operator*() const noexcept { return *m_col; }
pointer operator->() const noexcept { return std::to_address(m_col); }
reference operator*() const noexcept { return *m_col_it; }
pointer operator->() const noexcept { return std::to_address(m_col_it); }
const_iterator& operator++() noexcept
{
assert(m_logical_line);
++m_col;
while (m_col == m_segment->code.end())
++m_col_it;
while (m_col_it == m_segment_it->code.end())
{
if (++m_segment == m_logical_line->segments.end())
if (++m_segment_it == m_logical_line->segments.end())
{
m_col = column_iterator();
m_col_it = column_iterator();
break;
}
m_col = m_segment->code.begin();
m_col_it = m_segment_it->code.begin();
}
return *this;
}
Expand All @@ -115,12 +118,12 @@ struct logical_line
const_iterator& operator--() noexcept
{
assert(m_logical_line);
while (m_segment == m_logical_line->segments.end() || m_col == m_segment->code.begin())
while (m_segment_it == m_logical_line->segments.end() || m_col_it == m_segment_it->code.begin())
{
--m_segment;
m_col = m_segment->code.end();
--m_segment_it;
m_col_it = m_segment_it->code.end();
}
--m_col;
--m_col_it;
return *this;
}
const_iterator operator--(int) noexcept
Expand All @@ -132,19 +135,30 @@ struct logical_line
friend bool operator==(const const_iterator& a, const const_iterator& b) noexcept
{
assert(a.m_logical_line == b.m_logical_line);
return a.m_segment == b.m_segment && a.m_col == b.m_col;
return a.m_segment_it == b.m_segment_it && a.m_col_it == b.m_col_it;
}
friend bool operator!=(const const_iterator& a, const const_iterator& b) noexcept { return !(a == b); }

bool same_line(const const_iterator& o) const noexcept
{
assert(m_logical_line == o.m_logical_line);
return m_segment == o.m_segment;
return m_segment_it == o.m_segment_it;
}

std::pair<size_t, size_t> get_coordinates() const noexcept
{
assert(m_logical_line);

if (m_segment_it == m_logical_line->segments.end())
return { 0, 0 };

return { m_segment_it->code_offset + std::distance(m_segment_it->code.begin(), m_col_it),
std::distance(m_logical_line->segments.begin(), m_segment_it) };
}

private:
segment_iterator m_segment = segment_iterator();
column_iterator m_col = std::string_view::const_iterator();
segment_iterator m_segment_it = segment_iterator();
column_iterator m_col_it = std::string_view::const_iterator();
const logical_line* m_logical_line = nullptr;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,50 +89,32 @@ bool low_language_processor::create_symbol(
return ok;
}

// return true if the result is not empty
bool trim_right(std::string& s)
{
auto last_non_space = s.find_last_not_of(' ');
if (last_non_space != std::string::npos)
{
s.erase(last_non_space + 1);
return true;
}
else
{
s.clear();
return false;
}
}

low_language_processor::preprocessed_part low_language_processor::preprocess_inner(const resolved_statement& stmt)
{
using namespace semantics;
preprocessed_part result;

std::string new_label;
const auto label_inserter = [&result, &ids = hlasm_ctx.ids()](std::string&& label, const range& r) {
label.erase(label.find_last_not_of(' ') + 1);
if (label.empty())
result.label.emplace(r);
else
{
auto ord_id = ids.add(label);
result.label.emplace(r, ord_symbol_string { ord_id, std::move(label) });
}
};

// label
switch (const auto& label_ref = stmt.label_ref(); label_ref.type)
{
case label_si_type::CONC:
new_label = concatenation_point::evaluate(std::get<concat_chain>(label_ref.value), eval_ctx);
if (!trim_right(new_label))
result.label.emplace(label_ref.field_range);
else
{
auto ord_id = hlasm_ctx.ids().add(new_label);
result.label.emplace(label_ref.field_range, ord_symbol_string { ord_id, std::move(new_label) });
}
label_inserter(concatenation_point::evaluate(std::get<concat_chain>(label_ref.value), eval_ctx),
label_ref.field_range);
break;
case label_si_type::VAR:
new_label = var_sym_conc::evaluate(std::get<vs_ptr>(label_ref.value)->evaluate(eval_ctx));
if (!trim_right(new_label))
result.label.emplace(label_ref.field_range);
else
{
auto ord_id = hlasm_ctx.ids().add(new_label);
result.label.emplace(label_ref.field_range, ord_symbol_string { ord_id, std::move(new_label) });
}
label_inserter(
var_sym_conc::evaluate(std::get<vs_ptr>(label_ref.value)->evaluate(eval_ctx)), label_ref.field_range);
break;
case label_si_type::MAC:
if (stmt.opcode_ref().value.to_string_view() != "TITLE")
Expand Down
32 changes: 27 additions & 5 deletions parser_library/src/processing/preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,36 @@ void preprocessor::do_highlighting(const semantics::preprocessor_statement_si& s

src_proc.add_hl_symbol(token_info(details.instruction.r, semantics::hl_scopes::instruction), continue_column);

for (const auto& operand : details.operands.items)
{
for (const auto& operand : details.operands)
src_proc.add_hl_symbol(token_info(operand.r, semantics::hl_scopes::operand), continue_column);
}

for (const auto& remark_r : details.remarks.items)
{
for (const auto& remark_r : details.remarks)
src_proc.add_hl_symbol(token_info(remark_r, semantics::hl_scopes::remark), continue_column);
}

void preprocessor::do_highlighting(const semantics::preprocessor_statement_si& stmt,
const lexing::logical_line& ll,
semantics::source_info_processor& src_proc,
size_t continue_column) const
{
do_highlighting(stmt, src_proc, continue_column);

constexpr const auto continuation_column = lexing::default_ictl.end;
constexpr const auto ignore_column = lexing::default_ictl.end + 1;
for (size_t i = 0, lineno = stmt.m_details.stmt_r.start.line; i < ll.segments.size(); ++i, ++lineno)
{
const auto& segment = ll.segments[i];

if (!segment.continuation.empty())
src_proc.add_hl_symbol(
token_info(range(position(lineno, continuation_column), position(lineno, ignore_column)),
semantics::hl_scopes::continuation));

if (!segment.ignore.empty())
src_proc.add_hl_symbol(token_info(
range(position(lineno, ignore_column),
position(lineno, ignore_column + segment.ignore.length() - segment.continuation.empty())),
semantics::hl_scopes::ignored));
}
}

Expand Down
19 changes: 12 additions & 7 deletions parser_library/src/processing/preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ using library_fetcher =
class preprocessor
{
public:
using line_iterator = std::vector<document_line>::const_iterator;

struct included_member_details
{
std::string name;
Expand All @@ -78,18 +80,16 @@ class preprocessor

virtual const std::vector<std::unique_ptr<included_member_details>>& view_included_members();

protected:
preprocessor() = default;
preprocessor(const preprocessor&) = default;
preprocessor(preprocessor&&) = default;

using line_iterator = std::vector<document_line>::const_iterator;

static line_iterator extract_nonempty_logical_line(lexing::logical_line& out,
line_iterator it,
line_iterator end,
const lexing::logical_line_extractor_args& opts);

protected:
preprocessor() = default;
preprocessor(const preprocessor&) = default;
preprocessor(preprocessor&&) = default;

void reset();
void set_statement(std::shared_ptr<semantics::preprocessor_statement_si> stmt);
void set_statements(std::vector<std::shared_ptr<semantics::preprocessor_statement_si>> stmts);
Expand All @@ -100,6 +100,11 @@ class preprocessor
semantics::source_info_processor& src_proc,
size_t continue_column = 15) const;

virtual void do_highlighting(const semantics::preprocessor_statement_si& stmt,
const lexing::logical_line& ll,
semantics::source_info_processor& src_proc,
size_t continue_column = 15) const;

void append_included_member(std::unique_ptr<included_member_details> details);
void append_included_members(std::vector<std::unique_ptr<included_member_details>> details);
void capture_included_members(preprocessor& preproc);
Expand Down
Loading

0 comments on commit 73b545f

Please sign in to comment.