; -- Common ABNF Productions

keystring = leadkeychar *keychar
leadkeychar = ALPHA
keychar = ALPHA / DIGIT / HYPHEN
number  = ( LDIGIT 1*DIGIT ) / DIGIT

ALPHA   = %x41-5A / %x61-7A   ; "A"-"Z" / "a"-"z"
DIGIT   = %x30 / LDIGIT       ; "0"-"9"
LDIGIT  = %x31-39             ; "1"-"9"
HEX     = DIGIT / %x41-46 / %x61-66 ; "0"-"9" / "A"-"F" / "a"-"f"

SP      = 1*SPACE  ; one or more " "
WSP     = 0*SPACE  ; zero or more " "
NULL    = %x00 ; null (0)
SPACE   = %x20 ; space (" ")
DQUOTE  = %x22 ; quote (""")
SHARP   = %x23 ; octothorpe (or sharp sign) ("#")
DOLLAR  = %x24 ; dollar sign ("$")
SQUOTE  = %x27 ; single quote ("'")
LPAREN  = %x28 ; left paren ("(")
RPAREN  = %x29 ; right paren (")")
PLUS    = %x2B ; plus sign ("+")
COMMA   = %x2C ; comma (",")
HYPHEN  = %x2D ; hyphen ("-")
DOT     = %x2E ; period (".")
SEMI    = %x3B ; semicolon (";")
LANGLE  = %x3C ; left angle bracket ("<")
EQUALS  = %x3D ; equals sign ("=")
RANGLE  = %x3E ; right angle bracket (">")
ESC     = %x5C ; backslash ("\")
USCORE  = %x5F ; underscore ("_")
LCURLY  = %x7B ; left curly brace "{"
RCURLY  = %x7D ; right curly brace "}"

; Any UTF-8 [RFC3629] encoded Unicode [Unicode] character
UTF8    = UTF1 / UTFMB
UTFMB   = UTF2 / UTF3 / UTF4
UTF0    = %x80-BF
UTF1    = %x00-7F
UTF2    = %xC2-DF UTF0
UTF3    = %xE0 %xA0-BF UTF0 / %xE1-EC 2(UTF0) /
	%xED %x80-9F UTF0 / %xEE-EF 2(UTF0)
UTF4    = %xF0 %x90-BF 2(UTF0) / %xF1-F3 3(UTF0) /
	%xF4 %x80-8F 2(UTF0)

OCTET   = %x00-FF ; Any octet (8-bit data unit)



; ----------------------
; ----------------------

numericoid = number 1*( DOT number )
descr = keystring
oid = descr / numericoid



; ----------------------
; Attribute Description
; ----------------------
attributedescription = attributetype options
attributetype = oid
options = *( SEMI option )
option = 1*keychar

; ----------------------
; Schema Definitions
; ----------------------
noidlen = numericoid [ LCURLY len RCURLY ]
len = number

oids = oid / ( LPAREN WSP oidlist WSP RPAREN )
oidlist = oid *( WSP DOLLAR WSP oid )

extensions = *( SP xstring SP qdstrings )
xstring = "X" HYPHEN 1*( ALPHA / HYPHEN / USCORE )

qdescrs = qdescr / ( LPAREN WSP qdescrlist WSP RPAREN )
qdescrlist = [ qdescr *( SP qdescr ) ]
qdescr = SQUOTE descr SQUOTE

qdstrings = qdstring / ( LPAREN WSP qdstringlist WSP RPAREN )
qdstringlist = [ qdstring *( SP qdstring ) ]
qdstring = SQUOTE dstring SQUOTE
dstring = 1*( QS / QQ / QUTF8 )   ; escaped UTF-8 string

QQ =  ESC %x32 %x37 ; "\27"
QS =  ESC %x35 ( %x43 / %x63 ) ; "\5C" / "\5c"

; Any UTF-8 encoded Unicode character
; except %x27 ("\'") and %x5C ("\")
QUTF8    = QUTF1 / UTFMB

; Any ASCII character except %x27 ("\'") and %x5C ("\")
QUTF1    = %x00-26 / %x28-5B / %x5D-7F



; ----------------------
; Object Class Definitions
; ----------------------
ObjectClassDescription = LPAREN WSP
	numericoid                 ; object identifier
	[ SP "NAME" SP qdescrs ]   ; short names (descriptors)
	[ SP "DESC" SP qdstring ]  ; description
	[ SP "OBSOLETE" ]          ; not active
	[ SP "SUP" SP oids ]       ; superior object classes
	[ SP kind ]                ; kind of class
	[ SP "MUST" SP oids ]      ; attribute types
	[ SP "MAY" SP oids ]       ; attribute types
	extensions WSP RPAREN

kind = "ABSTRACT" / "STRUCTURAL" / "AUXILIARY"



; ----------------------
; Attribute Types
; ----------------------
AttributeTypeDescription = LPAREN WSP
	numericoid                    ; object identifier
	[ SP "NAME" SP qdescrs ]      ; short names (descriptors)
	[ SP "DESC" SP qdstring ]     ; description
	[ SP "OBSOLETE" ]             ; not active
	[ SP "SUP" SP oid ]           ; supertype
	[ SP "EQUALITY" SP oid ]      ; equality matching rule
	[ SP "ORDERING" SP oid ]      ; ordering matching rule
	[ SP "SUBSTR" SP oid ]        ; substrings matching rule
	[ SP "SYNTAX" SP noidlen ]    ; value syntax
	[ SP "SINGLE-VALUE" ]         ; single-value
	[ SP "COLLECTIVE" ]           ; collective
	[ SP "NO-USER-MODIFICATION" ] ; not user modifiable
	[ SP "USAGE" SP usage ]       ; usage
	extensions WSP RPAREN         ; extensions

usage = "userApplications"     /  ; user
	"directoryOperation"   /  ; directory operational
	"distributedOperation" /  ; DSA-shared operational
	"dSAOperation"            ; DSA-specific operational






; ----------------------
; Matching Rules
; ----------------------
MatchingRuleDescription = LPAREN WSP
	numericoid                 ; object identifier
	[ SP "NAME" SP qdescrs ]   ; short names (descriptors)
	[ SP "DESC" SP qdstring ]  ; description
	[ SP "OBSOLETE" ]          ; not active
	SP "SYNTAX" SP numericoid  ; assertion syntax
	extensions WSP RPAREN      ; extensions



; ----------------------
; Matching Rule Uses
; ----------------------
MatchingRuleUseDescription = LPAREN WSP
	numericoid                 ; object identifier
	[ SP "NAME" SP qdescrs ]   ; short names (descriptors)
	[ SP "DESC" SP qdstring ]  ; description
	[ SP "OBSOLETE" ]          ; not active
	SP "APPLIES" SP oids       ; attribute types
	extensions WSP RPAREN      ; extensions



; ----------------------
; LDAP Syntaxes
; ----------------------
SyntaxDescription = LPAREN WSP
	numericoid                 ; object identifier
	[ SP "DESC" SP qdstring ]  ; description
	extensions WSP RPAREN      ; extensions



; ----------------------
; DIT Content Rules
; ----------------------
DITContentRuleDescription = LPAREN WSP
	numericoid                 ; object identifier
	[ SP "NAME" SP qdescrs ]   ; short names (descriptors)
	[ SP "DESC" SP qdstring ]  ; description
	[ SP "OBSOLETE" ]          ; not active
	[ SP "AUX" SP oids ]       ; auxiliary object classes
	[ SP "MUST" SP oids ]      ; attribute types
	[ SP "MAY" SP oids ]       ; attribute types
	[ SP "NOT" SP oids ]       ; attribute types
	extensions WSP RPAREN      ; extensions




; ----------------------
; DIT Structure Rules
; ----------------------
DITStructureRuleDescription = LPAREN WSP
	ruleid                     ; rule identifier
	[ SP "NAME" SP qdescrs ]   ; short names (descriptors)
	[ SP "DESC" SP qdstring ]  ; description
	[ SP "OBSOLETE" ]          ; not active
	SP "FORM" SP oid           ; NameForm
	[ SP "SUP" ruleids ]       ; superior rules
	extensions WSP RPAREN      ; extensions

ruleids = ruleid / ( LPAREN WSP ruleidlist WSP RPAREN )
ruleidlist = ruleid *( SP ruleid )
ruleid = number




; ----------------------
; Name Forms
; ----------------------
NameFormDescription = LPAREN WSP
	numericoid                 ; object identifier
	[ SP "NAME" SP qdescrs ]   ; short names (descriptors)
	[ SP "DESC" SP qdstring ]  ; description
	[ SP "OBSOLETE" ]          ; not active
	SP "OC" SP oid             ; structural object class
	SP "MUST" SP oids          ; attribute types
	[ SP "MAY" SP oids ]       ; attribute types
	extensions WSP RPAREN      ; extensions



; ----------------------
; SCHEMA
; ----------------------
SCHEMA = *(	
			AttributeType / AttributeTypes / 
			ObjectClass / ObjectClasses / 
			
			MatchingRule / MatchingRules / 
			LdapSyntax / LdapSyntaxes / 
			
			NameForm / 
			DITStructureRule / 
			DITContentRule / 
			Syntax / 
			MatchingRuleUse / 
			Attribute
		)

AttributeType = WSP "attributeType" WSP AttributeTypeDescription WSP
AttributeTypes = WSP "attributeTypes:" 1*(WSP AttributeTypeDescription WSP)
ObjectClass = WSP "objectClass" WSP ObjectClassDescription WSP
ObjectClasses = WSP "objectClasses:" 1*(WSP ObjectClassDescription WSP)
	
MatchingRule = WSP "matchingRule" WSP MatchingRuleDescription WSP
MatchingRules = WSP "matchingRules:" 1*(WSP MatchingRuleDescription WSP)
LdapSyntax = WSP "ldapSyntax" WSP SyntaxDescription WSP
LdapSyntaxes = WSP "ldapSyntaxes:" 1*(WSP SyntaxDescription WSP)
	
NameForm = WSP "nameForm" WSP NameFormDescription WSP
DITStructureRule = WSP "DITStructureRule" WSP DITStructureRuleDescription WSP
DITContentRule = WSP "DITContentRule" WSP DITContentRuleDescription WSP
Syntax = WSP "syntax" WSP SyntaxDescription WSP
MatchingRuleUse = WSP "matchingRuleUse" WSP MatchingRuleUseDescription WSP
Attribute = WSP "attribute" WSP attributedescription WSP
