From f2f20d5cae37064a329ee451efb6f2f26e2a0f0b Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Wed, 8 Apr 2015 19:34:18 +0200 Subject: started to implement capabilities for ontology serialization. --- src/plugins/xml/XmlOutput.cpp | 445 +++++++++++++++++---- src/plugins/xml/XmlOutput.hpp | 31 +- .../integration/user_defined_syntax/poem.in.osml | 23 +- testdata/integration/user_defined_syntax/poem.osml | 22 + .../user_defined_syntax/token_escaping.in.osml | 15 +- .../user_defined_syntax/token_escaping.osml | 12 + .../user_defined_syntax/wikilike.in.osml | 40 +- .../integration/user_defined_syntax/wikilike.osml | 37 ++ 8 files changed, 443 insertions(+), 182 deletions(-) create mode 100644 testdata/integration/user_defined_syntax/poem.osml create mode 100644 testdata/integration/user_defined_syntax/token_escaping.osml create mode 100644 testdata/integration/user_defined_syntax/wikilike.osml diff --git a/src/plugins/xml/XmlOutput.cpp b/src/plugins/xml/XmlOutput.cpp index 166fbf7..adf1691 100644 --- a/src/plugins/xml/XmlOutput.cpp +++ b/src/plugins/xml/XmlOutput.cpp @@ -17,75 +17,176 @@ */ #include +#include #include "XmlOutput.hpp" #include #include -// TODO: REMOVE -#include - namespace ousia { namespace xml { +/** + * Wrapper structure for transformation parameters. + */ +struct TransformParams { + Manager &mgr; + Logger &logger; + bool pretty; + bool flat; + SourceId documentId; + // this stores all already serialized dependent typesystems and ontologies. + std::unordered_set serialized; + + TransformParams(Manager &mgr, Logger &logger, bool pretty, bool flat, + SourceId documentId) + : mgr(mgr), + logger(logger), + pretty(pretty), + flat(flat), + documentId(documentId) + { + } +}; + +/* + * These are method declarations to allow for cross-references of methods. + */ + +/* + * Ontology transformation. + */ + +static Rooted transformOntology(Handle parent, + Handle o, + TransformParams &P); + +/* + * Typesystem transformation. + */ +static Rooted transformTypesystem(Handle parent, + Handle t, + TransformParams &P); + +/* + * Attribute transformation. + */ +static std::map transformAttributes( + const std::string &name, DocumentEntity *entity, TransformParams &P); + +static void addNameAttribute(Handle n, + std::map &attrs); + +/* + * DocumentEntity transformation. + */ +static void transformChildren(DocumentEntity *parentEntity, + Handle parent, TransformParams &P); + +static Rooted transformStructuredEntity(Handle parent, + Handle s, + TransformParams &P); + +/* + * Annotations. + */ +static Rooted transformAnchor(Handle parent, Handle a, + TransformParams &P); + +/* + * DocumentPrimitives. + */ + +static std::string toString(Variant v, TransformParams &P); + +static Rooted transformPrimitive(Handle parent, + Handle type, + Handle p, + TransformParams &P); + +/* + * The actual transformation implementation starts here. + */ + static Rooted createImportElement(Handle parent, Handle referenced, ResourceManager &resourceManager, - const std::string &rel) + const std::string &rel, + TransformParams &P) { SourceLocation loc = referenced->getLocation(); + // check if the source location is the same as for the whole document. + // in that case we do not want to make an import statement. + if (P.documentId == loc.getSourceId()) { + return nullptr; + } + // if that is not the case, we try to find the respective resource. Resource res = resourceManager.getResource(loc.getSourceId()); if (!res.isValid()) { return nullptr; } - Rooted import{ - new Element{parent->getManager(), - parent, - "import", - {{"rel", rel}, {"src", res.getLocation()}}}}; + // if we found it we create an import element. + Rooted import{new Element{ + P.mgr, parent, "import", {{"rel", rel}, {"src", res.getLocation()}}}}; return import; } void XmlTransformer::writeXml(Handle doc, std::ostream &out, Logger &logger, ResourceManager &resourceManager, - bool pretty) + bool pretty, bool flat) { Manager &mgr = doc->getManager(); // the outermost tag is the document itself. Rooted document{new Element{mgr, {nullptr}, "document"}}; + // create parameter wrapper object + TransformParams P{mgr, logger, pretty, flat, + doc->getLocation().getSourceId()}; // write imports for all referenced ontologies. - for (auto d : doc->getOntologies()) { - Rooted import = - createImportElement(document, d, resourceManager, "ontology"); - if (import != nullptr) { - document->addChild(import); - // add the import as namespace information to the document node as - // well. - document->getAttributes().emplace( - std::string("xmlns:") + d->getName(), d->getName()); - } else { - logger.warning(std::string( - "The location of ontology \"" + d->getName() + - "\" could not be retrieved using the given ResourceManager.")); + for (auto o : doc->getOntologies()) { + if (!flat) { + Rooted import = createImportElement( + document, o, resourceManager, "ontology", P); + if (import != nullptr) { + document->addChild(import); + // add the import as namespace information to the document node + // as well. + document->getAttributes().emplace( + std::string("xmlns:") + o->getName(), o->getName()); + continue; + } else { + logger.warning(std::string( + "The location of ontology \"" + o->getName() + + "\" could not be retrieved using the given ResourceManager." + " The ontology is now serialized inline.")); + } } + Rooted ontology = transformOntology(document, o, P); + document->addChild(ontology); } // write imports for all referenced typesystems. for (auto t : doc->getTypesystems()) { - Rooted import = - createImportElement(document, t, resourceManager, "typesystem"); - if (import != nullptr) { - document->addChild(import); - } else { - logger.warning(std::string( - "The location of typesystem \"" + t->getName() + - "\" could not be retrieved using the given ResourceManager.")); + if (!flat) { + Rooted import = createImportElement( + document, t, resourceManager, "typesystem", P); + if (import != nullptr) { + document->addChild(import); + continue; + } else { + logger.warning( + std::string("The location of typesystem \"" + t->getName() + + "\" could not be retrieved using the given " + "ResourceManager. " + " The typesystem is now serialized inline.")); + } } + Rooted typesystem = transformTypesystem(document, t, P); + document->addChild(typesystem); } // transform the root element (and, using recursion, everything below it) Rooted root = - transformStructuredEntity(document, doc->getRoot(), logger, pretty); + transformStructuredEntity(document, doc->getRoot(), P); document->addChild(root); // then serialize. document->serialize( @@ -93,23 +194,196 @@ void XmlTransformer::writeXml(Handle doc, std::ostream &out, pretty); } -static std::string toString(Variant v, bool pretty) +/* + * Ontology transformation functions. + */ + +static std::string getStructuredClassRef(Handle referencing, + Handle referenced) { - if (v.isString()) { - return v.asString(); + std::string res; + if (referencing->getParent() == referenced->getParent()) { + res = referenced->getName(); } else { - return VariantWriter::writeOusiaToString(v, pretty); + res = referenced->getParent().cast()->getName() + "." + + referenced->getName(); + } + return res; +} + +static Rooted transformSyntaxDescriptor(Handle parent, + SyntaxDescriptor &stx, + TransformParams &P) +{ + Rooted syntax{new Element(P.mgr, parent, "syntax")}; + if (stx.open != Tokens::Empty) { + Rooted open{new Element(P.mgr, syntax, "open")}; + syntax->addChild(open); + // TODO: Transform token. + } + if (stx.close != Tokens::Empty) { + Rooted close{new Element(P.mgr, syntax, "close")}; + syntax->addChild(close); + // TODO: Transform token. + } + if (stx.shortForm != Tokens::Empty) { + Rooted shortForm{new Element(P.mgr, syntax, "short")}; + syntax->addChild(shortForm); + // TODO: Transform token. + } + return syntax; +} + +static Rooted transformFieldDescriptor(Handle parent, + Handle fd, + TransformParams &P) +{ + // find the correct tag name. + std::string tagName; + if (fd->isPrimitive()) { + tagName = "primitive"; + } else { + tagName = "field"; + } + // transform the attributes. + std::map attrs; + addNameAttribute(fd, attrs); + bool isSubtree = fd->getFieldType() == FieldDescriptor::FieldType::SUBTREE; + attrs.emplace("subtree", toString(isSubtree, P)); + attrs.emplace("optional", toString(fd->isOptional(), P)); + // TODO: whitespace mode? + // create the XML element itself. + Rooted fieldDescriptor{new Element(P.mgr, parent, tagName)}; + // translate the syntax. + SyntaxDescriptor stx = fd->getSyntaxDescriptor(); + Rooted syntax = transformSyntaxDescriptor(fieldDescriptor, stx, P); + fieldDescriptor->addChild(syntax); + // translate the child references. + for (auto s : fd->getChildren()) { + std::string ref = getStructuredClassRef( + fd->getParent().cast(), s); + Rooted childRef{ + new Element(P.mgr, fieldDescriptor, "childRef", {{"ref", ref}})}; + fieldDescriptor->addChild(childRef); + } + return fieldDescriptor; +} + +static void transformDescriptor(Handle elem, Handle d, + TransformParams &P) +{ + // add name. + addNameAttribute(d, elem->getAttributes()); + // TODO: transform the attributes descriptor. + // transform the syntactic sugar descriptors + { + SyntaxDescriptor stx = d->getSyntaxDescriptor(); + Rooted syntax = transformSyntaxDescriptor(elem, stx, P); + elem->addChild(syntax); + } + // transform all field descriptors. + for (auto fd : d->getFieldDescriptors()) { + Rooted fieldDescriptor = transformFieldDescriptor(elem, fd, P); + elem->addChild(fieldDescriptor); } } -std::map XmlTransformer::transformAttributes( - const std::string &name, DocumentEntity *entity, Logger &logger, - bool pretty) +static Rooted transformStructuredClass(Handle parent, + Handle s, + TransformParams &P) +{ + Rooted structuredClass{new Element(P.mgr, parent, "struct")}; + structuredClass->getAttributes().emplace("cardinality", + toString(s->getCardinality(), P)); + if (s->getSuperclass() != nullptr) { + structuredClass->getAttributes().emplace( + "isa", getStructuredClassRef(s, s->getSuperclass())); + } + structuredClass->getAttributes().emplace("transparent", + toString(s->isTransparent(), P)); + structuredClass->getAttributes().emplace("root", toString(s->isRoot(), P)); + transformDescriptor(structuredClass, s, P); + return structuredClass; +} + +static Rooted transformAnnotationClass(Handle parent, + Handle a, + TransformParams &P) +{ + Rooted annotationClass{new Element(P.mgr, parent, "struct")}; + transformDescriptor(annotationClass, a, P); + return annotationClass; +} + +Rooted transformOntology(Handle parent, Handle o, + TransformParams &P) +{ + // only transform this ontology if it was not transformed already. + if (o->getLocation().getSourceId() != P.documentId) { + // also: store that we have serialized this ontology. + if (!P.serialized.insert(o->getLocation().getSourceId()).second) { + return nullptr; + } + } + + if (P.flat) { + // transform all referenced ontologies if we want a standalone version. + for (auto o2 : o->getOntologies()) { + Rooted refOnto = transformOntology(parent, o2, P); + if (refOnto != nullptr) { + parent->addChild(refOnto); + } + } + + // transform all referenced typesystems if we want a standalone version. + for (auto t : o->getTypesystems()) { + Rooted refTypes = transformTypesystem(parent, t, P); + if (refTypes != nullptr) { + parent->addChild(refTypes); + } + } + } + + // transform the ontology itself. + // create an XML element for the ontology. + Rooted ontology{new Element(P.mgr, parent, "ontology")}; + // transform all StructuredClasses. + for (auto s : o->getStructureClasses()) { + Rooted structuredClass = + transformStructuredClass(ontology, s, P); + parent->addChild(structuredClass); + } + // transform all AnnotationClasses. + for (auto a : o->getAnnotationClasses()) { + Rooted annotationClass = + transformAnnotationClass(ontology, a, P); + } + // return the transformed Ontology. + return ontology; +} + +/* + * Typesystem transformation functions. + */ +Rooted transformTypesystem(Handle parent, + Handle t, TransformParams &P) +{ + // TODO: implement. + return nullptr; +} + +/* + * Attributes transform functions. + */ + +std::map transformAttributes(const std::string &name, + DocumentEntity *entity, + TransformParams &P) { // copy the attributes. Variant attrs = entity->getAttributes(); // build them. - entity->getDescriptor()->getAttributesDescriptor()->build(attrs, logger); + entity->getDescriptor()->getAttributesDescriptor()->build(attrs, P.logger); // get the array representation. Variant::arrayType attrArr = attrs.asArray(); // transform them to string key-value pairs. @@ -124,13 +398,13 @@ std::map XmlTransformer::transformAttributes( // Write other user defined properties for (size_t a = 0; a < as.size(); a++) { - xmlAttrs.emplace(as[a]->getName(), toString(attrArr[a], pretty)); + xmlAttrs.emplace(as[a]->getName(), toString(attrArr[a], P)); } return xmlAttrs; } -void XmlTransformer::addNameAttribute(Handle n, - std::map &attrs) +void addNameAttribute(Handle n, + std::map &attrs) { // copy the name attribute. if (!n->getName().empty()) { @@ -138,11 +412,14 @@ void XmlTransformer::addNameAttribute(Handle n, } } -void XmlTransformer::transformChildren(DocumentEntity *parentEntity, - Handle parent, Logger &logger, - bool pretty) +/* + * StructureNode transform functions. + */ + +void transformChildren(DocumentEntity *parentEntity, Handle parent, + + TransformParams &P) { - Manager &mgr = parent->getManager(); NodeVector fieldDescs = parentEntity->getDescriptor()->getFieldDescriptors(); @@ -152,8 +429,8 @@ void XmlTransformer::transformChildren(DocumentEntity *parentEntity, // if this is not the default field create an intermediate node for it. Rooted par = parent; if (fieldDesc->getFieldType() != FieldDescriptor::FieldType::TREE) { - par = - Rooted{new Element(mgr, parent, fieldDesc->getName())}; + par = Rooted{ + new Element(P.mgr, parent, fieldDesc->getName())}; parent->addChild(par); } if (!fieldDesc->isPrimitive()) { @@ -162,11 +439,10 @@ void XmlTransformer::transformChildren(DocumentEntity *parentEntity, Rooted child; if (c->isa(&RttiTypes::StructuredEntity)) { child = transformStructuredEntity( - par, c.cast(), logger, pretty); + par, c.cast(), P); } else { assert(c->isa(&RttiTypes::Anchor)); - child = - transformAnchor(par, c.cast(), logger, pretty); + child = transformAnchor(par, c.cast(), P); } if (child != nullptr) { par->addChild(child); @@ -182,8 +458,8 @@ void XmlTransformer::transformChildren(DocumentEntity *parentEntity, assert(field[0]->isa(&RttiTypes::DocumentPrimitive)); Rooted prim = field[0].cast(); // transform the primitive content. - Rooted text = transformPrimitive( - par, fieldDesc->getPrimitiveType(), prim, logger, pretty); + Rooted text = + transformPrimitive(par, fieldDesc->getPrimitiveType(), prim, P); if (text != nullptr) { par->addChild(text); } @@ -191,42 +467,35 @@ void XmlTransformer::transformChildren(DocumentEntity *parentEntity, } } -Rooted XmlTransformer::transformStructuredEntity( - Handle parent, Handle s, Logger &logger, - bool pretty) +Rooted transformStructuredEntity(Handle parent, + Handle s, + TransformParams &P) { - Manager &mgr = parent->getManager(); - // transform the attributes. - auto attrs = transformAttributes(s->getName(), s.get(), logger, pretty); - addNameAttribute(s, attrs); // create the XML element itself. Rooted elem{new Element{ - mgr, parent, s->getDescriptor()->getName(), - transformAttributes(s->getName(), s.get(), logger, pretty), + P.mgr, parent, s->getDescriptor()->getName(), + transformAttributes(s->getName(), s.get(), P), s->getDescriptor()->getParent().cast()->getName()}}; // then transform the children. - transformChildren(s.get(), elem, logger, pretty); + transformChildren(s.get(), elem, P); return elem; } -Rooted XmlTransformer::transformAnchor(Handle parent, - Handle a, - Logger &logger, bool pretty) +Rooted transformAnchor(Handle parent, Handle a, + TransformParams &P) { Rooted elem; if (a->isStart()) { // if this is the start anchor we append all the additional information // of the annotation here. // transform the attributes. - auto attrs = - transformAttributes("", a->getAnnotation().get(), logger, pretty); - addNameAttribute(a->getAnnotation(), attrs); + auto attrs = transformAttributes("", a->getAnnotation().get(), P); elem = Rooted{new Element( - parent->getManager(), parent, - a->getAnnotation()->getDescriptor()->getName(), attrs, "a:start")}; + P.mgr, parent, a->getAnnotation()->getDescriptor()->getName(), + attrs, "a:start")}; // and handle the children. - transformChildren(a->getAnnotation().get(), elem, logger, pretty); + transformChildren(a->getAnnotation().get(), elem, P); } else if (a->isEnd()) { /* * in principle !a->isStart() should imply a->isEnd() but if no @@ -237,23 +506,33 @@ Rooted XmlTransformer::transformAnchor(Handle parent, std::map attrs; addNameAttribute(a->getAnnotation(), attrs); elem = Rooted{new Element( - parent->getManager(), parent, - a->getAnnotation()->getDescriptor()->getName(), attrs, "a:end")}; + P.mgr, parent, a->getAnnotation()->getDescriptor()->getName(), + attrs, "a:end")}; } else { - logger.warning("Ignoring disconnected Anchor", *a); + P.logger.warning("Ignoring disconnected Anchor", *a); } return elem; } -Rooted XmlTransformer::transformPrimitive(Handle parent, - Handle type, - Handle p, - Logger &logger, bool pretty) +/* + * Primitive transform functions. + */ + +std::string toString(Variant v, TransformParams &P) +{ + if (v.isString()) { + return v.asString(); + } else { + return VariantWriter::writeOusiaToString(v, P.pretty); + } +} + +Rooted transformPrimitive(Handle parent, Handle type, + Handle p, TransformParams &P) { - Manager &mgr = parent->getManager(); // transform the primitive content. Variant content = p->getContent(); - if (!type->build(content, logger)) { + if (!type->build(content, P.logger)) { return nullptr; } // special treatment for struct types because they get built as arrays, @@ -268,7 +547,7 @@ Rooted XmlTransformer::transformPrimitive(Handle parent, } content = std::move(map); } - Rooted text{new Text(mgr, parent, toString(content, pretty))}; + Rooted text{new Text(P.mgr, parent, toString(content, P))}; return text; } } diff --git a/src/plugins/xml/XmlOutput.hpp b/src/plugins/xml/XmlOutput.hpp index 55c1c67..da49094 100644 --- a/src/plugins/xml/XmlOutput.hpp +++ b/src/plugins/xml/XmlOutput.hpp @@ -36,35 +36,12 @@ namespace ousia { namespace xml { class XmlTransformer { -private: - std::map transformAttributes( - const std::string &name, DocumentEntity *entity, Logger &logger, - bool pretty); - - void addNameAttribute(Handle n, - std::map &attrs); - - void transformChildren(DocumentEntity *parentEntity, Handle parent, - Logger &logger, bool pretty); - - Rooted transformStructuredEntity(Handle parent, - Handle s, - Logger &logger, bool pretty); - - Rooted transformAnchor(Handle parent, Handle a, - Logger &logger, bool pretty); - - Rooted transformPrimitive(Handle parent, Handle type, - Handle p, Logger &logger, - bool pretty); public: /** * This writes an XML serialization of the given document to the given * output stream. The serialization is equivalent to the input XML format, * safe for the ontology references. TODO: Can we change this? If so: how? - * Note, though, that the serialization will not exploit transparency. - * TODO: Can we change that? * * @param doc is some Document. * @param out is the output stream the XML serialization of the document @@ -74,10 +51,14 @@ public: * typesystems that were imported in this document. * @param pretty is a flag that manipulates whether newlines and tabs are * used. + * @param flat if this flag is set the result will be a 'standalone' + * version of the document including serialized versions of + * all referenced ontologies and typesystems. */ void writeXml(Handle doc, std::ostream &out, Logger &logger, - ResourceManager &resMgr, bool pretty); + ResourceManager &resMgr, bool pretty = true, + bool flat = false); }; } } -#endif +#endif \ No newline at end of file diff --git a/testdata/integration/user_defined_syntax/poem.in.osml b/testdata/integration/user_defined_syntax/poem.in.osml index f1986d9..e8b3796 100644 --- a/testdata/integration/user_defined_syntax/poem.in.osml +++ b/testdata/integration/user_defined_syntax/poem.in.osml @@ -1,27 +1,6 @@ \begin{document} -\ontology#poem{ - \struct#poem[root=true] - \field - \childRef[ref=stanza] - \struct#stanza[transparent=true] - \syntax - \close{\paragraph} - \field - \childRef[ref=line] - \childRef[ref=indentation] - \struct#line[transparent=true] - \syntax - \close{\newline} - \primitive[type=string] - \struct#indentation - \syntax - \open{\indent} - \close{\dedent} - \field - \childRef[ref=line] - \childRef[ref=indentation] -} +\import[ontology]{./poem.osml} % To Autumn by John Keats (1820) % http://en.wikisource.org/wiki/Keats;_poems_published_in_1820/To_Autumn diff --git a/testdata/integration/user_defined_syntax/poem.osml b/testdata/integration/user_defined_syntax/poem.osml new file mode 100644 index 0000000..0c7b065 --- /dev/null +++ b/testdata/integration/user_defined_syntax/poem.osml @@ -0,0 +1,22 @@ +\ontology#poem{ + \struct#poem[root=true] + \field + \childRef[ref=stanza] + \struct#stanza[transparent=true] + \syntax + \close{\paragraph} + \field + \childRef[ref=line] + \childRef[ref=indentation] + \struct#line[transparent=true] + \syntax + \close{\newline} + \primitive[type=string] + \struct#indentation + \syntax + \open{\indent} + \close{\dedent} + \field + \childRef[ref=line] + \childRef[ref=indentation] +} diff --git a/testdata/integration/user_defined_syntax/token_escaping.in.osml b/testdata/integration/user_defined_syntax/token_escaping.in.osml index 66ad1eb..79f6bc7 100644 --- a/testdata/integration/user_defined_syntax/token_escaping.in.osml +++ b/testdata/integration/user_defined_syntax/token_escaping.in.osml @@ -2,20 +2,9 @@ This test checks whether tokens starting with the default field indicator at the beginning works by escaping the "!" with a backslash. }% -\document -\ontology#test{ - \struct#a[root=true] - \field - \childRef[ref=b] - \childRef[ref=c] - \struct#b - \syntax - \short{\!=} - \struct#c - \syntax - \short{=} -} +\document +\import[ontology]{./token_escaping.osml} \begin{a} = != \end{a} diff --git a/testdata/integration/user_defined_syntax/token_escaping.osml b/testdata/integration/user_defined_syntax/token_escaping.osml new file mode 100644 index 0000000..1f76ad7 --- /dev/null +++ b/testdata/integration/user_defined_syntax/token_escaping.osml @@ -0,0 +1,12 @@ +\ontology#test{ + \struct#a[root=true] + \field + \childRef[ref=b] + \childRef[ref=c] + \struct#b + \syntax + \short{\!=} + \struct#c + \syntax + \short{=} +} diff --git a/testdata/integration/user_defined_syntax/wikilike.in.osml b/testdata/integration/user_defined_syntax/wikilike.in.osml index 9bc80c7..88ffa85 100644 --- a/testdata/integration/user_defined_syntax/wikilike.in.osml +++ b/testdata/integration/user_defined_syntax/wikilike.in.osml @@ -1,43 +1,5 @@ \begin{document} - -\ontology#book{ - \struct#book[root=true] - \field - \childRef[ref=section] - \childRef[ref=paragraph] - \struct#section - \primitive#title[type=string,subtree=true] - \syntax - \open{==} - \close{==} - \field - \childRef[ref=paragraph] - \struct#paragraph[transparent=true] - \syntax - \close{\paragraph} - \field - \childRef[ref=text] - \childRef[ref=code] - \childRef[ref=speech] - \childRef[ref=thought] - \struct#code - \syntax - \open{`} - \close{`} - \field - \childRef[ref=text] - \struct#speech - \syntax - \open{<<} - \close{>>} - \fieldRef[ref=paragraph.$default] - \struct#text[transparent=true] - \primitive[type=string] - \struct#thought - \syntax - \short{--} -} - +\import[ontology]{./wikilike.osml} \begin{book} == This tests somewhat plays with user defined syntax == diff --git a/testdata/integration/user_defined_syntax/wikilike.osml b/testdata/integration/user_defined_syntax/wikilike.osml new file mode 100644 index 0000000..694b8ee --- /dev/null +++ b/testdata/integration/user_defined_syntax/wikilike.osml @@ -0,0 +1,37 @@ +\ontology#book{ + \struct#book[root=true] + \field + \childRef[ref=section] + \childRef[ref=paragraph] + \struct#section + \primitive#title[type=string,subtree=true] + \syntax + \open{==} + \close{==} + \field + \childRef[ref=paragraph] + \struct#paragraph[transparent=true] + \syntax + \close{\paragraph} + \field + \childRef[ref=text] + \childRef[ref=code] + \childRef[ref=speech] + \childRef[ref=thought] + \struct#code + \syntax + \open{`} + \close{`} + \field + \childRef[ref=text] + \struct#speech + \syntax + \open{<<} + \close{>>} + \fieldRef[ref=paragraph.$default] + \struct#text[transparent=true] + \primitive[type=string] + \struct#thought + \syntax + \short{--} +} -- cgit v1.2.3