<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % ALLREGEX "(any|letter|interval|set|string|cat|or|star|plus|optional|at-least|range|times|macro)">
<!ENTITY % INT "CDATA">
<!ENTITY % URI "CDATA">
<!ENTITY % CHAR "CDATA">
<!ENTITY % BOOLEAN "(true|false)">

<!ELEMENT lexer (define-macro|rule|define-macro-xml|rule-xml)*>

<!-- macroes -->

<!ELEMENT define-macro EMPTY>
<!ATTLIST define-macro pattern CDATA #REQUIRED
                       name CDATA #REQUIRED>

<!ELEMENT define-macro-xml (%ALLREGEX;)>
<!ATTLIST define-macro-xml name CDATA #REQUIRED>

<!-- rules -->

<!ELEMENT rule EMPTY>
<!ATTLIST rule id CDATA #REQUIRED
	              pattern CDATA #REQUIRED>

<!ELEMENT rule-xml (main,(follow|end-of-line)?)>
<!ATTLIST rule-xml beginning-of-line %BOOLEAN; #IMPLIED
	                  id CDATA #REQUIRED>

<!ELEMENT main (%ALLREGEX;)>

<!ELEMENT follow (%ALLREGEX;)>

<!ELEMENT end-of-line EMPTY>

<!-- regex -->

<!ELEMENT letter EMPTY>
<!ATTLIST letter value %CHAR; #REQUIRED>

<!ELEMENT string EMPTY>
<!ATTLIST string value CDATA #REQUIRED
	             ignore-case %BOOLEAN; #IMPLIED>

<!ELEMENT any EMPTY>

<!ELEMENT star (%ALLREGEX;)>

<!ELEMENT plus (%ALLREGEX;)>

<!ELEMENT optional (%ALLREGEX;)>

<!ELEMENT range (%ALLREGEX;)>
<!ATTLIST range to %INT; #REQUIRED
	               from %INT; #REQUIRED>

<!ELEMENT at-least (%ALLREGEX;)>
<!ATTLIST at-least from %INT; #REQUIRED>

<!ELEMENT times (%ALLREGEX;)>
<!ATTLIST times value %INT; #REQUIRED>

<!ELEMENT cat (%ALLREGEX;,(%ALLREGEX;)+)>

<!ELEMENT or (%ALLREGEX;,(%ALLREGEX;)+)>

<!ELEMENT set ((interval|letter)+)>
<!ATTLIST set negate %BOOLEAN; #IMPLIED>

<!ELEMENT interval EMPTY>
<!ATTLIST interval from %CHAR; #REQUIRED
                   to %CHAR; #REQUIRED>

<!ELEMENT macro EMPTY>
<!ATTLIST macro name CDATA #REQUIRED>