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()
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue