blob: 9aa790b4bb4507376982777c767b2cc028abc61e [file] [log] [blame]
header {
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.api.ldap.model.schema.syntaxes;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.directory.api.ldap.model.schema.parsers.LdapComparatorDescription;
import org.apache.directory.api.ldap.model.schema.DitContentRule;
import org.apache.directory.api.ldap.model.schema.DitStructureRule;
import org.apache.directory.api.ldap.model.schema.LdapSyntax;
import org.apache.directory.api.ldap.model.schema.MatchingRule;
import org.apache.directory.api.ldap.model.schema.MutableMatchingRule;
import org.apache.directory.api.ldap.model.schema.MatchingRuleUse;
import org.apache.directory.api.ldap.model.schema.NameForm;
import org.apache.directory.api.ldap.model.schema.parsers.NormalizerDescription;
import org.apache.directory.api.ldap.model.schema.parsers.ParserMonitor;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.api.ldap.model.schema.MutableAttributeType;
import org.apache.directory.api.ldap.model.schema.ObjectClass;
import org.apache.directory.api.ldap.model.schema.MutableObjectClass;
import org.apache.directory.api.ldap.model.schema.parsers.SyntaxCheckerDescription;
import org.apache.directory.api.ldap.model.schema.syntaxCheckers.OpenLdapObjectIdentifierMacro;
import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum;
import org.apache.directory.api.ldap.model.schema.UsageEnum;
}
/**
* An antlr generated schema main lexer.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
class AntlrSchemaLexer extends Lexer;
options {
k = 8 ;
exportVocab=AntlrSchema ;
charVocabulary = '\u0000'..'\uFFFE';
caseSensitive = false ;
defaultErrorHandler = false ;
}
WHSP
:
( options {greedy=true;} :
' '
|
'\t'
|
'\r' (options {greedy=true;} : '\n')? { newline(); }
|
'\n' { newline(); }
|
'#' (~'\n')* '\n' { newline(); }
)+
{$setType(Token.SKIP);} //ignore this token
;
LPAR : '(' ;
RPAR : ')' ;
QUOTE : '\'' ;
DOLLAR : '$' ;
LBRACKET : '{' ;
RBRACKET : '}' ;
LEN : LBRACKET ('0'..'9')+ RBRACKET ;
SINGLE_VALUE : ( "single-value" (WHSP)? ) ;
COLLECTIVE : ( "collective" (WHSP)? ) ;
NO_USER_MODIFICATION : ( "no-user-modification" (WHSP)? ) ;
OBSOLETE : ( "obsolete" (WHSP)? ) ;
ABSTRACT : ( "abstract" (WHSP)? ) ;
STRUCTURAL : ( "structural" (WHSP)? ) ;
protected AUXILIARY : ( "auxiliary" (WHSP)? ) ;
OBJECTIDENTIFIER :
( "objectidentifier"
WHSP
( oiName:UNQUOTED_STRING )
WHSP
( oiValue:UNQUOTED_STRING )
)
{ setText( oiName.getText() + " " + oiValue.getText() ); }
;
OBJECTCLASS : ( "objectclass" (WHSP)? ) ;
ATTRIBUTETYPE : ( "attributetype" (WHSP)? ) ;
STARTNUMERICOID : ( LPAR (options {greedy=true;} : WHSP)? ( numericoid:VALUES ) ) { setText(numericoid.getText()); } ;
NAME : ( "name" (options {greedy=true;} : WHSP)? qdstrings:VALUES ) { setText(qdstrings.getText().trim()); } ;
DESC : ( "desc" (options {greedy=true;} : WHSP)? qdstring:VALUES ) { setText(qdstring.getText().trim()); } ;
SUP : ( "sup" (options {greedy=true;} : WHSP)? sup:VALUES ) { setText(sup.getText().trim()); } ;
MUST : ( "must" (options {greedy=true;} : WHSP)? must:VALUES ) { setText(must.getText().trim()); } ;
MAY : ( "may" (options {greedy=true;} : WHSP)? may:VALUES ) { setText(may.getText()); } ;
protected AUX : ( "aux" (options {greedy=true;} : WHSP)? aux:VALUES ) { setText(aux.getText()); } ;
NOT : ( "not" (options {greedy=true;} : WHSP)? not:VALUES ) { setText(not.getText()); } ;
FORM : ( "form" (options {greedy=true;} : WHSP)? form:VALUES ) { setText(form.getText()); } ;
OC : ( "oc" (options {greedy=true;} : WHSP)? oc:VALUES ) { setText(oc.getText()); } ;
EQUALITY : ( "equality" (options {greedy=true;} : WHSP)? equality:VALUES ) { setText(equality.getText().trim()); } ;
ORDERING : ( "ordering" (options {greedy=true;} : WHSP)? ordering:VALUES ) { setText(ordering.getText().trim()); } ;
SUBSTR : ( "substr" (options {greedy=true;} : WHSP)? substring:VALUES ) { setText(substring.getText().trim()); } ;
SYNTAX : ( "syntax" (options {greedy=true;} : WHSP)? syntax:VALUES (len:LEN)? ) { setText(syntax.getText().trim() + (len!=null?len.getText().trim():"")); } ;
APPLIES : ( "applies" (options {greedy=true;} : WHSP)? applies:VALUES ) { setText(applies.getText().trim()); } ;
EXTENSION : x:( "x-" ( options {greedy=true;} : 'a'..'z' | '-' | '_' )+ (options {greedy=true;} : WHSP)? VALUES ) ;
FQCN : ( "fqcn" (options {greedy=true;} : WHSP)? fqcn:FQCN_VALUE ) { setText(fqcn.getText().trim()); } ;
BYTECODE : ( "bytecode" (options {greedy=true;} : WHSP)? bytecode:BYTECODE_VALUE ) { setText(bytecode.getText().trim()); } ;
AUX_OR_AUXILIARY :
( AUXILIARY ) => AUXILIARY { $setType( AUXILIARY ); }
|
( AUX ) { $setType( AUX ); }
;
protected VALUES : ( VALUE | LPAR VALUE ( (DOLLAR)? VALUE )* RPAR ) ;
protected VALUE : (WHSP)? ( QUOTED_STRING | UNQUOTED_STRING ) (options {greedy=true;}: WHSP)? ;
protected UNQUOTED_STRING : (options{greedy=true;}: 'a'..'z' | '0'..'9' | '-' | '_' | ';' | '.' | ':' )+ ;
protected QUOTED_STRING : ( QUOTE (~'\'')* QUOTE ) ;
protected FQCN_VALUE : ( FQCN_IDENTIFIER ( '.' FQCN_IDENTIFIER )* ) ;
protected FQCN_IDENTIFIER : ( FQCN_LETTER ( FQCN_LETTERORDIGIT )* ) ;
protected FQCN_LETTER :
'\u0024' |
'\u005f' |
'\u0061'..'\u007a' |
'\u00c0'..'\u00d6' |
'\u00d8'..'\u00f6' |
'\u00f8'..'\u00ff' |
'\u0100'..'\u1fff' |
'\u3040'..'\u318f' |
'\u3300'..'\u337f' |
'\u3400'..'\u3d2d' |
'\u4e00'..'\u9fff' |
'\uf900'..'\ufaff' ;
protected FQCN_LETTERORDIGIT :
'\u0024' |
'\u005f' |
'\u0061'..'\u007a' |
'\u00c0'..'\u00d6' |
'\u00d8'..'\u00f6' |
'\u00f8'..'\u00ff' |
'\u0100'..'\u1fff' |
'\u3040'..'\u318f' |
'\u3300'..'\u337f' |
'\u3400'..'\u3d2d' |
'\u4e00'..'\u9fff' |
'\uf900'..'\ufaff' |
'\u0030'..'\u0039' ;
protected BYTECODE_VALUE : ( 'a'..'z' | '0'..'9' | '+' | '/' | '=' )+ ;
USAGE : ( "usage" (WHSP)? ) ;
USER_APPLICATIONS : ( "userapplications" (WHSP)? ) ;
DIRECTORY_OPERATION : ( "directoryoperation" (WHSP)? ) ;
DISTRIBUTED_OPERATION : ( "distributedoperation" (WHSP)? ) ;
DSA_OPERATION : ( "dsaoperation" (WHSP)? ) ;
/**
* An antlr generated schema main parser.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
class AntlrSchemaParser extends Parser;
options {
k = 3 ;
defaultErrorHandler = false ;
//buildAST=true ;
}
{
private ParserMonitor monitor = null;
private boolean isQuirksModeEnabled = false;
public void setParserMonitor( ParserMonitor monitor )
{
this.monitor = monitor;
}
private void matchedProduction( String msg )
{
if ( null != monitor )
{
monitor.matchedProduction( msg );
}
}
public void setQuirksMode( boolean enabled )
{
this.isQuirksModeEnabled = enabled;
}
public boolean isQuirksMode()
{
return this.isQuirksModeEnabled;
}
static class Extension
{
String key = "";
List<String> values = new ArrayList<String>();
public void addValue( String value )
{
this.values.add( value );
}
}
static class NoidLen
{
String noid = "";
long len = 0L;
}
static class ElementTracker
{
Map<String, Integer> elementMap = new HashMap<String, Integer>();
void track(String element, Token token) throws SemanticException
{
if(elementMap.containsKey(element))
{
throw new SemanticException( element + " appears twice.", token.getFilename(), token.getLine() , token.getColumn() );
}
elementMap.put(element, Integer.valueOf(1));
}
boolean contains(String element)
{
return elementMap.containsKey(element);
}
}
}
openLdapSchema returns [List<Object> list = new ArrayList<Object>()]
{
AttributeType attributeType = null;
ObjectClass objectClass = null;
OpenLdapObjectIdentifierMacro oloid = null;
}
:
(
oloid = openLdapObjectIdentifier { list.add( oloid ); }
|
attributeType = openLdapAttributeType { list.add( attributeType ); }
|
objectClass = openLdapObjectClass { list.add( objectClass ); }
)*
;
openLdapObjectIdentifier returns [OpenLdapObjectIdentifierMacro oloid]
{
matchedProduction( "openLdapObjectIdentifier()" );
}
:
(
oi:OBJECTIDENTIFIER
{
String[] nameAndValue = oi.getText().split( " " );
oloid = new OpenLdapObjectIdentifierMacro();
oloid.setName( nameAndValue[0] );
oloid.setRawOidOrNameSuffix( nameAndValue[1] );
}
)
;
openLdapObjectClass returns [ObjectClass objectClass]
{
matchedProduction( "openLdapObjectClass()" );
}
:
(
OBJECTCLASS
( objectClass=objectClassDescription )
)
;
openLdapAttributeType returns [AttributeType attributeType]
{
matchedProduction( "openLdapAttributeType()" );
}
:
(
ATTRIBUTETYPE
( attributeType=attributeTypeDescription )
)
;
/**
* Production for matching object class descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* 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"
*
* extensions = *( SP xstring SP qdstrings )
* xstring = "X" HYPHEN 1*( ALPHA / HYPHEN / USCORE )
* </pre>
*/
objectClassDescription returns [MutableObjectClass objectClass]
{
matchedProduction( "objectClassDescription()" );
ElementTracker et = new ElementTracker();
}
:
( oid:STARTNUMERICOID { objectClass = new MutableObjectClass(numericoid(oid.getText())); } )
(
( name:NAME { et.track("NAME", name); objectClass.setNames(qdescrs(name.getText())); } )
|
( desc:DESC { et.track("DESC", desc); objectClass.setDescription(qdstring(desc.getText())); } )
|
( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); objectClass.setObsolete( true ); } )
|
( sup:SUP { et.track("SUP", sup); objectClass.setSuperiorOids(oids(sup.getText())); } )
|
( kind1:ABSTRACT { et.track("KIND", kind1); objectClass.setType( ObjectClassTypeEnum.ABSTRACT ); }
|
kind2:STRUCTURAL { et.track("KIND", kind2); objectClass.setType( ObjectClassTypeEnum.STRUCTURAL ); }
|
kind3:AUXILIARY { et.track("KIND", kind3); objectClass.setType( ObjectClassTypeEnum.AUXILIARY ); }
)
|
( must:MUST { et.track("MUST", must); objectClass.setMustAttributeTypeOids(oids(must.getText())); } )
|
( may:MAY { et.track("MAY", may); objectClass.setMayAttributeTypeOids(oids(may.getText())); } )
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
objectClass.addExtension(ex.key, ex.values);
} )
)*
RPAR
;
/**
* Production for matching attribute type descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* 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
*
* extensions = *( SP xstring SP qdstrings )
* xstring = "X" HYPHEN 1*( ALPHA / HYPHEN / USCORE )
* </pre>
*/
attributeTypeDescription returns [MutableAttributeType attributeType]
{
matchedProduction( "attributeTypeDescription()" );
ElementTracker et = new ElementTracker();
}
:
( oid:STARTNUMERICOID { attributeType = new MutableAttributeType(numericoid(oid.getText())); } )
(
( name:NAME { et.track("NAME", name); attributeType.setNames(qdescrs(name.getText())); } )
|
( desc:DESC { et.track("DESC", desc); attributeType.setDescription(qdstring(desc.getText())); } )
|
( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); attributeType.setObsolete( true ); } )
|
( superior:SUP { et.track("SUP", superior); attributeType.setSuperiorOid(oid(superior.getText())); } )
|
( equality:EQUALITY { et.track("EQUALITY", equality); attributeType.setEqualityOid(oid(equality.getText())); } )
|
( ordering:ORDERING { et.track("ORDERING", ordering); attributeType.setOrderingOid(oid(ordering.getText())); } )
|
( substring:SUBSTR { et.track("SUBSTR", substring); attributeType.setSubstringOid(oid(substring.getText())); } )
|
( syntax:SYNTAX {
et.track("SYNTAX", syntax);
NoidLen noidlen = noidlen(syntax.getText());
attributeType.setSyntaxOid(noidlen.noid);
attributeType.setSyntaxLength(noidlen.len);
} )
|
( singleValued:SINGLE_VALUE { et.track("SINGLE_VALUE", singleValued); attributeType.setSingleValued( true ); } )
|
( collective:COLLECTIVE { et.track("COLLECTIVE", collective); attributeType.setCollective( true ); } )
|
( noUserModification:NO_USER_MODIFICATION { et.track("NO_USER_MODIFICATION", noUserModification); attributeType.setUserModifiable( false ); } )
|
( usage1:USAGE (WHSP)* USER_APPLICATIONS { et.track("USAGE", usage1); attributeType.setUsage( UsageEnum.USER_APPLICATIONS ); }
|
usage2:USAGE DIRECTORY_OPERATION { et.track("USAGE", usage2); attributeType.setUsage( UsageEnum.DIRECTORY_OPERATION ); }
|
usage3:USAGE DISTRIBUTED_OPERATION { et.track("USAGE", usage3); attributeType.setUsage( UsageEnum.DISTRIBUTED_OPERATION ); }
|
usage4:USAGE DSA_OPERATION { et.track("USAGE", usage4); attributeType.setUsage( UsageEnum.DSA_OPERATION ); }
)
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
attributeType.addExtension(ex.key, ex.values);
} )
)*
RPAR
{
if( !isQuirksModeEnabled )
{
// semantic check: required elements
if( !et.contains("SYNTAX") && !et.contains("SUP") )
{
throw new SemanticException( "One of SYNTAX or SUP is required", null, 0, 0 );
}
// COLLECTIVE requires USAGE userApplications
if ( attributeType.isCollective() && ( attributeType.getUsage() != UsageEnum.USER_APPLICATIONS ) )
{
throw new SemanticException( "COLLECTIVE requires USAGE userApplications", null, 0, 0 );
}
// NO-USER-MODIFICATION requires an operational USAGE.
if ( !attributeType.isUserModifiable() && ( attributeType.getUsage() == UsageEnum.USER_APPLICATIONS ) )
{
throw new SemanticException( "NO-USER-MODIFICATION requires an operational USAGE", null, 0, 0 );
}
}
}
;
/**
* Production for matching ldap syntax descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* SyntaxDescription = LPAREN WSP
* numericoid ; object identifier
* [ SP "DESC" SP qdstring ] ; description
* extensions WSP RPAREN ; extensions
* </pre>
*/
ldapSyntaxDescription returns [LdapSyntax ldapSyntax]
{
matchedProduction( "ldapSyntaxDescription()" );
ElementTracker et = new ElementTracker();
}
:
( oid:STARTNUMERICOID { ldapSyntax = new LdapSyntax(numericoid(oid.getText())); } )
(
( name:NAME { et.track("NAME", name); ldapSyntax.setNames(qdescrs(name.getText())); } )
|
( desc:DESC { et.track("DESC", desc); ldapSyntax.setDescription(qdstring(desc.getText())); } )
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
ldapSyntax.addExtension(ex.key, ex.values);
} )
)*
RPAR
;
/**
* Production for matching rule descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* 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
* </pre>
*/
matchingRuleDescription returns [MutableMatchingRule matchingRule]
{
matchedProduction( "matchingRuleDescription()" );
ElementTracker et = new ElementTracker();
}
:
( oid:STARTNUMERICOID { matchingRule = new MutableMatchingRule(numericoid(oid.getText())); } )
(
( name:NAME { et.track("NAME", name); matchingRule.setNames(qdescrs(name.getText())); } )
|
( desc:DESC { et.track("DESC", desc); matchingRule.setDescription(qdstring(desc.getText())); } )
|
( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); matchingRule.setObsolete( true ); } )
|
( syntax:SYNTAX { et.track("SYNTAX", syntax); matchingRule.setSyntaxOid(numericoid(syntax.getText())); } )
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
matchingRule.addExtension(ex.key, ex.values);
} )
)*
RPAR
{
if( !isQuirksModeEnabled )
{
// semantic check: required elements
if( !et.contains("SYNTAX") ) {
throw new SemanticException( "SYNTAX is required", null, 0, 0 );
}
}
}
;
/**
* Production for matching rule use descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* 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
* </pre>
*/
matchingRuleUseDescription returns [MatchingRuleUse matchingRuleUse]
{
matchedProduction( "matchingRuleUseDescription()" );
ElementTracker et = new ElementTracker();
}
:
( oid:STARTNUMERICOID { matchingRuleUse = new MatchingRuleUse(numericoid(oid.getText())); } )
(
( name:NAME { et.track("NAME", name); matchingRuleUse.setNames(qdescrs(name.getText())); } )
|
( desc:DESC { et.track("DESC", desc); matchingRuleUse.setDescription(qdstring(desc.getText())); } )
|
( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); matchingRuleUse.setObsolete( true ); } )
|
( applies:APPLIES { et.track("APPLIES", applies); matchingRuleUse.setApplicableAttributeOids(oids(applies.getText())); } )
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
matchingRuleUse.addExtension(ex.key, ex.values);
} )
)*
RPAR
{
if( !isQuirksModeEnabled )
{
// semantic check: required elements
if( !et.contains("APPLIES") ) {
throw new SemanticException( "APPLIES is required", null, 0, 0 );
}
}
}
;
/**
* Production for DIT content rule descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* 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
* </pre>
*/
ditContentRuleDescription returns [DitContentRule ditContentRule]
{
matchedProduction( "ditContentRuleDescription()" );
ElementTracker et = new ElementTracker();
}
:
( oid:STARTNUMERICOID { ditContentRule = new DitContentRule(numericoid(oid.getText())); } )
(
( name:NAME { et.track("NAME", name); ditContentRule.setNames(qdescrs(name.getText())); } )
|
( desc:DESC { et.track("DESC", desc); ditContentRule.setDescription(qdstring(desc.getText())); } )
|
( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); ditContentRule.setObsolete( true ); } )
|
( aux:AUX { et.track("AUX", aux); ditContentRule.setAuxObjectClassOids(oids(aux.getText())); } )
|
( must:MUST { et.track("MUST", must); ditContentRule.setMustAttributeTypeOids(oids(must.getText())); } )
|
( may:MAY { et.track("MAY", may); ditContentRule.setMayAttributeTypeOids(oids(may.getText())); } )
|
( not:NOT { et.track("NOT", not); ditContentRule.setNotAttributeTypeOids(oids(not.getText())); } )
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
ditContentRule.addExtension(ex.key, ex.values);
} )
)*
RPAR
;
/**
* Production for DIT structure rules descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* 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
* </pre>
*/
ditStructureRuleDescription returns [DitStructureRule ditStructureRule]
{
matchedProduction( "ditStructureRuleDescription()" );
ElementTracker et = new ElementTracker();
}
:
( ruleid:STARTNUMERICOID { ditStructureRule = new DitStructureRule(ruleid(ruleid.getText())); } )
(
( name:NAME { et.track("NAME", name); ditStructureRule.setNames(qdescrs(name.getText())); } )
|
( desc:DESC { et.track("DESC", desc); ditStructureRule.setDescription(qdstring(desc.getText())); } )
|
( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); ditStructureRule.setObsolete( true ); } )
|
( form:FORM { et.track("FORM", form); ditStructureRule.setForm(oid(form.getText())); } )
|
( sup:SUP { et.track("SUP", sup); ditStructureRule.setSuperRules(ruleids(sup.getText())); } )
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
ditStructureRule.addExtension(ex.key, ex.values);
} )
)*
RPAR
{
if( !isQuirksModeEnabled )
{
// semantic check: required elements
if( !et.contains("FORM") ) {
throw new SemanticException( "FORM is required", null, 0, 0 );
}
}
}
;
/**
* Production for name form descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* 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
* </pre>
*/
nameFormDescription returns [NameForm nameForm]
{
matchedProduction( "nameFormDescription()" );
ElementTracker et = new ElementTracker();
}
:
( oid:STARTNUMERICOID { nameForm = new NameForm(numericoid(oid.getText())); } )
(
( name:NAME { et.track("NAME", name); nameForm.setNames(qdescrs(name.getText())); } )
|
( desc:DESC { et.track("DESC", desc); nameForm.setDescription(qdstring(desc.getText())); } )
|
( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); nameForm.setObsolete( true ); } )
|
( oc:OC { et.track("OC", oc); nameForm.setStructuralObjectClassOid(oid(oc.getText())); } )
|
( must:MUST { et.track("MUST", must); nameForm.setMustAttributeTypeOids(oids(must.getText())); } )
|
( may:MAY { et.track("MAY", may); nameForm.setMayAttributeTypeOids(oids(may.getText())); } )
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
nameForm.addExtension(ex.key, ex.values);
} )
)*
RPAR
{
if( !isQuirksModeEnabled )
{
// semantic check: required elements
if( !et.contains("MUST") ) {
throw new SemanticException( "MUST is required", null, 0, 0 );
}
if( !et.contains("OC") ) {
throw new SemanticException( "OC is required", null, 0, 0 );
}
// semantic check: MUST and MAY must be disjoint
//List<String> aList = new ArrayList<String>( nfd.getMustAttributeTypes() );
//aList.retainAll( nfd.getMayAttributeTypes() );
//if( !aList.isEmpty() )
//{
// throw new SemanticException( "MUST and MAY must be disjoint, "+aList.get( 0 )+" appears in both", null, 0, 0 );
//}
}
}
;
/**
* Production for comparator descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* LdapComparator = LPAREN WSP
* numericoid ; object identifier
* [ SP "DESC" SP qdstring ] ; description
* SP "FQCN" SP fqcn ; fully qualified class name
* [ SP "BYTECODE" SP base64 ] ; optional base64 encoded bytecode
* extensions WSP RPAREN ; extensions
*
* base64 = *(4base64-char)
* base64-char = ALPHA / DIGIT / "+" / "/"
* fqcn = fqcnComponent 1*( DOT fqcnComponent )
* fqcnComponent = ???
* </pre>
*/
ldapComparator returns [LdapComparatorDescription lcd]
{
matchedProduction( "ldapComparator()" );
ElementTracker et = new ElementTracker();
}
:
( oid:STARTNUMERICOID { lcd = new LdapComparatorDescription(numericoid(oid.getText())); } )
(
( desc:DESC { et.track("DESC", desc); lcd.setDescription(qdstring(desc.getText())); } )
|
( fqcn:FQCN { et.track("FQCN", fqcn); lcd.setFqcn(fqcn.getText()); } )
|
( bytecode:BYTECODE { et.track("BYTECODE", bytecode); lcd.setBytecode(bytecode.getText()); } )
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
lcd.addExtension(ex.key, ex.values);
} )
)*
RPAR
{
if( !isQuirksModeEnabled )
{
// semantic check: required elements
if( !et.contains("FQCN") ) {
throw new SemanticException( "FQCN is required", null, 0, 0 );
}
// semantic check: length should be divisible by 4
if( ( lcd.getBytecode() != null ) && ( lcd.getBytecode().length() % 4 != 0 ) ) {
throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
}
}
}
;
/**
* Production for normalizer descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* NormalizerDescription = LPAREN WSP
* numericoid ; object identifier
* [ SP "DESC" SP qdstring ] ; description
* SP "FQCN" SP fqcn ; fully qualified class name
* [ SP "BYTECODE" SP base64 ] ; optional base64 encoded bytecode
* extensions WSP RPAREN ; extensions
*
* base64 = *(4base64-char)
* base64-char = ALPHA / DIGIT / "+" / "/"
* fqcn = fqcnComponent 1*( DOT fqcnComponent )
* fqcnComponent = ???
* </pre>
*/
normalizerDescription returns [NormalizerDescription nd]
{
matchedProduction( "normalizerDescription()" );
ElementTracker et = new ElementTracker();
}
:
( oid:STARTNUMERICOID { nd = new NormalizerDescription(numericoid(oid.getText())); } )
(
( desc:DESC { et.track("DESC", desc); nd.setDescription(qdstring(desc.getText())); } )
|
( fqcn:FQCN { et.track("FQCN", fqcn); nd.setFqcn(fqcn.getText()); } )
|
( bytecode:BYTECODE { et.track("BYTECODE", bytecode); nd.setBytecode(bytecode.getText()); } )
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
nd.addExtension(ex.key, ex.values);
} )
)*
RPAR
{
if( !isQuirksModeEnabled )
{
// semantic check: required elements
if( !et.contains("FQCN") ) {
throw new SemanticException( "FQCN is required", null, 0, 0 );
}
// semantic check: length should be divisible by 4
if( nd.getBytecode() != null && ( nd.getBytecode().length() % 4 != 0 ) ) {
throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
}
}
}
;
/**
* Production for syntax checker descriptions. It is fault-tolerant
* against element ordering.
*
* <pre>
* SyntaxCheckerDescription = LPAREN WSP
* numericoid ; object identifier
* [ SP "DESC" SP qdstring ] ; description
* SP "FQCN" SP fqcn ; fully qualified class name
* [ SP "BYTECODE" SP base64 ] ; optional base64 encoded bytecode
* extensions WSP RPAREN ; extensions
*
* base64 = *(4base64-char)
* base64-char = ALPHA / DIGIT / "+" / "/"
* fqcn = fqcnComponent 1*( DOT fqcnComponent )
* fqcnComponent = ???
* </pre>
*/
syntaxCheckerDescription returns [SyntaxCheckerDescription scd]
{
matchedProduction( "syntaxCheckerDescription()" );
ElementTracker et = new ElementTracker();
}
:
( oid:STARTNUMERICOID { scd = new SyntaxCheckerDescription(numericoid(oid.getText())); } )
(
( desc:DESC { et.track("DESC", desc); scd.setDescription(qdstring(desc.getText())); } )
|
( fqcn:FQCN { et.track("FQCN", fqcn); scd.setFqcn(fqcn.getText()); } )
|
( bytecode:BYTECODE { et.track("BYTECODE", bytecode); scd.setBytecode(bytecode.getText()); } )
|
( extension:EXTENSION {
Extension ex = extension(extension.getText());
et.track(ex.key, extension);
scd.addExtension(ex.key, ex.values);
} )
)*
RPAR
{
if( !isQuirksModeEnabled )
{
// semantic check: required elements
if( !et.contains("FQCN") ) {
throw new SemanticException( "FQCN is required", null, 0, 0 );
}
// semantic check: length should be divisible by 4
if( scd.getBytecode() != null && ( scd.getBytecode().length() % 4 != 0 ) ) {
throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
}
}
}
;
noidlen [String s] returns [NoidLen noidlen]
{
matchedProduction( "noidlen()" );
AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
parser.setParserMonitor(monitor);
noidlen = isQuirksModeEnabled ? parser.quirksNoidlen() : parser.noidlen();
}
:
;
extension [String s] returns [Extension extension]
{
matchedProduction( "extension()" );
AntlrSchemaExtensionLexer lexer = new AntlrSchemaExtensionLexer(new StringReader(s));
AntlrSchemaExtensionParser parser = new AntlrSchemaExtensionParser(lexer);
extension = parser.extension();
}
:
;
numericoid [String s] returns [String numericoid]
{
matchedProduction( "numericoid()");
if(isQuirksModeEnabled)
{
numericoid = oid(s);
}
else
{
AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
parser.setParserMonitor(monitor);
numericoid = parser.numericoid();
}
}
:
;
oid [String s] returns [String oid]
{
matchedProduction( "oid()" );
List<String> oids = oids(s);
if( oids.size() != 1 )
{
throw new SemanticException( "Exactly one OID expected", null, 0, 0 );
}
oid = oids.get(0);
}
:
;
oids [String s] returns [List<String> oids]
{
matchedProduction( "oids()" );
if(isQuirksModeEnabled)
{
oids = qdescrs(s);
}
else
{
AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
parser.setParserMonitor(monitor);
oids = parser.oids();
}
}
:
;
qdescr [String s] returns [String qdescr]
{
matchedProduction( "qdescr()" );
List<String> qdescrs = qdescrs(s);
if( qdescrs.size() != 1 )
{
throw new SemanticException( "Exactly one qdescrs expected", null, 0, 0 );
}
qdescr = qdescrs.get(0);
}
:
;
qdescrs [String s] returns [List<String> qdescrs]
{
matchedProduction( "qdescrs()" );
AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
parser.setParserMonitor(monitor);
qdescrs = isQuirksModeEnabled ? parser.quirksQdescrs() : parser.qdescrs();
}
:
;
qdstring [String s] returns [String qdstring]
{
matchedProduction( "qdstring()" );
List<String> qdstrings = qdstrings(s);
if( qdstrings.size() != 1 )
{
throw new SemanticException( "Exactly one qdstrings expected", null, 0, 0 );
}
qdstring = qdstrings.get(0);
}
:
;
qdstrings [String s] returns [List<String> qdstrings]
{
matchedProduction( "qdstrings()" );
AntlrSchemaQdstringLexer lexer = new AntlrSchemaQdstringLexer(new StringReader(s));
AntlrSchemaQdstringParser parser = new AntlrSchemaQdstringParser(lexer);
parser.setParserMonitor(monitor);
qdstrings = parser.qdstrings();
}
:
;
ruleid [String s] returns [Integer ruleid]
{
matchedProduction( "ruleid()" );
AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
parser.setParserMonitor(monitor);
ruleid = parser.ruleid();
}
:
;
ruleids [String s] returns [List<Integer> ruleids]
{
matchedProduction( "ruleids()" );
AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
parser.setParserMonitor(monitor);
ruleids = parser.ruleids();
}
:
;