Add proper support of external #define
This commit is contained in:
parent
3871d9c9b2
commit
6ee9dd106e
3 changed files with 58 additions and 10 deletions
|
|
@ -18,20 +18,26 @@ Parser::~Parser()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::addDefinition(absl::string_view id, absl::string_view value)
|
|
||||||
{
|
|
||||||
_definitions[id] = std::string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::reset()
|
void Parser::reset()
|
||||||
{
|
{
|
||||||
_pathsIncluded.clear();
|
_pathsIncluded.clear();
|
||||||
|
_currentDefinitions = _externalDefinitions;
|
||||||
_currentHeader.reset();
|
_currentHeader.reset();
|
||||||
_currentOpcodes.clear();
|
_currentOpcodes.clear();
|
||||||
_errorCount = 0;
|
_errorCount = 0;
|
||||||
_warningCount = 0;
|
_warningCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Parser::addExternalDefinition(absl::string_view id, absl::string_view value)
|
||||||
|
{
|
||||||
|
_externalDefinitions[id] = std::string(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::clearExternalDefinitions()
|
||||||
|
{
|
||||||
|
_externalDefinitions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void Parser::parseFile(const fs::path& path)
|
void Parser::parseFile(const fs::path& path)
|
||||||
{
|
{
|
||||||
parseVirtualFile(path, nullptr);
|
parseVirtualFile(path, nullptr);
|
||||||
|
|
@ -97,6 +103,11 @@ void Parser::includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader
|
||||||
_included.push_back(std::move(reader));
|
_included.push_back(std::move(reader));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Parser::addDefinition(absl::string_view id, absl::string_view value)
|
||||||
|
{
|
||||||
|
_currentDefinitions[id] = std::string(value);
|
||||||
|
}
|
||||||
|
|
||||||
void Parser::processTopLevel()
|
void Parser::processTopLevel()
|
||||||
{
|
{
|
||||||
while (!_included.empty()) {
|
while (!_included.empty()) {
|
||||||
|
|
@ -404,8 +415,8 @@ std::string Parser::expandDollarVars(const SourceRange& range, absl::string_view
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = _definitions.find(name);
|
auto it = _currentDefinitions.find(name);
|
||||||
if (it == _definitions.end()) {
|
if (it == _currentDefinitions.end()) {
|
||||||
emitWarning(range, "The variable `" + name + "` is not defined.");
|
emitWarning(range, "The variable `" + name + "` is not defined.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,9 @@ public:
|
||||||
Parser();
|
Parser();
|
||||||
~Parser();
|
~Parser();
|
||||||
|
|
||||||
void addDefinition(absl::string_view id, absl::string_view value);
|
void addExternalDefinition(absl::string_view id, absl::string_view value);
|
||||||
|
void clearExternalDefinitions();
|
||||||
|
|
||||||
void parseFile(const fs::path& path);
|
void parseFile(const fs::path& path);
|
||||||
void parseString(const fs::path& path, absl::string_view sfzView);
|
void parseString(const fs::path& path, absl::string_view sfzView);
|
||||||
void parseVirtualFile(const fs::path& path, std::unique_ptr<Reader> reader);
|
void parseVirtualFile(const fs::path& path, std::unique_ptr<Reader> reader);
|
||||||
|
|
@ -41,7 +43,7 @@ public:
|
||||||
typedef absl::flat_hash_map<std::string, std::string> DefinitionSet;
|
typedef absl::flat_hash_map<std::string, std::string> DefinitionSet;
|
||||||
|
|
||||||
const IncludeFileSet& getIncludedFiles() const noexcept { return _pathsIncluded; }
|
const IncludeFileSet& getIncludedFiles() const noexcept { return _pathsIncluded; }
|
||||||
const DefinitionSet& getDefines() const noexcept { return _definitions; }
|
const DefinitionSet& getDefines() const noexcept { return _currentDefinitions; }
|
||||||
|
|
||||||
size_t getErrorCount() const noexcept { return _errorCount; }
|
size_t getErrorCount() const noexcept { return _errorCount; }
|
||||||
size_t getWarningCount() const noexcept { return _warningCount; }
|
size_t getWarningCount() const noexcept { return _warningCount; }
|
||||||
|
|
@ -64,6 +66,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader, const SourceRange& includeStmtRange);
|
void includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader, const SourceRange& includeStmtRange);
|
||||||
|
void addDefinition(absl::string_view id, absl::string_view value);
|
||||||
void processTopLevel();
|
void processTopLevel();
|
||||||
void processDirective();
|
void processDirective();
|
||||||
void processHeader();
|
void processHeader();
|
||||||
|
|
@ -96,7 +99,7 @@ private:
|
||||||
Listener* _listener = nullptr;
|
Listener* _listener = nullptr;
|
||||||
|
|
||||||
fs::path _originalDirectory { fs::current_path() };
|
fs::path _originalDirectory { fs::current_path() };
|
||||||
DefinitionSet _definitions;
|
DefinitionSet _externalDefinitions;
|
||||||
|
|
||||||
// a current list of files included, last one at the back
|
// a current list of files included, last one at the back
|
||||||
std::vector<std::unique_ptr<Reader>> _included;
|
std::vector<std::unique_ptr<Reader>> _included;
|
||||||
|
|
@ -105,6 +108,7 @@ private:
|
||||||
size_t _maxIncludeDepth = 32;
|
size_t _maxIncludeDepth = 32;
|
||||||
bool _recursiveIncludeGuardEnabled = false;
|
bool _recursiveIncludeGuardEnabled = false;
|
||||||
IncludeFileSet _pathsIncluded;
|
IncludeFileSet _pathsIncluded;
|
||||||
|
DefinitionSet _currentDefinitions;
|
||||||
|
|
||||||
// parsing state
|
// parsing state
|
||||||
absl::optional<std::string> _currentHeader;
|
absl::optional<std::string> _currentHeader;
|
||||||
|
|
|
||||||
|
|
@ -415,3 +415,36 @@ TEST_CASE("[Parsing] Headers (new parser)")
|
||||||
REQUIRE(mock.fullBlockMembers == expectedMembers);
|
REQUIRE(mock.fullBlockMembers == expectedMembers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("[Parsing] External definitions")
|
||||||
|
{
|
||||||
|
sfz::Parser parser;
|
||||||
|
ParsingMocker mock;
|
||||||
|
parser.setListener(&mock);
|
||||||
|
parser.addExternalDefinition("foo", "abc");
|
||||||
|
parser.addExternalDefinition("bar", "123");
|
||||||
|
parser.parseString("/externalDefinitions.sfz",
|
||||||
|
R"(<header>
|
||||||
|
param1=$foo
|
||||||
|
param2=$bar)");
|
||||||
|
std::vector<std::vector<sfz::Opcode>> expectedMembers = {
|
||||||
|
{{"param1", "abc"}, {"param2", "123"}}
|
||||||
|
};
|
||||||
|
std::vector<std::string> expectedHeaders = {
|
||||||
|
"header"
|
||||||
|
};
|
||||||
|
std::vector<sfz::Opcode> expectedOpcodes;
|
||||||
|
|
||||||
|
for (auto& members: expectedMembers)
|
||||||
|
for (auto& opcode: members)
|
||||||
|
expectedOpcodes.push_back(opcode);
|
||||||
|
|
||||||
|
REQUIRE(mock.beginnings == 1);
|
||||||
|
REQUIRE(mock.endings == 1);
|
||||||
|
REQUIRE(mock.errors.empty());
|
||||||
|
REQUIRE(mock.warnings.empty());
|
||||||
|
REQUIRE(mock.opcodes == expectedOpcodes);
|
||||||
|
REQUIRE(mock.headers == expectedHeaders);
|
||||||
|
REQUIRE(mock.fullBlockHeaders == expectedHeaders);
|
||||||
|
REQUIRE(mock.fullBlockMembers == expectedMembers);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue