VapourSynth-llvmexpr
Loading...
Searching...
No Matches
main.cpp File Reference
#include "ASTPrinter.hpp"
#include "AnalysisEngine.hpp"
#include "Preprocessor.hpp"
#include "Tokenizer.hpp"
#include <format>
#include <fstream>
#include <iostream>
#include <span>
#include <sstream>
#include <string>
#include <string_view>
Include dependency graph for main.cpp:

Go to the source code of this file.

Functions

void print_usage ()
int main (int argc, char *argv[])

Function Documentation

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 48 of file main.cpp.

48 {
49 std::string input_file;
50 std::string output_file;
51 Mode mode = Mode::Expr;
52 bool dump_ast = false;
53 bool preprocess_only = false;
54 std::vector<std::pair<std::string, std::string>> predefined_macros;
55
56 auto args = std::span(argv, argc);
57
58 if (argc < 2) {
60 return 1;
61 }
62
63 for (int i = 1; i < argc; ++i) {
64 std::string_view arg = args[i];
65
66 if (!arg.starts_with('-')) {
67 if (!input_file.empty()) {
68 std::cerr << "Error: Only one input file can be specified.\n";
69 return 1;
70 }
71 input_file = arg;
72 continue;
73 }
74
75 if (arg == "-o") {
76 if (i + 1 >= argc) {
77 std::cerr << "Error: -o requires an argument\n";
78 return 1;
79 }
80 output_file = args[++i];
81 } else if (arg == "-m") {
82 if (i + 1 >= argc) {
83 std::cerr << "Error: -m requires an argument\n";
84 return 1;
85 }
86 std::string_view mode_str = args[++i];
87 if (mode_str == "single") {
88 mode = Mode::Single;
89 } else if (mode_str != "expr") {
90 std::cerr << std::format(
91 "Error: Invalid mode '{}'. Use 'expr' or 'single'.\n",
92 std::string(mode_str));
93 return 1;
94 }
95 } else if (arg == "-D") {
96 if (i + 1 >= argc) {
97 std::cerr << "Error: -D requires an argument\n";
98 return 1;
99 }
100 std::string_view macro_def = args[++i];
101 size_t eq_pos = macro_def.find('=');
102 if (eq_pos != std::string_view::npos) {
103 std::string name(macro_def.substr(0, eq_pos));
104 std::string value(macro_def.substr(eq_pos + 1));
105 predefined_macros.emplace_back(std::move(name),
106 std::move(value));
107 } else {
108 predefined_macros.emplace_back(std::string(macro_def), "");
109 }
110 } else if (arg == "--dump-ast") {
111 dump_ast = true;
112 } else if (arg == "-E") {
113 preprocess_only = true;
114 } else {
115 std::cerr << std::format("Error: Unknown option '{}'\n",
116 std::string(arg));
117 print_usage();
118 return 1;
119 }
120 }
121
122 if (input_file.empty()) {
123 std::cerr << "Error: No input file specified.\n";
124 print_usage();
125 return 1;
126 }
127
128 if (preprocess_only) {
129 if (dump_ast) {
130 std::cerr << "Error: --dump-ast and -E cannot be used together\n";
131 return 1;
132 }
133 if (!output_file.empty()) {
134 std::cerr << "Error: -o and -E cannot be used together\n";
135 return 1;
136 }
137 } else {
138 if (output_file.empty()) {
139 std::cerr << "Error: Output file must be specified with -o\n";
140 print_usage();
141 return 1;
142 }
143 }
144
145 std::ifstream in_stream(input_file);
146 if (!in_stream) {
147 std::cerr << std::format("Error: Cannot open input file '{}'\n",
148 input_file);
149 return 1;
150 }
151 std::stringstream buffer;
152 buffer << in_stream.rdbuf();
153 std::string source = buffer.str();
154
155 try {
157
158 if (mode == Mode::Expr) {
159 preprocessor.addPredefinedMacro("__EXPR__", "");
160 } else if (mode == Mode::VkExpr) {
161 preprocessor.addPredefinedMacro("__EXPR__", "");
162 preprocessor.addPredefinedMacro("__GPU__", "");
163 } else {
164 preprocessor.addPredefinedMacro("__SINGLEEXPR__", "");
165 }
166
167 for (const auto& [name, value] : predefined_macros) {
168 preprocessor.addPredefinedMacro(name, value);
169 }
170
171 auto preprocess_result = preprocessor.process();
172
173 if (!preprocess_result.success) {
174 std::cerr << "Preprocessing errors:\n";
175 for (const auto& error : preprocess_result.errors) {
176 std::cerr << error << "\n";
177 }
178 return 1;
179 }
180
181 if (preprocess_only) {
182 std::cout << "=== Preprocessed Code ===\n";
183 std::cout << preprocess_result.source << "\n";
184 std::cout << "\n=== Macro Expansion Trace ===\n";
185
186 std::string expansion_info =
187 Preprocessor::formatMacroExpansions(preprocess_result.line_map);
188 if (expansion_info.empty()) {
189 std::cout << "(No macro expansions)\n";
190 } else {
191 std::cout << expansion_info;
192 }
193
194 return 0;
195 }
196
197 Tokenizer tokenizer(preprocess_result.source);
198 auto tokens = tokenizer.tokenize();
199
200 AnalysisEngine engine(
201 tokens, mode,
202 114514, // NOLINT(cppcoreguidelines-avoid-magic-numbers)
203 0, preprocess_result.line_map,
204 preprocess_result.library_line_count);
205
206 bool success = engine.runAnalysis();
207
208 if (dump_ast) {
209 ASTPrinter printer;
210 std::cout << "--- AST Dump ---\n"
211 << printer.print(engine.getAST())
212 << "--- End AST Dump ---\n";
213 }
214
215 std::string diagnostics = engine.formatDiagnostics();
216
217 if (!success) {
218 std::cerr << std::format("Analysis errors:\n{}\n", diagnostics);
219 return 1;
220 }
221 if (!diagnostics.empty()) {
222 std::cerr << std::format("Analysis warnings:\n{}\n", diagnostics);
223 }
224
225 std::string postfix_code = engine.generateCode();
226
227 std::ofstream out_stream(output_file);
228 if (!out_stream) {
229 std::cerr << std::format("Error: Cannot open output file '{}'\n",
230 output_file);
231 return 1;
232 }
233 out_stream << postfix_code << '\n';
234
235 std::cout << std::format("Successfully converted '{}' to '{}'\n",
236 input_file, output_file);
237
238 } catch (const std::exception& e) {
239 std::cerr << std::format("An error occurred: {}\n", e.what());
240 return 1;
241 }
242
243 return 0;
244}
std::string print(const Program *program)
static std::string formatMacroExpansions(const std::vector< LineMapping > &line_map)
void print_usage()
Definition main.cpp:35

References infix2postfix::Expr, infix2postfix::AnalysisEngine::formatDiagnostics(), infix2postfix::Preprocessor::formatMacroExpansions(), infix2postfix::AnalysisEngine::generateCode(), infix2postfix::AnalysisEngine::getAST(), infix2postfix::ASTPrinter::print(), print_usage(), infix2postfix::AnalysisEngine::runAnalysis(), infix2postfix::Single, infix2postfix::Tokenizer::tokenize(), and infix2postfix::VkExpr.

◆ print_usage()

void print_usage ( )

Definition at line 35 of file main.cpp.

35 {
36 std::cerr << "Usage: infix2postfix <in.expr> -m [expr/single] -o "
37 "<out.expr> [-D MACRO[=value]] [--dump-ast] [-E]"
38 << '\n';
39 std::cerr << "Options:\n";
40 std::cerr << " -m MODE Set mode (expr or single)\n";
41 std::cerr << " -o FILE Output file\n";
42 std::cerr << " -D MACRO[=VAL] Define preprocessor macro\n";
43 std::cerr << " --dump-ast Dump the AST\n";
44 std::cerr << " -E Output preprocessed code and macro "
45 "expansion trace\n";
46}

Referenced by main().