<?xml version="1.0" encoding="UTF-8"?>
<grammar ns="tag:textalign.net,2015:ns" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns:local="tag:textalign.net,2015:ns" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
  <start>
    <element name="TAN-mor">
      <a:documentation>specifies that the TAN file contains definitions for the parts of speech for a language, the codes for those parts, and the rules for combining them. Root element.</a:documentation>
      <ref name="TAN-root"/>
    </element>
  </start>
  <include href="incl/TAN-class-3.rng">
    <define name="decl-id-ref-opt">
      <a:documentation>no declarations may have ids</a:documentation>
      <empty/>
    </define>
    <define name="TAN-body-core">
      <ref name="TAN-R-mor-body"/>
    </define>
  </include>
  <define name="TAN-R-mor-body">
    <a:documentation>TAN-R-mor body consists of zero or more assert, report, category, or options</a:documentation>
    <oneOrMore>
      <ref name="lang-outside"/>
    </oneOrMore>
    <interleave>
      <choice>
        <ref name="feature-list"/>
        <ref name="category-list"/>
      </choice>
      <zeroOrMore>
        <ref name="assert"/>
      </zeroOrMore>
      <zeroOrMore>
        <ref name="report"/>
      </zeroOrMore>
    </interleave>
  </define>
  <define name="feature-list">
    <zeroOrMore>
      <ref name="feature"/>
    </zeroOrMore>
  </define>
  <define name="category-list">
    <zeroOrMore>
      <ref name="category"/>
    </zeroOrMore>
  </define>
  <define name="feature">
    <a:documentation>TAN-R-mor files declare the morphological features that are allowed for a given language</a:documentation>
    <element name="feature">
      <a:documentation>names, through its IRI + name pattern, a grammatical feature or concept (e.g., plural, subjunctive, 1st person) that is part of a language. In the context of &lt;feature&gt; a @code is always included. The first &lt;feature&gt; of a &lt;category&gt; never has @code, and refers to the grammatical feature that characterizes the category.</a:documentation>
      <a:documentation>See main.xml# keywords-feature for a list of standard features, derived  from OLiA.</a:documentation>
      <ref name="feature-pattern"/>
    </element>
  </define>
  <define name="feature-pattern">
    <optional>
      <ref name="ed-stamp"/>
    </optional>
    <choice>
      <ref name="inclusion"/>
      <group>
        <ref name="code"/>
        <interleave>
          <zeroOrMore>
            <ref name="comment"/>
          </zeroOrMore>
          <ref name="entity-nondigital-ref"/>
        </interleave>
      </group>
    </choice>
  </define>
  <define name="feature-pattern-no-code">
    <optional>
      <ref name="ed-stamp"/>
    </optional>
    <choice>
      <ref name="inclusion"/>
      <interleave>
        <zeroOrMore>
          <ref name="comment"/>
        </zeroOrMore>
        <ref name="entity-nondigital-ref"/>
      </interleave>
    </choice>
  </define>
  <!-- code, decl-pattern-default -->
  <define name="category-feature">
    <element name="feature">
      <ref name="feature-pattern-no-code"/>
    </element>
  </define>
  <define name="category">
    <element name="category">
      <a:documentation>groups a set of features that share a common grammatical trait such as gender, number, etc.</a:documentation>
      <optional>
        <ref name="ed-stamp"/>
      </optional>
      <choice>
        <ref name="inclusion"/>
        <interleave>
          <zeroOrMore>
            <ref name="comment"/>
          </zeroOrMore>
          <group>
            <ref name="category-feature"/>
            <oneOrMore>
              <ref name="feature"/>
            </oneOrMore>
          </group>
        </interleave>
      </choice>
    </element>
  </define>
  <define name="code">
    <attribute name="code">
      <a:documentation>contains a string that serves as an identifier for &lt;feature&gt;.</a:documentation>
      <data type="string">
        <a:documentation>hyphen reserved for "not applicable"; spaces and (),| reserved for @feature-test expressions</a:documentation>
        <param name="pattern">[^\-\+\s]|[^\+\s]+</param>
      </data>
    </attribute>
  </define>
  <!-- reports and asserts -->
  <define name="assert">
    <element name="assert">
      <a:documentation>names a pattern that, if found to be false in any &lt;m&gt; in a dependent TAN-LM file, will return the enclosed message upon validation of the dependent file, along with an error or warning. Modeled on Schematron &lt;report&gt;.</a:documentation>
      <ref name="test-pattern"/>
    </element>
  </define>
  <define name="report">
    <element name="report">
      <a:documentation>names a pattern that, if found to be true in any &lt;m&gt; in a dependent TAN-LM file, will return the enclosed message upon validation of the dependent file, along with an error or warning. Modeled on Schematron &lt;report&gt;.</a:documentation>
      <ref name="test-pattern"/>
    </element>
  </define>
  <define name="test-pattern">
    <a:documentation>Test pattern attributes for determining whether to return the message provided by text.</a:documentation>
    <optional>
      <ref name="certainty-stamp"/>
    </optional>
    <choice>
      <ref name="inclusion"/>
      <group>
        <optional>
          <ref name="filter"/>
        </optional>
        <choice>
          <ref name="matches-m"/>
          <ref name="matches-tok"/>
          <ref name="feature-test"/>
          <ref name="feature-qty-test"/>
        </choice>
        <text/>
      </group>
    </choice>
  </define>
  <define name="filter">
    <attribute name="context">
      <a:documentation>specifies under what conditions a particular &lt;assert&gt; or &lt;report&gt; should be enforced. When an &lt;m&gt; in a dependent TAN-LM file is validated, if it contains the codes for the features in question, the other conditions of the &lt;assert&gt; or &lt;report&gt; will be checked; otherwise, the &lt;assert&gt; or &lt;report&gt; will be ignored.</a:documentation>
    </attribute>
  </define>
  <define name="matches-m">
    <attribute name="matches-m">
      <a:documentation>takes a regular expression. If an &lt;m&gt; matches the pattern, then the condition will be true. </a:documentation>
      <a:documentation>One of four tests for determining the truth value that will trigger the message in a &lt;report&gt; or &lt;assert&gt; </a:documentation>
    </attribute>
  </define>
  <define name="matches-tok">
    <attribute name="matches-tok">
      <a:documentation>takes a regular expression. When validating a given &lt;m&gt;, a test will be made against each companion &lt;tok&gt; (i.e., those &lt;tok&gt;s that have the same ancestral &lt;ana&gt;). The condition will be treated as true only if there is a match with the resolved value of every such &lt;tok&gt;, and false if there is any nonmatch. </a:documentation>
      <a:documentation>One of four tests for determining the truth value that will trigger the message in a &lt;report&gt; or &lt;assert&gt; </a:documentation>
    </attribute>
  </define>
  <define name="feature-test">
    <attribute name="feature-test">
      <a:documentation>specifies one or more features separated by spaces or the padded + (a plus sign with surrounding spaces). A plain space is treated  as meaning "or" and the padded + as meaning "and." If there is at least one match between the list and the value of the codes in an &lt;m&gt; then the condition will be treated as true. The padded plus sign specifies that all the items need to be found in the &lt;m&gt;. </a:documentation>
      <a:documentation>For example, feature-test="A B + C D + E" means that the condition will be true for a given &lt;m&gt; only if that &lt;m&gt; has A or B and C or D and E present as values. This test is one of four tests for determining the truth value that will trigger the message in a &lt;report&gt; or &lt;assert&gt; </a:documentation>
      <data type="string">
        <param name="pattern">[^\s\+]+(\s(\+\s)?[^\s\+]+)*</param>
      </data>
    </attribute>
  </define>
  <define name="feature-qty-test">
    <attribute name="feature-qty-test">
      <a:documentation>specifies a range or sequence of integers (e.g., 2-4). If the quantity of features in an &lt;m&gt; matches a number from that sequence, the condition is true, and false otherwise. If the keyword 'last' or 'max' is used, the number of features will be substituted. </a:documentation>
      <a:documentation>This test is useful for non-category based languages to put a limit on the number of features that can be declared in an &lt;m&gt;. It is one of four tests for determining the truth value that will determine whether a &lt;report&gt; or &lt;assert&gt; will be acted upon. </a:documentation>
      <ref name="seq-picker"/>
    </attribute>
  </define>
</grammar>
