summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/parser/ParserScope.cpp21
-rw-r--r--src/core/parser/ParserScope.hpp4
-rw-r--r--test/formats/osml/OsmlParserTest.cpp14
-rw-r--r--testdata/osmlparser/inline_domain.osml14
4 files changed, 49 insertions, 4 deletions
diff --git a/src/core/parser/ParserScope.cpp b/src/core/parser/ParserScope.cpp
index ce3dc94..b0a4945 100644
--- a/src/core/parser/ParserScope.cpp
+++ b/src/core/parser/ParserScope.cpp
@@ -21,6 +21,7 @@
#include <core/common/VariantWriter.hpp>
#include <core/model/Domain.hpp>
#include <core/model/Typesystem.hpp>
+#include <core/model/RootNode.hpp>
#include "ParserScope.hpp"
@@ -233,6 +234,13 @@ void ParserScope::pop()
}
flags.resize(newLen);
+ // Whenever a RootNode is popped from the stack, we have to perform deferred
+ // resolution -- however, postpone issuing error messages
+ if (nodes.back()->isa(&RttiTypes::RootNode)) {
+ Logger logger;
+ performDeferredResolution(logger, true);
+ }
+
// Remove the element from the stack
nodes.pop_back();
}
@@ -424,7 +432,7 @@ bool ParserScope::resolveTypeWithValue(const std::string &name,
resultCallback);
}
-bool ParserScope::performDeferredResolution(Logger &logger)
+bool ParserScope::performDeferredResolution(Logger &logger, bool postpone)
{
// Repeat the resolution process as long as something has changed in the
// last iteration (resolving a node may cause other nodes to be resolvable).
@@ -446,8 +454,9 @@ bool ParserScope::performDeferredResolution(Logger &logger)
// Abort if nothing has changed in the last iteration
if (!hasChange) {
// In a last step, clear the "awaitingResolution" list to allow
- // cyclical dependencies to be resolved
- if (!awaitingResolution.empty()) {
+ // cyclical dependencies to be resolved -- if the postpone flag
+ // is set, do not do this
+ if (!awaitingResolution.empty() && !postpone) {
awaitingResolution.clear();
} else {
break;
@@ -460,6 +469,12 @@ bool ParserScope::performDeferredResolution(Logger &logger)
return true;
}
+ // If the postpone flag is set to true, we'll abort here -- this function
+ // will be called again later
+ if (postpone) {
+ return false;
+ }
+
// Output error messages for all elements for which resolution did not
// succeed.
for (auto &failed : deferred) {
diff --git a/src/core/parser/ParserScope.hpp b/src/core/parser/ParserScope.hpp
index 185b845..24af6b8 100644
--- a/src/core/parser/ParserScope.hpp
+++ b/src/core/parser/ParserScope.hpp
@@ -797,8 +797,10 @@ public:
* pending deferred resolutions is cleared after this function has run.
*
* @param logger is the logger instance into which errors should be logged.
+ * @param postpone if set to true, postpones issuing any error messages and
+ * waits for node resolution.
*/
- bool performDeferredResolution(Logger &logger);
+ bool performDeferredResolution(Logger &logger, bool postpone = false);
};
}
diff --git a/test/formats/osml/OsmlParserTest.cpp b/test/formats/osml/OsmlParserTest.cpp
index 1ab55f2..295d9bf 100644
--- a/test/formats/osml/OsmlParserTest.cpp
+++ b/test/formats/osml/OsmlParserTest.cpp
@@ -91,5 +91,19 @@ TEST(OsmlParser, empty_typesystem)
ASSERT_TRUE(node->isa(&RttiTypes::Typesystem));
ASSERT_EQ("testTypesystem", node->getName());
}
+TEST(OsmlParser, inlineDomain)
+{
+ OsmlStandaloneEnvironment env(logger);
+ logger.reset();
+
+ ASSERT_FALSE(logger.hasError());
+ Rooted<Node> node =
+ env.parse("inline_domain.osml", "", "", RttiSet{&RttiTypes::Node});
+ ASSERT_FALSE(logger.hasError());
+
+ ASSERT_TRUE(node != nullptr);
+ ASSERT_TRUE(node->isa(&RttiTypes::Document));
+}
+
}
diff --git a/testdata/osmlparser/inline_domain.osml b/testdata/osmlparser/inline_domain.osml
new file mode 100644
index 0000000..1d71df4
--- /dev/null
+++ b/testdata/osmlparser/inline_domain.osml
@@ -0,0 +1,14 @@
+\begin{document}
+
+\domain#testDomain
+ \struct#test[isRoot=true]
+ \field
+ \childRef[ref=a]
+ \struct#a
+
+\begin{test}
+\a
+\end{test}
+
+\end{document}
+