Add proper support of external #define

This commit is contained in:
Jean Pierre Cimalando 2020-03-28 02:44:06 +01:00
parent 3871d9c9b2
commit 6ee9dd106e
3 changed files with 58 additions and 10 deletions

View file

@ -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()
{
_pathsIncluded.clear();
_currentDefinitions = _externalDefinitions;
_currentHeader.reset();
_currentOpcodes.clear();
_errorCount = 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)
{
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));
}
void Parser::addDefinition(absl::string_view id, absl::string_view value)
{
_currentDefinitions[id] = std::string(value);
}
void Parser::processTopLevel()
{
while (!_included.empty()) {
@ -404,8 +415,8 @@ std::string Parser::expandDollarVars(const SourceRange& range, absl::string_view
continue;
}
auto it = _definitions.find(name);
if (it == _definitions.end()) {
auto it = _currentDefinitions.find(name);
if (it == _currentDefinitions.end()) {
emitWarning(range, "The variable `" + name + "` is not defined.");
continue;
}

View file

@ -27,7 +27,9 @@ public:
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 parseString(const fs::path& path, absl::string_view sfzView);
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;
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 getWarningCount() const noexcept { return _warningCount; }
@ -64,6 +66,7 @@ public:
private:
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 processDirective();
void processHeader();
@ -96,7 +99,7 @@ private:
Listener* _listener = nullptr;
fs::path _originalDirectory { fs::current_path() };
DefinitionSet _definitions;
DefinitionSet _externalDefinitions;
// a current list of files included, last one at the back
std::vector<std::unique_ptr<Reader>> _included;
@ -105,6 +108,7 @@ private:
size_t _maxIncludeDepth = 32;
bool _recursiveIncludeGuardEnabled = false;
IncludeFileSet _pathsIncluded;
DefinitionSet _currentDefinitions;
// parsing state
absl::optional<std::string> _currentHeader;

View file

@ -415,3 +415,36 @@ TEST_CASE("[Parsing] Headers (new parser)")
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);
}