VapourSynth-llvmexpr
Loading...
Searching...
No Matches
AnalysisEngine.cpp
Go to the documentation of this file.
1
19
20#include "AnalysisEngine.hpp"
21#include "CodeGenerator.hpp"
22#include "Parser.hpp"
23#include "SemanticAnalyzer.hpp"
25
26#include <algorithm>
27#include <format>
28
29namespace infix2postfix {
30
31AnalysisEngine::AnalysisEngine(const std::vector<Token>& tokens, Mode mode,
32 int num_inputs, int num_intermediate_inputs,
33 const std::vector<LineMapping>& line_map,
34 int library_line_count)
35 : tokens(tokens), mode(mode), num_inputs(num_inputs),
36 num_intermediate_inputs(num_intermediate_inputs), line_map(line_map),
37 library_line_count(library_line_count) {}
38
40
42 diagnostics.clear();
43
44 Parser parser(tokens);
45 auto parse_result = parser.parse();
46 ast = std::move(parse_result.ast);
47
48 std::ranges::transform(parse_result.errors, std::back_inserter(diagnostics),
49 [](const auto& error) {
50 return Diagnostic(DiagnosticSeverity::Error,
51 error.message, error.range);
52 });
53
54 if (!ast || hasErrors()) {
55 return false;
56 }
57
58 semantic_analyzer = std::make_unique<SemanticAnalyzer>(
59 mode, num_inputs, num_intermediate_inputs, library_line_count);
60 semantic_analyzer->analyze(ast.get());
61
62 const auto& semantic_diagnostics = semantic_analyzer->getDiagnostics();
63 diagnostics.insert(diagnostics.end(), semantic_diagnostics.begin(),
64 semantic_diagnostics.end());
65
66 return !hasErrors();
67}
68
70 if (!ast || !semantic_analyzer) {
71 throw std::runtime_error(
72 "Cannot generate code: analysis not run or failed");
73 }
74
75 if (hasErrors()) {
76 throw std::runtime_error(
77 "Cannot generate code: semantic analysis had errors");
78 }
79
80 CodeGenerator code_generator(mode, num_inputs, num_intermediate_inputs);
81
82 return code_generator.generate(ast.get());
83}
84
86 return std::ranges::any_of(diagnostics, [](const auto& diag) {
87 return diag.severity == DiagnosticSeverity::Error;
88 });
89}
90
92 if (diagnostics.empty()) {
93 return "";
94 }
95
96 std::string result;
97 int error_count = 0;
98 int warning_count = 0;
99
100 for (const auto& diag : diagnostics) {
101 if (diag.severity == DiagnosticSeverity::Error) {
102 error_count++;
103 } else {
104 warning_count++;
105 }
106
107 if (!result.empty()) {
108 result += "\n";
109 }
110 std::string severity_name = std::string(enum_name(diag.severity));
111
112 const LineMapping* mapping = nullptr;
113 auto it = std::ranges::find_if(line_map, [&](const auto& m) {
114 return m.preprocessed_line == diag.range.start.line;
115 });
116 if (it != line_map.end()) {
117 mapping = &(*it);
118 }
119
120 Range range = diag.range;
121 std::string message = diag.message;
122
123 if (mapping != nullptr) {
124 range.start.line = mapping->original_line;
125 range.end.line = mapping->original_line;
126
127 if (!mapping->expansions.empty()) {
128 std::string expansion_trace;
129 std::vector<const MacroExpansion*> containing_expansions;
130
131 for (const auto& expansion : mapping->expansions) {
132 if (diag.range.start.column + 1 >=
133 expansion.preprocessed_start_column &&
134 diag.range.end.column <
135 expansion.preprocessed_end_column) {
136 containing_expansions.push_back(&expansion);
137 }
138 }
139
140 std::ranges::sort(containing_expansions,
141 [](const auto* a, const auto* b) {
142 return (a->preprocessed_end_column -
143 a->preprocessed_start_column) <
144 (b->preprocessed_end_column -
145 b->preprocessed_start_column);
146 });
147
148 for (const auto* expansion : containing_expansions) {
149 expansion_trace += std::format(
150 "\n note: in expansion of macro '{}' from {}:{}",
151 expansion->macro_name, mapping->original_line,
152 expansion->original_column);
153 }
154 message += expansion_trace;
155 }
156 }
157
158 result += std::format("{} - {}: {}", range.to_string(), severity_name,
159 message);
160 }
161
162 std::string summary;
163 if (error_count > 0 && warning_count > 0) {
164 summary = std::format("\nFound {} error(s) and {} warning(s).",
165 error_count, warning_count);
166 } else if (error_count > 0) {
167 summary = std::format("\nFound {} error(s).", error_count);
168 } else if (warning_count > 0) {
169 summary = std::format("\nFound {} warning(s).", warning_count);
170 }
171
172 result += summary;
173 return result;
174}
175
176} // namespace infix2postfix
consteval std::string_view enum_name()
Definition EnumName.hpp:57
std::string formatDiagnostics() const
AnalysisEngine(const std::vector< Token > &tokens, Mode mode, int num_inputs, int num_intermediate_inputs, const std::vector< LineMapping > &line_map, int library_line_count=0)
std::string generate(const Program *program)
ParseResult parse()
Definition Parser.cpp:32
std::vector< MacroExpansion > expansions
SourceLocation end
Definition types.hpp:48
std::string to_string() const
Definition types.hpp:51
SourceLocation start
Definition types.hpp:47