forked from sfztools/sfizz
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPreprocessor.cpp
110 lines (88 loc) · 3.56 KB
/
Preprocessor.cpp
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
/*
This program reads a SFZ file, and outputs it back into a single file
with all the includes and definitions processed.
It can serve to facilitate identifying problems, whether these are related to
the parser or complicated instrument structures.
*/
#include "parser/Parser.h"
#include "../tests/cxxopts.hpp"
#include "absl/strings/string_view.h"
#include <iostream>
class MyParserListener : public sfz::Parser::Listener {
public:
explicit MyParserListener(sfz::Parser& parser)
: _parser(parser)
{
}
protected:
void onParseFullBlock(const std::string& header, const std::vector<sfz::Opcode>& opcodes) override
{
std::cout << '\n';
std::cout << '<' << header << '>' << '\n';
for (const sfz::Opcode& opc : opcodes)
std::cout << opc.opcode << '=' << opc.value << '\n';
}
void onParseError(const sfz::SourceRange& range, const std::string& message) override
{
const auto relativePath = range.start.filePath->lexically_relative(_parser.originalDirectory());
std::cerr << "Parse error in " << relativePath << " at line " << range.start.lineNumber + 1 << ": " << message << '\n';
}
void onParseWarning(const sfz::SourceRange& range, const std::string& message) override
{
const auto relativePath = range.start.filePath->lexically_relative(_parser.originalDirectory());
std::cerr << "Parse warning in " << relativePath << " at line " << range.start.lineNumber + 1 << ": " << message << '\n';
}
private:
sfz::Parser& _parser;
};
int main(int argc, char *argv[])
{
cxxopts::Options options("sfizz_preprocess", "Preprocess SFZ files");
options.positional_help("<sfz-file>");
options.add_options()
("D,define", "Add external definition", cxxopts::value<std::vector<std::string>>())
("i,input", "Input SFZ file", cxxopts::value<std::string>())
("h,help", "Print usage");
options.parse_positional({"input"});
std::unique_ptr<cxxopts::ParseResult> resultPtr;
try {
resultPtr = absl::make_unique<cxxopts::ParseResult>(options.parse(argc, argv));
} catch (cxxopts::OptionException& ex) {
std::cerr << ex.what() << "\n";
return 1;
}
cxxopts::ParseResult& result = *resultPtr;
if (result.count("help")) {
std::cerr << options.help() << "\n";
return 0;
}
if (!result.count("input")) {
std::cerr << "Please indicate the SFZ file path.\n";
return 1;
}
const fs::path sfzFilePath { result["input"].as<std::string>() };
sfz::Parser parser;
MyParserListener listener(parser);
parser.setListener(&listener);
if (result.count("define")) {
auto& definitions = result["define"].as<std::vector<std::string>>();
for (absl::string_view definition : definitions) {
size_t pos = definition.find('=');
if (pos == definition.npos) {
std::cerr << "The definition is malformed, should be key=value.\n";
return 1;
}
absl::string_view key = definition.substr(0, pos);
absl::string_view val = definition.substr(pos + 1);
parser.addExternalDefinition(key, val);
}
}
parser.parseFile(sfzFilePath);
if (parser.getErrorCount() > 0)
return 1;
return 0;
}