// ============================================================================ // // // OpenLDAP Schema Parser // // // ============================================================================ // $Rev$ // ============================================================================ 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. * */ /* * Keep the semicolon right next to the package name or else there will be a * bug that comes into the foreground in the new antlr release. */ package org.apache.directory.api.ldap.schema.converter; import java.util.List ; import java.util.ArrayList ; import java.util.Collections; import java.io.IOException; import org.apache.directory.api.ldap.schema.converter.SchemaElement; import org.apache.directory.api.ldap.model.schema.UsageEnum; import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum; } class antlrSchemaConverterLexer extends Lexer ; options { k = 7 ; exportVocab=antlrSchema ; charVocabulary = '\3'..'\377' ; caseSensitive = false ; defaultErrorHandler = false ; } WS : ( '#' (~'\n')* '\n' { newline(); } | ' ' | '\t' | '\r' '\n' { newline(); } | '\n' { newline(); } | '\r' { newline(); } ) {$setType(Token.SKIP);} //ignore this token ; QUOTE : '\'' ; DIGIT : '0' .. '9' ; DOLLAR : '$' ; OPEN_PAREN : '(' ; CLOSE_PAREN : ')' ; OPEN_BRACKET : '{' ; CLOSE_BRACKET : '}' ; protected NUMERIC_STRING : ('0' .. '9')+ ; NUMERICOID : NUMERIC_STRING ( '.' NUMERIC_STRING )+ ; IDENTIFIER options { testLiterals=true; } : ( 'a' .. 'z') ( 'a' .. 'z' | '0' .. '9' | '-' | ';' )* ; DESC : "desc" WS QUOTE ( ~'\'' | '\\' '\'' )+ QUOTE ; SYNTAX : "syntax" WS NUMERICOID ( OPEN_BRACKET ( DIGIT )+ CLOSE_BRACKET )? ; class antlrSchemaConverterParser extends Parser ; options { k = 5 ; defaultErrorHandler = false ; } { private List schemaElements = new ArrayList(); // ------------------------------------------------------------------------ // Public Methods // ------------------------------------------------------------------------ public void clear() { schemaElements.clear(); } public List getSchemaElements() { return Collections.unmodifiableList( schemaElements ); } } // ---------------------------------------------------------------------------- // Main Entry Point Production // ---------------------------------------------------------------------------- parseSchema : ( attributeType | objectClass )* "END" ; // ---------------------------------------------------------------------------- // AttributeType Productions // ---------------------------------------------------------------------------- objectClass { ObjectClassHolder objectClass = null; } : "objectclass" OPEN_PAREN oid:NUMERICOID { objectClass = new ObjectClassHolder( oid.getText() ); } ( objectClassNames[objectClass] )? ( objectClassDesc[objectClass] )? ( "OBSOLETE" { objectClass.setObsolete( true ); } )? ( objectClassSuperiors[objectClass] )? ( "ABSTRACT" { objectClass.setClassType( ObjectClassTypeEnum.ABSTRACT ); } | "STRUCTURAL" { objectClass.setClassType( ObjectClassTypeEnum.STRUCTURAL ); } | "AUXILIARY" { objectClass.setClassType( ObjectClassTypeEnum.AUXILIARY ); } )? ( must[objectClass] )? ( may[objectClass] )? // @TODO : add ( extension[type] )* CLOSE_PAREN { schemaElements.add( objectClass ); } ; may [ObjectClassHolder objectClass] { List list = null; } : "MAY" list=woidlist { objectClass.setMay( list ); } ; must [ObjectClassHolder objectClass] { List list = null; } : "MUST" list=woidlist { objectClass.setMust( list ); } ; objectClassSuperiors [ObjectClassHolder objectClass] { List list = null; } : "SUP" list=woidlist { objectClass.setSuperiors( list ); } ; woid returns [String oid] { oid = null; } : ( opt1:NUMERICOID { oid = opt1.getText(); } | opt2:IDENTIFIER { oid = opt2.getText(); } ) ; woidlist returns [List list] { list = new ArrayList( 2 ); String oid = null; } : ( oid=woid { list.add( oid ); } | ( OPEN_PAREN oid=woid { list.add( oid ); } ( DOLLAR oid=woid { list.add( oid ); } )* CLOSE_PAREN ) ) ; objectClassDesc [ObjectClassHolder objectClass] : d:DESC { String text = d.getText(); int start = text.indexOf( '\'' ); String desc = text.substring( start + 1, text.length() - 1 ); desc = desc.replace( "\\\"", "\"" ); desc = desc.replace( "\\'", "'" ); desc = desc.replace( "\\27", "'" ); desc = desc.replace( "\\5C", "\"" ); objectClass.setDescription( desc ); } ; objectClassNames [ObjectClassHolder objectClass] { List list = new ArrayList(); } : ( "NAME" ( QUOTE id0:IDENTIFIER QUOTE { list.add( id0.getText() ); } | ( OPEN_PAREN QUOTE id1:IDENTIFIER { list.add( id1.getText() ); } QUOTE ( QUOTE id2:IDENTIFIER QUOTE { list.add( id2.getText() ); } )* CLOSE_PAREN ) ) ) { objectClass.setNames( list ); } ; // ---------------------------------------------------------------------------- // AttributeType Productions // ---------------------------------------------------------------------------- attributeType { AttributeTypeHolder type = null; } : "attributetype" OPEN_PAREN oid:NUMERICOID { type = new AttributeTypeHolder( oid.getText() ); } ( names[type] )? ( attributeTypeDesc[type] )? ( "OBSOLETE" { type.setObsolete( true ); } )? ( superior[type] )? ( equality[type] )? ( ordering[type] )? ( substr[type] )? ( syntax[type] )? ( "SINGLE-VALUE" { type.setSingleValue( true ); } )? ( "COLLECTIVE" { type.setCollective( true ); } )? ( "NO-USER-MODIFICATION" { type.setNoUserModification( true ); } )? ( usage[type] )? // @TODO : add ( extension[type] )* CLOSE_PAREN { schemaElements.add( type ); } ; attributeTypeDesc [AttributeTypeHolder type] : d:DESC { String text = d.getText(); int start = text.indexOf( '\'' ); String desc = text.substring( start +1, text.length() - 1 ); desc = desc.replace( "\\\"", "\"" ); desc = desc.replace( "\\'", "'" ); desc = desc.replace( "\\27", "'" ); desc = desc.replace( "\\5C", "\"" ); type.setDescription( desc ); } ; superior [AttributeTypeHolder type] : "SUP" ( oid:NUMERICOID { type.setSuperior( oid.getText() ); } | id:IDENTIFIER { type.setSuperior( id.getText() ); } ); equality [AttributeTypeHolder type] : "EQUALITY" ( oid:NUMERICOID { type.setEquality( oid.getText() ); } | id:IDENTIFIER { type.setEquality( id.getText() ); } ); substr [AttributeTypeHolder type] : "SUBSTR" ( oid:NUMERICOID { type.setSubstr( oid.getText() ); } | id:IDENTIFIER { type.setSubstr( id.getText() ); } ); ordering [AttributeTypeHolder type] : "ORDERING" ( oid:NUMERICOID { type.setOrdering( oid.getText() ); } | id:IDENTIFIER { type.setOrdering( id.getText() ); } ); names [AttributeTypeHolder type] { List list = new ArrayList(); } : "NAME" ( QUOTE id0:IDENTIFIER QUOTE { list.add( id0.getText() ); } | ( OPEN_PAREN ( QUOTE id1:IDENTIFIER { list.add( id1.getText() ); } QUOTE )+ CLOSE_PAREN ) ) { type.setNames( list ); } ; syntax [AttributeTypeHolder type] : token:SYNTAX { String[] comps = token.getText().split( " " ); int index = comps[1].indexOf( "{" ); if ( index == -1 ) { type.setSyntax( comps[1] ); return; } String oid = comps[1].substring( 0, index ); String length = comps[1].substring( index + 1, comps[1].length() - 1 ); type.setSyntax( oid ); type.setOidLen( Long.parseLong( length ) ); } ; usage [AttributeTypeHolder type] : "USAGE" ( "userApplications" { type.setUsage( UsageEnum.USER_APPLICATIONS ); } | "directoryOperation" { type.setUsage( UsageEnum.DIRECTORY_OPERATION ); } | "distributedOperation" { type.setUsage( UsageEnum.DISTRIBUTED_OPERATION ); } | "dSAOperation" { type.setUsage( UsageEnum.DSA_OPERATION ); } );