summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/formats/osxml/OsxmlParser.cpp288
-rw-r--r--src/formats/osxml/OsxmlParser.hpp2
-rw-r--r--test/formats/osxml/OsxmlParserTest.cpp28
4 files changed, 91 insertions, 229 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2106cf0..ec1bb4d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -203,6 +203,7 @@ TARGET_LINK_LIBRARIES(ousia_osml
ADD_LIBRARY(ousia_osxml
src/formats/osxml/OsxmlAttributeLocator
src/formats/osxml/OsxmlEventParser
+ src/formats/osxml/OsxmlParser
)
TARGET_LINK_LIBRARIES(ousia_osxml
@@ -351,6 +352,7 @@ IF(TEST)
ADD_EXECUTABLE(ousia_test_osxml
test/formats/osxml/OsxmlEventParserTest
+ test/formats/osxml/OsxmlParserTest
)
TARGET_LINK_LIBRARIES(ousia_test_osxml
diff --git a/src/formats/osxml/OsxmlParser.cpp b/src/formats/osxml/OsxmlParser.cpp
index 869c76a..c216855 100644
--- a/src/formats/osxml/OsxmlParser.cpp
+++ b/src/formats/osxml/OsxmlParser.cpp
@@ -16,223 +16,83 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <iostream>
-#include <map>
-#include <sstream>
-#include <vector>
-
-#include <expat.h>
-
-#include <core/common/CharReader.hpp>
-#include <core/common/Utils.hpp>
-#include <core/common/VariantReader.hpp>
-#include <core/parser/ParserScope.hpp>
-#include <core/parser/ParserStack.hpp>
-#include <core/parser/stack/DocumentHandler.hpp>
-#include <core/parser/stack/DomainHandler.hpp>
-#include <core/parser/stack/ImportIncludeHandler.hpp>
-#include <core/parser/stack/TypesystemHandler.hpp>
-#include <core/model/Document.hpp>
-#include <core/model/Domain.hpp>
-#include <core/model/Typesystem.hpp>
-
-#include "XmlParser.hpp"
+#include <core/parser/stack/GenericParserStates.hpp>
+#include <core/parser/stack/Stack.hpp>
+#include <core/parser/ParserContext.hpp>
+
+#include "OsxmlEventParser.hpp"
+#include "OsxmlParser.hpp"
namespace ousia {
-namespace ParserStates {
-/* Document states */
-static const ParserState Document =
- ParserStateBuilder()
- .parent(&None)
- .createdNodeType(&RttiTypes::Document)
- .elementHandler(DocumentHandler::create)
- .arguments({Argument::String("name", "")});
-
-static const ParserState DocumentChild =
- ParserStateBuilder()
- .parents({&Document, &DocumentChild})
- .createdNodeTypes({&RttiTypes::StructureNode,
- &RttiTypes::AnnotationEntity,
- &RttiTypes::DocumentField})
- .elementHandler(DocumentChildHandler::create);
-
-/* Domain states */
-static const ParserState Domain = ParserStateBuilder()
- .parents({&None, &Document})
- .createdNodeType(&RttiTypes::Domain)
- .elementHandler(DomainHandler::create)
- .arguments({Argument::String("name")});
-
-static const ParserState DomainStruct =
- ParserStateBuilder()
- .parent(&Domain)
- .createdNodeType(&RttiTypes::StructuredClass)
- .elementHandler(DomainStructHandler::create)
- .arguments({Argument::String("name"),
- Argument::Cardinality("cardinality", Cardinality::any()),
- Argument::Bool("isRoot", false),
- Argument::Bool("transparent", false),
- Argument::String("isa", "")});
-
-static const ParserState DomainAnnotation =
- ParserStateBuilder()
- .parent(&Domain)
- .createdNodeType(&RttiTypes::AnnotationClass)
- .elementHandler(DomainAnnotationHandler::create)
- .arguments({Argument::String("name")});
-
-static const ParserState DomainAttributes =
- ParserStateBuilder()
- .parents({&DomainStruct, &DomainAnnotation})
- .createdNodeType(&RttiTypes::StructType)
- .elementHandler(DomainAttributesHandler::create)
- .arguments({});
-
-static const ParserState DomainAttribute =
- ParserStateBuilder()
- .parent(&DomainAttributes)
- .elementHandler(TypesystemStructFieldHandler::create)
- .arguments({Argument::String("name"), Argument::String("type"),
- Argument::Any("default", Variant::fromObject(nullptr))});
-
-static const ParserState DomainField =
- ParserStateBuilder()
- .parents({&DomainStruct, &DomainAnnotation})
- .createdNodeType(&RttiTypes::FieldDescriptor)
- .elementHandler(DomainFieldHandler::create)
- .arguments({Argument::String("name", ""),
- Argument::Bool("isSubtree", false),
- Argument::Bool("optional", false)});
-
-static const ParserState DomainFieldRef =
- ParserStateBuilder()
- .parents({&DomainStruct, &DomainAnnotation})
- .createdNodeType(&RttiTypes::FieldDescriptor)
- .elementHandler(DomainFieldRefHandler::create)
- .arguments({Argument::String("ref", DEFAULT_FIELD_NAME)});
-
-static const ParserState DomainStructPrimitive =
- ParserStateBuilder()
- .parents({&DomainStruct, &DomainAnnotation})
- .createdNodeType(&RttiTypes::FieldDescriptor)
- .elementHandler(DomainPrimitiveHandler::create)
- .arguments(
- {Argument::String("name", ""), Argument::Bool("isSubtree", false),
- Argument::Bool("optional", false), Argument::String("type")});
-
-static const ParserState DomainStructChild =
- ParserStateBuilder()
- .parent(&DomainField)
- .elementHandler(DomainChildHandler::create)
- .arguments({Argument::String("ref")});
-
-static const ParserState DomainStructParent =
- ParserStateBuilder()
- .parent(&DomainStruct)
- .createdNodeType(&RttiTypes::DomainParent)
- .elementHandler(DomainParentHandler::create)
- .arguments({Argument::String("ref")});
-
-static const ParserState DomainStructParentField =
- ParserStateBuilder()
- .parent(&DomainStructParent)
- .createdNodeType(&RttiTypes::FieldDescriptor)
- .elementHandler(DomainParentFieldHandler::create)
- .arguments({Argument::String("name", ""),
- Argument::Bool("isSubtree", false),
- Argument::Bool("optional", false)});
-
-static const ParserState DomainStructParentFieldRef =
- ParserStateBuilder()
- .parent(&DomainStructParent)
- .createdNodeType(&RttiTypes::FieldDescriptor)
- .elementHandler(DomainParentFieldRefHandler::create)
- .arguments({Argument::String("ref", DEFAULT_FIELD_NAME)});
-
-/* Typesystem states */
-static const ParserState Typesystem =
- ParserStateBuilder()
- .parents({&None, &Domain})
- .createdNodeType(&RttiTypes::Typesystem)
- .elementHandler(TypesystemHandler::create)
- .arguments({Argument::String("name", "")});
-
-static const ParserState TypesystemEnum =
- ParserStateBuilder()
- .parent(&Typesystem)
- .createdNodeType(&RttiTypes::EnumType)
- .elementHandler(TypesystemEnumHandler::create)
- .arguments({Argument::String("name")});
-
-static const ParserState TypesystemEnumEntry =
- ParserStateBuilder()
- .parent(&TypesystemEnum)
- .elementHandler(TypesystemEnumEntryHandler::create)
- .arguments({});
-
-static const ParserState TypesystemStruct =
- ParserStateBuilder()
- .parent(&Typesystem)
- .createdNodeType(&RttiTypes::StructType)
- .elementHandler(TypesystemStructHandler::create)
- .arguments({Argument::String("name"), Argument::String("parent", "")});
-
-static const ParserState TypesystemStructField =
- ParserStateBuilder()
- .parent(&TypesystemStruct)
- .elementHandler(TypesystemStructFieldHandler::create)
- .arguments({Argument::String("name"), Argument::String("type"),
- Argument::Any("default", Variant::fromObject(nullptr))});
-
-static const ParserState TypesystemConstant =
- ParserStateBuilder()
- .parent(&Typesystem)
- .createdNodeType(&RttiTypes::Constant)
- .elementHandler(TypesystemConstantHandler::create)
- .arguments({Argument::String("name"), Argument::String("type"),
- Argument::Any("value")});
-
-/* Special states for import and include */
-static const ParserState Import =
- ParserStateBuilder()
- .parents({&Document, &Typesystem, &Domain})
- .elementHandler(ImportHandler::create)
- .arguments({Argument::String("rel", ""), Argument::String("type", ""),
- Argument::String("src", "")});
-
-static const ParserState Include =
- ParserStateBuilder()
- .parent(&All)
- .elementHandler(IncludeHandler::create)
- .arguments({Argument::String("rel", ""), Argument::String("type", ""),
- Argument::String("src", "")});
-
-static const std::multimap<std::string, const ParserState *> XmlStates{
- {"document", &Document},
- {"*", &DocumentChild},
- {"domain", &Domain},
- {"struct", &DomainStruct},
- {"annotation", &DomainAnnotation},
- {"attributes", &DomainAttributes},
- {"attribute", &DomainAttribute},
- {"field", &DomainField},
- {"fieldRef", &DomainFieldRef},
- {"primitive", &DomainStructPrimitive},
- {"childRef", &DomainStructChild},
- {"parentRef", &DomainStructParent},
- {"field", &DomainStructParentField},
- {"fieldRef", &DomainStructParentFieldRef},
- {"typesystem", &Typesystem},
- {"enum", &TypesystemEnum},
- {"entry", &TypesystemEnumEntry},
- {"struct", &TypesystemStruct},
- {"field", &TypesystemStructField},
- {"constant", &TypesystemConstant},
- {"import", &Import},
- {"include", &Include}};
+using namespace parser_stack;
+
+/**
+ * Class containing the actual OsxmlParser implementation.
+ */
+class OsxmlParserImplementation : public OsxmlEvents {
+private:
+ /**
+ * Actual xml parser -- converts the xml stream into a set of events.
+ */
+ OsxmlEventParser parser;
+
+ /**
+ * Pushdown automaton responsible for converting the xml events into an
+ * actual Node tree.
+ */
+ Stack stack;
+
+public:
+ /**
+ * Constructor of the OsxmlParserImplementation class.
+ *
+ * @param reader is a reference to the CharReader instance from which the
+ * XML should be read.
+ * @param ctx is a reference to the ParserContext instance that should be
+ * used.
+ */
+ OsxmlParserImplementation(CharReader &reader, ParserContext &ctx)
+ : parser(reader, *this, ctx.getLogger()),
+ stack(ctx, GenericParserStates)
+ {
+ }
+
+ /**
+ * Starts the actual parsing process.
+ */
+ void parse() { parser.parse(); }
+
+ void command(const Variant &name, const Variant::mapType &args) override
+ {
+ stack.command(name, args);
+ stack.fieldStart(true);
+ }
+
+ void annotationStart(const Variant &name,
+ const Variant::mapType &args) override
+ {
+ stack.annotationStart(name, args);
+ stack.fieldStart(true);
+ }
+
+ void annotationEnd(const Variant &className,
+ const Variant &elementName) override
+ {
+ stack.annotationEnd(className, elementName);
+ }
+
+ void fieldEnd() override { stack.fieldEnd(); }
+
+ void data(const Variant &data) override { stack.data(data); }
+};
+
+/* Class OsxmlParser */
+
+void OsxmlParser::doParse(CharReader &reader, ParserContext &ctx)
+{
+ OsxmlParserImplementation impl(reader, ctx);
+ impl.parse();
}
-
-
}
diff --git a/src/formats/osxml/OsxmlParser.hpp b/src/formats/osxml/OsxmlParser.hpp
index 281a49c..0fbf83c 100644
--- a/src/formats/osxml/OsxmlParser.hpp
+++ b/src/formats/osxml/OsxmlParser.hpp
@@ -17,7 +17,7 @@
*/
/**
- * @file XmlParser.hpp
+ * @file OsxmlParser.hpp
*
* Contains the parser responsible for reading Ousía XML Documents (extension
* oxd) and Ousía XML Modules (extension oxm).
diff --git a/test/formats/osxml/OsxmlParserTest.cpp b/test/formats/osxml/OsxmlParserTest.cpp
index 269a3f6..a2bd8b1 100644
--- a/test/formats/osxml/OsxmlParserTest.cpp
+++ b/test/formats/osxml/OsxmlParserTest.cpp
@@ -30,7 +30,7 @@
#include <core/StandaloneEnvironment.hpp>
#include <plugins/filesystem/FileLocator.hpp>
-#include <formats/osdmx/OsdmxParser.hpp>
+#include <formats/osxml/OsxmlParser.hpp>
namespace ousia {
@@ -41,7 +41,7 @@ extern const Rtti Typesystem;
}
struct XmlStandaloneEnvironment : public StandaloneEnvironment {
- XmlParser xmlParser;
+ OsxmlParser parser;
FileLocator fileLocator;
XmlStandaloneEnvironment(ConcreteLogger &logger)
@@ -52,21 +52,21 @@ struct XmlStandaloneEnvironment : public StandaloneEnvironment {
registry.registerDefaultExtensions();
registry.registerParser({"text/vnd.ousia.oxm", "text/vnd.ousia.oxd"},
- {&RttiTypes::Node}, &xmlParser);
+ {&RttiTypes::Node}, &parser);
registry.registerResourceLocator(&fileLocator);
}
};
static TerminalLogger logger(std::cerr, true);
-TEST(XmlParser, mismatchedTag)
+TEST(OsxmlParser, mismatchedTag)
{
XmlStandaloneEnvironment env(logger);
env.parse("mismatchedTag.oxm", "", "", RttiSet{&RttiTypes::Document});
ASSERT_TRUE(logger.hasError());
}
-TEST(XmlParser, generic)
+TEST(OsxmlParser, generic)
{
XmlStandaloneEnvironment env(logger);
env.parse("generic.oxm", "", "", RttiSet{&RttiTypes::Node});
@@ -186,7 +186,7 @@ static void checkFieldDescriptor(
Handle<Type> primitiveType = nullptr, bool optional = false)
{
auto res = desc->resolve(&RttiTypes::FieldDescriptor, name);
- ASSERT_EQ(1, res.size());
+ ASSERT_EQ(1U, res.size());
checkFieldDescriptor(res[0].node, name, parent, children, type,
primitiveType, optional);
}
@@ -201,7 +201,7 @@ static void checkFieldDescriptor(
optional);
}
-TEST(XmlParser, domainParsing)
+TEST(OsxmlParser, domainParsing)
{
XmlStandaloneEnvironment env(logger);
Rooted<Node> book_domain_node =
@@ -339,10 +339,10 @@ static void checkText(Handle<Node> p, Handle<Node> expectedParent,
{
checkStructuredEntity(p, expectedParent, doc, "paragraph");
Rooted<StructuredEntity> par = p.cast<StructuredEntity>();
- ASSERT_EQ(1, par->getField().size());
+ ASSERT_EQ(1U, par->getField().size());
checkStructuredEntity(par->getField()[0], par, doc, "text");
Rooted<StructuredEntity> text = par->getField()[0].cast<StructuredEntity>();
- ASSERT_EQ(1, text->getField().size());
+ ASSERT_EQ(1U, text->getField().size());
Handle<StructureNode> d = text->getField()[0];
ASSERT_FALSE(d == nullptr);
@@ -352,7 +352,7 @@ static void checkText(Handle<Node> p, Handle<Node> expectedParent,
ASSERT_EQ(expected, prim->getContent());
}
-TEST(XmlParser, documentParsing)
+TEST(OsxmlParser, documentParsing)
{
XmlStandaloneEnvironment env(logger);
Rooted<Node> book_document_node =
@@ -364,7 +364,7 @@ TEST(XmlParser, documentParsing)
checkStructuredEntity(doc->getRoot(), doc, doc, "book");
{
Rooted<StructuredEntity> book = doc->getRoot();
- ASSERT_EQ(2, book->getField().size());
+ ASSERT_EQ(2U, book->getField().size());
checkText(book->getField()[0], book, doc,
"This might be some introductory text or a dedication.");
checkStructuredEntity(book->getField()[1], book, doc, "chapter",
@@ -372,7 +372,7 @@ TEST(XmlParser, documentParsing)
{
Rooted<StructuredEntity> chapter =
book->getField()[1].cast<StructuredEntity>();
- ASSERT_EQ(3, chapter->getField().size());
+ ASSERT_EQ(3U, chapter->getField().size());
checkText(chapter->getField()[0], chapter, doc,
"Here we might have an introduction to the chapter.");
checkStructuredEntity(chapter->getField()[1], chapter, doc,
@@ -381,7 +381,7 @@ TEST(XmlParser, documentParsing)
{
Rooted<StructuredEntity> section =
chapter->getField()[1].cast<StructuredEntity>();
- ASSERT_EQ(1, section->getField().size());
+ ASSERT_EQ(1U, section->getField().size());
checkText(section->getField()[0], section, doc,
"Here we might find the actual section content.");
}
@@ -391,7 +391,7 @@ TEST(XmlParser, documentParsing)
{
Rooted<StructuredEntity> section =
chapter->getField()[2].cast<StructuredEntity>();
- ASSERT_EQ(1, section->getField().size());
+ ASSERT_EQ(1U, section->getField().size());
checkText(section->getField()[0], section, doc,
"Here we might find the actual section content.");
}