<?xml version="1.0" encoding="utf-8" ?>

<!--
  Copyright (c) 1997-2017
  Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
  http://www.polymake.org

  This program is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2, or (at your option) any
  later version: http://www.gnu.org/licenses/gpl.txt.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
===============================================================================

  Common building blocks for Relax-NG Schemas for polymake v3
-->

<grammar xmlns="http://relaxng.org/ns/structure/1.0"
         datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
         xmlns:note="http://www.math.tu-berlin.de/polymake/note"
         ns="http://www.math.tu-berlin.de/polymake/#3">

  <define name="SubObject">
    <element name="object">
      <optional>
        <note:a> The type defaults to the declared property type </note:a>
        <attribute name="type" />
      </optional>
      <ref name="ObjectContent" />
    </element>
  </define>

  <define name="SimpleName">
    <attribute name="name">
      <data type="string">
        <param name="pattern">[a-zA-Z][a-zA-Z_0-9]*</param>
      </data>
    </attribute>
  </define>

  <define name="PropertyName">
    <attribute name="name">
      <note:a>
        Must be prefixed by the name of the application where this property is introduced
        if that is different from the application where the owning object is defined
        (aka property injection).
      </note:a>
      <data type="string">
        <param name="pattern">([a-zA-Z][a-zA-Z_0-9]*::)?[a-zA-Z][a-zA-Z_0-9]*</param>
      </data>
    </attribute>
  </define>

  <define name="Extensions">
    <optional>
      <attribute name="ext">
        <note:a>
          The first reference to any extension in the document order must consist
          of the ordinal number and the URI; all subsequent references are solely numbers.
        </note:a>
        <data type="string">
          <param name="pattern">( *\d+(=[^\s#]+(#\d+)?)?)+ *</param>
        </data>
      </attribute>
    </optional>
  </define>

  <define name="ObjectTextDescriptions">
    <optional>
      <attribute name="name" />
    </optional>
    <optional>
      <element name="description">
        <text/>
      </element>
    </optional>
    <zeroOrMore>
      <element name="credit">
        <attribute name="product" />
        <text/>
      </element>
    </zeroOrMore>
  </define>

  <define name="ObjectContent">
    <ref name="Extensions" />
    <ref name="ObjectTextDescriptions" />
    <interleave>
      <zeroOrMore>
        <ref name="Property" />
      </zeroOrMore>
      <zeroOrMore>
        <ref name="Attachment" />
      </zeroOrMore>
    </interleave>
  </define>

  <define name="Property">
    <element name="property">
      <ref name="PropertyName" />
      <ref name="Extensions" />
      <choice>
        <group>
          <note:a>
            undefined value is signaled by the special attribute
          </note:a>
          <attribute name="undef"><value>true</value></attribute>
          <empty/>
        </group>

        <group>
 	  <note:a>
            type defaults to the declared property type
          </note:a>
          <optional>
            <attribute name="type" />
          </optional>
          <ref name="PropertyData" />
        </group>

        <ref name="Text" />

        <oneOrMore>
	  <ref name="SubObject" />
        </oneOrMore>
      </choice>
    </element>
  </define>

  <define name="Attachment">
    <element name="attachment">
      <ref name="SimpleName" />
      <ref name="Extensions" />
      <ref name="AttachmentData" />
    </element>
  </define>

  <define name="PropertyData">
    <choice>
      <note:a>
        Scalar property values may be stored in the value attribute,
	saving space and improving legibility.
      </note:a>
      <group>
        <attribute name="value" />
        <empty/>
      </group>

      <ref name="Complex" />

      <note:a> Array of (sub-)objects. </note:a>
      <element name="m">
        <oneOrMore>
	  <ref name="SubObject" />
        </oneOrMore>
      </element>
    </choice>
  </define>

  <define name="AttachmentData">
    <choice>
      <note:a>
        Scalar property values may be stored in the value attribute,
	saving space and improving legibility.
	Default type is String.
      </note:a>
      <group>
        <optional>
          <attribute name="type" />
        </optional>
        <attribute name="value" />
        <empty/>
      </group>

      <group>
        <attribute name="type" />
        <optional>
          <note:a>
            Property path in dotted notation, referring to the enclosing object.
            The property is passed to the constructor of the data stored in this attachment.
          </note:a>
          <attribute name="construct" />
        </optional>
        <ref name="Complex" />
      </group>

      <ref name="Text" />
    </choice>
  </define>

  <define name="Text">
    <note:a>
      Unstructured text must be declared explicitly by the type attribute.
      The contents are expected to be enclosed in CDATA brackets to preserve line breaks etc.
    </note:a>
    <attribute name="type"><value>text</value></attribute>
    <text/>
  </define>

  <define name="Complex">
    <choice>
      <ref name="Vector" />
      <ref name="Matrix" />
      <ref name="Tuple" />
    </choice>
  </define>

  <define name="VectorContents">
    <choice>
      <note:a> A dense vector with simple scalar elements </note:a>
      <list>
        <oneOrMore>
          <data type="string" />
        </oneOrMore>
      </list>
      <note:a> A dense vector with complex elements </note:a>
      <oneOrMore>
        <ref name="Tuple" />
      </oneOrMore>
      <note:a> A sparse vector </note:a>
      <group>
        <note:a>
          Vector dimension; if omitted, the cols attribute of the enclosing matrix has to be taken.
        </note:a>
        <optional>
          <ref name="SparseContainerDim" />
        </optional>
        <choice>
          <note:a> simple scalar elements; this choice matches an empty vector as well </note:a>
          <zeroOrMore>
            <element name="e">
              <ref name="ElementIndex" />
              <data type="string" />
            </element>
          </zeroOrMore>
          <note:a> complex elements </note:a>
          <oneOrMore>
            <element name="t">
              <ref name="ElementIndex" />
              <ref name="TupleContents" />
            </element>
          </oneOrMore>
        </choice>
      </group>
    </choice>
  </define>

  <note:a> index of an element in a sparse container </note:a>
  <define name="ElementIndex">
    <attribute name="i">
      <data type="nonNegativeInteger" />
    </attribute>
  </define>

  <note:a> dimension of a sparse container </note:a>
  <define name="SparseContainerDim">
     <attribute name="dim">
      <data type="nonNegativeInteger" />
    </attribute>
  </define>

  <note:a> number of columns in a matrix </note:a>
  <define name="NumberColumns">
     <attribute name="cols">
      <data type="nonNegativeInteger" />
    </attribute>
  </define>

  <note:a> data instance referred to from other places in the document </note:a>
  <define name="IdAttribute">
    <attribute name="id">
      <data type="nonNegativeInteger" />
    </attribute>
  </define>

  <define name="Vector">
    <element name="v">
      <ref name="VectorContents" />
    </element>
  </define>

  <define name="MatrixContents">
    <note:a> a matrix or a list of complex elements </note:a>
    <choice>
      <group>
        <note:a> cols attribute applies to sparse matrices </note:a>
        <optional>
          <ref name="NumberColumns" />
        </optional>
        <zeroOrMore>
          <ref name="Vector" />
        </zeroOrMore>
      </group>
      <group>
        <note:a>
          sparse container of complex elements, like graph with gaps left over from deleted nodes
        </note:a>
        <ref name="SparseContainerDim" />
        <optional>
          <ref name="NumberColumns" />
        </optional>
        <zeroOrMore>
          <element name="v">
            <ref name="ElementIndex" />
            <ref name="VectorContents" />
          </element>
        </zeroOrMore>
      </group>
      <oneOrMore>
        <ref name="Matrix" />
      </oneOrMore>
      <oneOrMore>
        <ref name="Tuple" />
      </oneOrMore>
    </choice>
  </define>

  <define name="Matrix">
    <element name="m">
      <ref name="MatrixContents" />
    </element>
  </define>

  <define name="TupleContents">
    <note:a> a heterogeneous ordered list </note:a>
    <choice>
      <note:a> all elements are simple acalars </note:a>
      <list>
        <oneOrMore>
          <data type="string" />
        </oneOrMore>
      </list>
      <note:a> at least one complex element </note:a>
      <oneOrMore>
        <choice>
          <ref name="Vector" />
          <ref name="Matrix" />
          <ref name="Tuple" />
          <element name="e">
            <data type="string" />
          </element>
        </choice>
      </oneOrMore>
    </choice>
  </define>

  <define name="Tuple">
    <element name="t">
      <ref name="TupleContents" />
    </element>
  </define>

</grammar>
