<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<!--
 | The <language/> element is the root node of language files.
 !
 ! Ex: <language name="foo">
 !       <lexer/>
 !       <parser/>
 !       </language>
 +-->
<xsd:element name="language">
  <xsd:complexType>
    <!--
     ! The <language/> element has, in order,
     ! one <lexer/> element, and one <parser/> element.
     +-->
    <xsd:sequence>
      <xsd:element ref="lexer"/>
      <xsd:element ref="parser"/>
      </xsd:sequence>

    <!--
     ! The <language/> element has a "name" attribute.
     +-->
    <xsd:attribute name="name" type="xsd:NMTOKEN" use="required"/>
    </xsd:complexType>
  </xsd:element>

<!--
 | The <lexer/> element describes the lexical portions of the language.
 +-->
<xsd:element name="lexer">
  <xsd:complexType>
    <!--
     ! The <lexer/> element may have <option/>, <pattern/>, <match/>,
     ! <ignore/>, and <error/> elements. The order of the <match/>,
     ! <ignore/>, and <error/> rules will be significant to most lexer
     ! generators.
     +-->
    <xsd:sequence>
      <xsd:choice maxOccurs="unbounded">

        <!--
         ! The <option/> element is used to pass options to the parser.
         !
         ! Ex: <option>case-insensitive</option>
         +-->
        <xsd:element name="option" type="xsd:string"/>

        <!--
         ! The <pattern/> element is used to define regex patterns to be
         ! reused by the lexical match rules.
         !
         ! Ex: <pattern name="NL">\n|\r\n|\r|\f</pattern>
         +-->
        <xsd:element name="pattern">
          <xsd:complexType>
            <xsd:simpleContent>
              <xsd:restriction base="xsd:string">
                <xsd:attribute name="name" type="xsd:NMTOKEN"
                  use="required"/>
                </xsd:restriction>
              </xsd:simpleContent>
            </xsd:complexType>
          </xsd:element>

        <!--
         ! The <match/> element is used to define lexical actions which
         ! generate terminal sub-trees. These sub-trees will consist of an
         ! element node (with the name given by the "term" attribute),
         ! containing a text node whose value is that of the matched lexem.
         !
         ! Ex: <match term="IMPORT_SYM">"@import"</match>
         !     <match term="identity">{IDENT}</match>
         !     <match term="HASH">"#"{NAME}</match>
         +-->
        <xsd:element name="match">
          <xsd:complexType>
            <xsd:simpleContent>
              <xsd:restriction base="xsd:string">
                <xsd:attribute name="term" type="xsd:NMTOKEN"
                  use="required"/>
                </xsd:restriction>
              </xsd:simpleContent>
            </xsd:complexType>
          </xsd:element>

        <!--
         ! The <ignore/> element is used to define lexical actions which
         ! ignore their lexem.
         !
         ! Ex: <ignore>\/\*[^*]*\*+([^/*][^*]*\*+)*\/</ignore>
         +-->
        <xsd:element name="ignore" type="xsd:string"/>

        <!--
         ! The <error/> element is used to define lexical actions which
         ! halt parsing and signal an error. (Often an 'anything' match
         ! placed at the end of the lexer section.)
         !
         ! Ex: <error>.</error>
         +-->
        <xsd:element name="error" type="xsd:string"/>

        </xsd:choice>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>


<!--
 ! The <parser/> element describes the grammatical portions of the language.
 +-->
<xsd:element name="parser">
  <xsd:complexType>
    <!--
     ! The <parser/> element has some number of <nonterm/> and <list/>
     ! elements. <list/> elements must be resolved down to <nonterm/>
     ! elements before code can be generated.
     +-->
    <xsd:sequence>
      <xsd:choice maxOccurs="unbounded">
        <xsd:element ref="nonterm"/>
        <xsd:element ref="list"/>
        </xsd:choice>
      </xsd:sequence>

    <!--
     ! The "start" attribute specifys the start symbol of the grammar.
     ! If it is not present, then the first <nonterm/> or <list/> will be
     ! used as the start symbol.
     +-->
    <xsd:attribute name="start" type="xsd:NMTOKEN"/>

    <!--
     ! The "expected_conflicts" attribute specifys the number of
     ! shift/reduce conflicts the parser generator should expect
     ! in the language. It defaults to "0".
     +-->
    <xsd:attribute name="expected_conflicts" type="xsd:nonNegativeInteger"
        default="0"/>

    </xsd:complexType>
  </xsd:element>

<!--
 ! <nonterm/> elements describe a Non-Terminal in the grammar.
 +-->
<xsd:element name="nonterm">
  <xsd:complexType>

    <!--
     ! <nonterm/> elements contain 0 or more <production/> elements. 
     +-->
    <xsd:sequence>
      <xsd:element name="production" type="ProductionType"
          minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>

    <!--
     ! The "name" attribute of <nonterm/>'s specify the name of the
     ! associated Symbol, and of the root of the symbol's sub-tree.
     +-->
    <xsd:attribute name="name" use="required" type="xsd:NMTOKEN"/>

    <!--
     ! The "epsilon" attribute sets if a Non-Terminal has any empty
     ! grammatical productions. Note, this -must- be specified using the
     ! "epsilon" attribute, and not an empty <production/> element.
     +-->
    <xsd:attribute name="epsilon" type="xsd:boolean" default="false"/>
    </xsd:complexType>
  </xsd:element>

<!--
 ! <list/> elements describe high-order lists which map to collections of
 ! recursive <nonterm/>s.
 +-->
<xsd:element name="list">
  <xsd:complexType>

    <!--
     ! <list/> elements contain <delimiter/> elements and <production/>
     ! elements. All of the <delimiter/> elements come before all of the
     ! <production/> elements.
     +-->
    <xsd:sequence>
      <xsd:element name="delimiter" type="ProductionType"
        minOccurs="0" maxOccurs="unbounded"/>
  
      <xsd:element name="production" type="ProductionType"
        maxOccurs="unbounded"/>
  
      </xsd:sequence>

    <!--
     ! The "name" attribute of <nonterm/>'s specify the name of the
     ! associated Symbol, and of the root of the symbol's sub-tree.
     +-->
    <xsd:attribute name="name" use="required" type="xsd:NMTOKEN"/>

    <!--
     ! The "epsilon", "item_epsilon", and "delim_epsilon" attributes of a
     ! <list/> are related. Only one of them can be set to "true", but
     ! there is no way to enforce this constraint in a schema yet.
     +-->
    <xsd:attribute name="epsilon" type="xsd:boolean" default="false"/>
    <xsd:attribute name="item_epsilon" type="xsd:boolean" default="false"/>
    <xsd:attribute name="delim_epsilon" type="xsd:boolean" default="false"/>

    <!--
     ! "item_name" is a rename name for list item nodes. Note, this is a
     ! rename name, so these nodes are not available as symbols to use in
     ! other productions!
     !
     !"item_action is the action to re-write item nodes with.
     !
     ! The attributes "item_name" and "item_action" are related.
     ! When "item_name" is not set, "item_action" defaults to "content".
     ! When "item_name" is set, "item_action" defaults to "preserve".
     +-->
    <xsd:attribute name="item_name" type="xsd:NMTOKEN"/>
    <xsd:attribute name="item_action" type="ActionType"/>

    <!--
     ! "delim_name" is a rename name for list delimiter nodes. Note, this is a
     ! rename name, so these nodes are not available as symbols to use in
     ! other productions!
     !
     !"delim_action is the action to re-write delimiter nodes with.
     !
     ! The attributes "delim_name" and "delim_action" are related.
     ! When "delim_name" is not set, "delim_action" defaults to "drop".
     ! When "delim_name" is set, "delim_action" defaults to "token".
     +-->
    <xsd:attribute name="delim_name" type="xsd:NMTOKEN"/>
    <xsd:attribute name="delim_action" type="ActionType"/>
    </xsd:complexType>
  </xsd:element>

<!--
 ! The ProductionType type is used by both the <delimiter/> and
 ! <production/> elements. It contains a list of one or more <symbol/>
 ! elements, which specify their own re-write actions.
 +-->
<xsd:complexType name="ProductionType">
  <xsd:sequence>
    <xsd:element name="symbol" maxOccurs="unbounded">
      <xsd:complexType>
        <xsd:simpleContent>
          <xsd:restriction base='xsd:NMTOKEN'>

            <!--
             ! The "action" attribute specifiys the re-write action which
             ! should be applied to a <symbol/>'s subtree at parse time.
             ! It defaults to "preserve".
             +-->
            <xsd:attribute name="action" type="ActionType" default="preserve"/>

            <!--
             ! If a <symbol/>'s subtree should be renamed at parse time,
             ! the "rename" attribute specifiys the new name.
             +-->
            <xsd:attribute name="rename" type="xsd:NMTOKEN"/>

            <!--
             ! The <language/> language supports optional symbols, through
             ! the use of a (language => language) transform. However, the
             ! transform never produces empty productions. Thus A? B? will
             ! yield A B and A and B, but not the epsilon production.
             +-->
            <xsd:attribute name="optional" type="xsd:boolean" default="false"/>

            </xsd:restriction>
          </xsd:simpleContent>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

<!--
 ! The ActionType type is used by various attributes to specify which
 ! re-write action to take at production time. It enumerates four possible
 ! values: "preserve", "content", "token", and "drop".
 +-->
<xsd:simpleType name="ActionType">
  <xsd:restriction base="xsd:string">
    <xsd:enumeration value="preserve"/>
    <xsd:enumeration value="content"/>
    <xsd:enumeration value="token"/>
    <xsd:enumeration value="drop"/>
    </xsd:restriction>
  </xsd:simpleType>

</xsd:schema>
