File: parser_report.h

package info (click to toggle)
libpog 0.5.3-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 3,644 kB
  • sloc: cpp: 51,038; ansic: 239; makefile: 14; python: 11; sh: 11
file content (87 lines) | stat: -rw-r--r-- 2,651 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#pragma once

#include <variant>
#include <vector>

#include <pog/rule.h>
#include <pog/state.h>

namespace pog {

template <typename ValueT>
struct ShiftReduceConflict
{
	const State<ValueT>* state;
	const Symbol<ValueT>* symbol;
	const Rule<ValueT>* rule;

	std::string to_string(std::string_view arrow = "->", std::string_view eps = "<eps>") const
	{
		return fmt::format("Shift-reduce conflict of symbol \'{}\' and rule \'{}\' in state {}", symbol->get_name(), rule->to_string(arrow, eps), state->get_index());
	}
};

template <typename ValueT>
struct ReduceReduceConflict
{
	const State<ValueT>* state;
	const Rule<ValueT>* rule1;
	const Rule<ValueT>* rule2;

	std::string to_string(std::string_view arrow = "->", std::string_view eps = "<eps>") const
	{
		return fmt::format("Reduce-reduce conflict of rule \'{}\' and rule \'{}\' in state {}", rule1->to_string(arrow, eps), rule2->to_string(arrow, eps), state->get_index());
	}
};

template <typename ValueT>
using Issue = std::variant<ShiftReduceConflict<ValueT>, ReduceReduceConflict<ValueT>>;

template <typename ValueT>
class ParserReport
{
public:
	using IssueType = Issue<ValueT>;
	using RuleType = Rule<ValueT>;
	using StateType = State<ValueT>;
	using SymbolType = Symbol<ValueT>;

	using ReduceReduceConflictType = ReduceReduceConflict<ValueT>;
	using ShiftReduceConflictType = ShiftReduceConflict<ValueT>;

	bool ok() const { return _issues.empty(); }
	operator bool() const { return ok(); }

	std::size_t number_of_issues() const { return _issues.size(); }
	auto begin() { return _issues.begin(); }
	auto end() { return _issues.end(); }
	auto begin() const { return _issues.begin(); }
	auto end() const { return _issues.end(); }

	void add_shift_reduce_conflict(const StateType* state, const SymbolType* symbol, const RuleType* rule)
	{
		_issues.push_back(ShiftReduceConflictType{state, symbol, rule});
	}

	void add_reduce_reduce_conflict(const StateType* state, const RuleType* rule1, const RuleType* rule2)
	{
		_issues.push_back(ReduceReduceConflictType{state, rule1, rule2});
	}

	std::string to_string(std::string_view arrow = "->", std::string_view eps = "<eps>") const
	{
		std::vector<std::string> issues_str(_issues.size());
		std::transform(_issues.begin(), _issues.end(), issues_str.begin(), [&](const auto& issue) {
			return visit_with(issue,
				[&](const ShiftReduceConflictType& sr) { return sr.to_string(arrow, eps); },
				[&](const ReduceReduceConflictType& rr) { return rr.to_string(arrow, eps); }
			);
		});
		return fmt::format("{}", fmt::join(issues_str.begin(), issues_str.end(), "\n"));
	}

private:
	std::vector<IssueType> _issues;
};

} // namespace pog