/** * ASN.1 Parsing */ grammar ASN_1; options { language = Java; output = AST; ASTLabelType = 'CommonTree'; memoize = true; } tokens { // literals ABSENT='ABSENT'; ABSTRACT_SYNTAX='ABSTRACT-SYNTAX'; ALL='ALL'; APPLICATION='APPLICATION'; AUTOMATIC='AUTOMATIC'; BEGIN='BEGIN'; BIT='BIT'; BMPString='BMPSTRING'; BOOLEAN='BOOLEAN'; BY='BY'; CHARACTER='CHARACTER'; CHOICE='CHOICE'; CLASS='CLASS'; COMPONENT='COMPONENT'; COMPONENTS='COMPONENTS'; CONSTRAINED='CONSTRAINED'; CONTAINING='CONTAINING'; DEFAULT='DEFAULT'; DEFINITIONS='DEFINITIONS'; EMBEDDED='EMBEDDED'; ENCODED='ENCODED'; ENCODING_CONTROL='ENCODING-CONTROL'; END='END'; ENUMERATED='ENUMERATED'; EXCEPT='EXCEPT'; EXPLICIT='EXPLICIT'; EXPORTS='EXPORTS'; EXTENSIBILITY='EXTENSIBILITY'; EXTERNAL='EXTERNAL'; FALSE='FALSE'; FROM='FROM'; GeneralizedTime='GeneralizedTime'; GeneralString='GeneralString'; GraphicString='GraphicString'; IA5String='IA5String'; IDENTIFIER='IDENTIFIER'; IMPLICIT='IMPLICIT'; IMPLIED='IMPLIED'; IMPORTS='IMPORTS'; INCLUDES='INCLUDES'; INSTANCE='INSTANCE'; INSTRUCTIONS='INSTRUCTIONS'; INTEGER='INTEGER'; INTERSECTION='INTERSECTION'; ISO646String='ISO646String'; MAX='MAX'; MIN='MIN'; MINUS_INFINITY='MINUS-INFINITY'; NOT_A_NUMBER='NOT-A-NUMBER'; NULL='NULL'; NumericString='NumericString'; OBJECT='OBJECT'; ObjectDescriptor='ObjectDescriptor'; OCTET='OCTET'; OF='OF'; OPTIONAL='OPTIONAL'; PATTERN='PATTERN'; PDV='PDV'; PLUS_INFINITY='PLUS-INFINITY'; PRESENT='PRESENT'; PrintableString='PrintableString'; PRIVATE='PRIVATE'; REAL='REAL'; RELATIVE_OID='RELATIVE-OID'; SEQUENCE='SEQUENCE'; SET='SET'; SIZE='SIZE'; STRING='STRING'; SYNTAX='SYNTAX'; T61String='T61String'; TAGS='TAGS'; TeletexString='TeletexString'; TRUE='TRUE'; TYPE_IDENTIFIER='TYPE-IDENTIFIER'; UNION='UNION'; UNIQUE='UNIQUE'; UNIVERSAL='UNIVERSAL'; UniversalString='UniversalString'; UTCTime='UTCTime'; UTF8String='UTF8String'; VideotexString='VideotexString'; VisibleString='VisibleString'; WITH='WITH'; // tokens accessed by actions HSTRING; BSTRING; NUMBER; // virtual tokens } @header { package com.gobito.asn_1.parse; import static com.gobito.asn_1.parse.ParseUtil.*; } @lexer::header { package com.gobito.asn_1.parse; import static com.gobito.asn_1.parse.ParseUtil.*; } @members { } @lexer::members { } // Lexical elements //"real" stuff WS : (WSNONL | NL) {$channel=HIDDEN;}; fragment NL : ('\n' | '\r' | '\u000B' | '\f'); fragment WSNONL : (' ' | '\t'); fragment LETTER: 'a'..'z' | 'A'..'Z'; fragment DIGIT: '0'..'9'; fragment IDHYPHEN: '-' (LETTER|DIGIT); fragment IDBODY : (LETTER|DIGIT|IDHYPHEN); CAPID : 'A'..'Z' IDBODY*; LCID : 'a'..'z' IDBODY*; fragment MLCOMMENTf : '/*' .* (MLCOMMENTf .*)* '*/'; MLCOMMENT : MLCOMMENTf {$channel=HIDDEN;}; SLCOMMENT : ('--' .* ('--'|NL)) {$channel=HIDDEN;}; fragment NUMBERf : '0' | '1'..'9' DIGIT*; REALNUMBER : (NUMBERf '.')=> NUMBERf ('.'(DIGIT+)?)? (('e'|'E')('+'|'-')? NUMBERf)? | NUMBERf {$type=NUMBER;}; fragment HSTRINGCONT : ('0'..'9' | 'A'..'F' | WS)*; HorBSTRING : '\'' cont=HSTRINGCONT '\'' ('H' {$type=HSTRING;}|'B' {$type=BSTRING;}) {($type == HSTRING) || isValidBSTRING($cont.text)}?; fragment CSTRINGNL : WSNONL* NL WSNONL*; CSTRING options {backtrack=true;}: ('"') {skip();} ((WS)=> ((CSTRINGNL)=>CSTRINGNL {skip();} | WSNONL+) | '"' {skip();} '"' | ~'"')* ('"' {skip();}) {$channel=DEFAULT;}; // handling xml fragment XMLNAMECHAR : 'A'..'Z' | 'a'..'z' | '0'..'9' | '-' | ':' | '_' | '.' ; fragment XMLNAMESTART: 'A'..'Z' | 'a'..'z' | '_' | ':' ; fragment INVALIDINXML : '<' | '&' ; fragment XMLENTREF : '&' XMLNAME ';' ; fragment XMLNAME : XMLNAMESTART XMLNAMECHAR+; fragment XMLSATTVAL : '\'' ( ('&')=>XMLENTREF | (~('\''|INVALIDINXML) ) )* '\''; fragment XMLDATTVAL : '"' ( ('&')=>XMLENTREF | (~('"'|INVALIDINXML) ) )* '"'; fragment XMLATTVAL : XMLDATTVAL | XMLSATTVAL ; fragment XMLATTRIB : XMLNAME '=' XMLATTVAL ; fragment WSBLOCK : WS+; fragment XMLATTRIBS : XMLATTRIB | (XMLATTRIB WS)=>XMLATTRIB WSBLOCK XMLATTRIBS; fragment XMLTAGATTS : WSBLOCK XMLATTRIBS ; fragment XMLOPENTAG : '<' XMLNAME XMLTAGATTS? WS* '>'; fragment XMLCLOSETAG : ''; fragment XMLSCLOSETAG : '<' XMLNAME XMLTAGATTS? WS* '/>'; fragment XMLNONEMPTYELEMENT : XMLOPENTAG XMLCONTENT XMLCLOSETAG; fragment XMLEMPTYELEMENT : XMLSCLOSETAG; fragment XMLELEMENT options { backtrack=true; } : XMLEMPTYELEMENT | XMLNONEMPTYELEMENT ; fragment XMLCONTENT : (XMLELEMENT | XMLENTREF | ~INVALIDINXML) *; XMLFRAG : XMLELEMENT; // Parser rules modulereference : CAPID; typereference : CAPID; encodingreference : CAPID {ucidIsAllUC($CAPID.text)}?; identifier : LCID; valuereference : LCID; moduleDefinition : moduleIdentifier DEFINITIONS encodingReferenceDefault tagDefault extensionDefault '::=' BEGIN moduleBody encodingControlSections END; encodingReferenceDefault : (encodingreference INSTRUCTIONS)?; moduleIdentifier : modulereference | definitiveIdentifier; definitiveIdentifier : '{' definitiveObjIdComponentList '}' | ; definitiveObjIdComponentList : definitiveObjIdComponent | definitiveObjIdComponent definitiveObjIdComponentList ; definitiveObjIdComponent : nameForm | definitiveNumberForm | definitiveNameAndNumberForm ; definitiveNumberForm : NUMBER ; definitiveNameAndNumberForm : identifier '(' definitiveNumberForm ')'; nameForm : identifier ; tagDefault : (EXPLICIT | IMPLICIT | AUTOMATIC) TAGS | ; extensionDefault : EXTENSIBILITY IMPLIED | ; moduleBody : (exports imports assignmentList)? ; exports : EXPORTS symbolsExported ';' | EXPORTS ALL ';' | ; symbolsExported : symbolList?; imports : IMPORTS symbolsImported | ; symbolsImported : symbolsFromModuleList? ; symbolsFromModuleList : symbolsFromModule+ ; symbolsFromModule : symbolList FROM globalModuleReference ; globalModuleReference : modulereference ((objectIdentifierValue)=>objectIdentifierValue | definedValue)? ; symbolList : symbol (',' symbol)* ; symbol : reference /*| parameterizedReference*/ ; reference : typereference | valuereference /* | objectclassreference | objectReference | objectSetReference */; assignmentList : assignment+ ; assignment options {backtrack=true;} : typeAssignment | valueAssignment | xmlValueAssignment | valueSetTypeAssignment /*| objectClassAssignment | objectAssignment | objectSetAssignment | parameterizedAssignment*/ ; definedType : externalTypeReference | typereference /*| parameterizedType | parameterizedValueSetType*/ ; definedValue : externalValueReference | valuereference /*| parameterizedValue*/ ; externalTypeReference : modulereference '.' typereference ; externalValueReference : modulereference '.' valuereference ; typeAssignment : typereference '::=' type ; valueAssignment : valuereference type '::=' value; xmlValueAssignment : valuereference '::=' xmlTypedValue; xmlTypedValue : XMLFRAG ; // needs some clever semantic predicating, probably valueSetTypeAssignment : typereference (type '::='|'::=' type) '{' elementSetSpecs '}'; type : (typeWithConstraint | builtinType | referencedType) constraint* ; builtinType : bitStringType | booleanType | characterStringType | choiceType | embeddedPDVType | enumeratedType | externalType /*| instanceOfType*/ | integerType | nullType /*| objectClassFieldType*/ | objectIdentifierType | octetStringType | realType | relativeOIDType | sequenceType | sequenceOfType | setType | setOfType | prefixedType ; referencedType : (usefulType)=>usefulType | definedType | selectionType /*| typeFromObject */ /*| valueSetFromObjects*/ ; namedType : identifier type; value options {backtrack=true;} : builtinValue | referencedValue /*| objectClassFieldValue*/ ; builtinValue options {backtrack=true;} : bitStringValue | booleanValue | characterStringValue | choiceValue | embeddedPDVValue | enumeratedValue | externalValue /*| instanceOfValue*/ | integerValue | nullValue | objectIdentifierValue | octetStringValue | realValue | relativeOIDValue | sequenceValue | sequenceOfValue | setValue | setOfValue /*| prefixedValue*/ ; referencedValue : definedValue /*| valueFromObject */; namedValue : identifier value; booleanType : BOOLEAN ; booleanValue : TRUE | FALSE ; integerType : INTEGER ('{' namedNumberList '}')?; namedNumberList : namedNumber (',' namedNumber)*; namedNumber : identifier '(' (signedNumber | definedValue) ')'; signedNumber : NUMBER | '-' NUMBER {$NUMBER.text != "0"}?; integerValue : signedNumber | identifier ; enumeratedType : ENUMERATED '{' enumerations '}' ; enumerations : rootEnumeration (',' '...' exceptionSpec (',' additionalEnumeration)?)? ; rootEnumeration : enumeration ; additionalEnumeration : enumeration ; enumeration : enumerationItem (',' enumerationItem)* ; enumerationItem : identifier | namedNumber ; enumeratedValue : identifier ; realType : REAL ; realValue : numericRealValue | specialRealValue ; numericRealValue : REALNUMBER | '-' REALNUMBER {Double.parseDouble($REALNUMBER.text) != 0.0}? | sequenceValue ; specialRealValue : PLUS_INFINITY | MINUS_INFINITY | NOT_A_NUMBER; bitStringType : BIT STRING ('{' namedBitList '}')? ; namedBitList : namedBit (',' namedBit)* ; namedBit : identifier '(' (NUMBER | definedValue) ')'; bitStringValue : BSTRING | HSTRING | '{' identifierList? '}' | CONTAINING value ; identifierList : identifier (',' identifier)* ; octetStringType : OCTET STRING ; octetStringValue : BSTRING | HSTRING | CONTAINING value ; nullType : NULL; nullValue : NULL; sequenceType : SEQUENCE '{' sequenceTypeBody '}'; sequenceTypeBody options {backtrack=true;} : componentTypeLists? ; extensionAndException : '...' exceptionSpec ; optionalExtensionMarker : (',' '...')? ; ctlExtensionStuff : extensionAndException extensionAdditions ( optionalExtensionMarker | extensionEndMarker ',' rootComponentTypeList ) ; componentTypeLists : ctlExtensionStuff | rootComponentTypeList (',' ctlExtensionStuff)? ; rootComponentTypeList : componentTypeList ; extensionEndMarker : ',' '...'; extensionAdditions : (',' extensionAdditionList)? ; extensionAdditionList : extensionAddition (',' extensionAddition)* ; extensionAddition : componentType | extensionAdditionGroup ; extensionAdditionGroup : '[[' versionNumber componentTypeList ']]' ; componentTypeList : componentType (',' componentType)* ; componentType : namedType (OPTIONAL | DEFAULT value)? | COMPONENTS OF type ; sequenceValue : '{' componentValueList? '}'; componentValueList : namedValue (',' namedValue)* ; sequenceOfType : SEQUENCE OF (type | namedType) ; sequenceOfValue : '{' ( (namedValueList)=>namedValueList | valueList)? '}' ; valueList : value (',' value)* ; namedValueList : namedValue (',' namedValue)* ; setType : '{' componentTypeLists? '}' ; setValue : '{' componentValueList? '}' ; setOfType : SET OF (type | namedType); setOfValue : '{' (valueList | namedValueList)? '}' ; choiceType : CHOICE '{' alternativeTypeLists '}' ; alternativeTypeLists : rootAlternativeTypeList (',' extensionAndException extensionAdditionAlternatives optionalExtensionMarker)? ; rootAlternativeTypeList : alternativeTypeList ; extensionAdditionAlternatives : (',' extensionAdditionAlternativesList)? ; extensionAdditionAlternativesList : extensionAdditionAlternative (',' extensionAdditionAlternative)* ; extensionAdditionAlternative : extensionAdditionAlternativesGroup | namedType ; extensionAdditionAlternativesGroup : '[[' versionNumber alternativeTypeList ']]'; choiceValue : identifier ':' value ; alternativeTypeList : namedType (',' namedType)* ; selectionType : identifier '<' type ; prefixedType : taggedType | encodingPrefixedType ; taggedType : tag (IMPLICIT|EXPLICIT)? type ; tag : '[' encodingReference clazz classNumber ']' ; encodingReference : (encodingreference ':')? ; encodingPrefixedType : encodingPrefix type ; encodingPrefix : '[' encodingReference /*encodingInstruction*/ ']' ; classNumber : NUMBER | definedValue ; clazz : (UNIVERSAL | APPLICATION | PRIVATE)? ; objectIdentifierType : OBJECT IDENTIFIER ; objectIdentifierValue : '{' ( ((definedValue)=>definedValue objIdComponents+) | objIdComponents+) '}' ; objIdComponents options{backtrack=true;} : nameForm {isStandardOIDName($text)}? | numberForm | nameAndNumberForm | definedValue ; numberForm : NUMBER ; nameAndNumberForm : identifier '(' numberForm ')' ; relativeOIDType : RELATIVE_OID ; relativeOIDValue : '{' relativeOIDComponentsList '}' ; relativeOIDComponentsList : relativeOIDComponents+ ; relativeOIDComponents : numberForm | nameAndNumberForm | definedValue ; embeddedPDVType : EMBEDDED PDV ; embeddedPDVValue : sequenceValue ; externalType : EXTERNAL ; externalValue : sequenceValue ; characterStringType : restrictedCharacterStringType | unrestrictedCharacterStringType ; characterStringValue : restrictedCharacterStringValue | unrestrictedCharacterStringValue ; restrictedCharacterStringType : BMPString | GeneralString | GraphicString | IA5String | ISO646String | NumericString | PrintableString | TeletexString | T61String | UniversalString | UTF8String | VideotexString | VisibleString ; restrictedCharacterStringValue : CSTRING | characterStringList | quadruple | tuple ; characterStringList : '{' charSyms '}' ; charSyms : charsDefn (',' charsDefn)* ; charsDefn : CSTRING | quadruple | tuple | definedValue ; quadruple : '{' group ',' plane ',' row ',' cell '}' ; group : NUMBER; plane : NUMBER; row : NUMBER; cell : NUMBER; tuple : '{' tableColumn ',' tableRow '}' ; tableColumn : NUMBER ; tableRow : NUMBER ; unrestrictedCharacterStringType : CHARACTER STRING ; unrestrictedCharacterStringValue : sequenceValue ; usefulType : a=typereference {$a.text == "GeneralizedTime" || $a.text == "UTCTime" || $a.text == "ObjectDescriptor" }? ; typeWithConstraint : (SET | SEQUENCE) (constraint | sizeConstraint) OF type ; constraint : '(' constraintSpec exceptionSpec ')' ; constraintSpec : subtypeConstraint /*| generalConstraint*/ ; subtypeConstraint : elementSetSpecs ; elementSetSpecs : rootElementSetSpec (',' '...' (',' additionalElementSetSpec)?)? ; rootElementSetSpec : elementSetSpec; additionalElementSetSpec : elementSetSpec; elementSetSpec : unions | ALL exclusions ; unions : intersections (unionMark intersections)* ; //uElems : unions ; intersections : intersectionElements (intersectionMark intersectionElements)* ; //iElems : intersections ; intersectionElements : elements exclusions? ; exclusions : EXCEPT elements ; unionMark : '|' | UNION ; intersectionMark : '^' | INTERSECTION ; elements : subtypeElements /*| objectSetElements*/ | '(' elementSetSpec ')' ; subtypeElements options {backtrack=true;} : valueRange | singleValue | containedSubtype | permittedAlphabet | sizeConstraint | typeConstraint | innerTypeConstraints | patternConstraint; singleValue : value; containedSubtype : INCLUDES? type; //includes : INCLUDES? ; valueRange : lowerEndpoint '..' upperEndpoint ; lowerEndpoint : lowerEndValue '<'? ; upperEndpoint : '<'? upperEndValue ; lowerEndValue : value | MIN ; upperEndValue : value | MAX ; sizeConstraint : SIZE constraint ; typeConstraint : type ; permittedAlphabet : FROM constraint; innerTypeConstraints : WITH (COMPONENT singleTypeConstraint | COMPONENTS multipleTypeConstraints) ; singleTypeConstraint : constraint ; multipleTypeConstraints : fullSpecification | partialSpecification ; fullSpecification : '{' typeConstraints '}' ; partialSpecification : '{' '...' ',' typeConstraints '}' ; typeConstraints : namedConstraint (',' namedConstraint)* ; namedConstraint : identifier componentConstraint ; componentConstraint : valueConstraint presenceConstraint ; valueConstraint : constraint? ; presenceConstraint : (PRESENT|ABSENT|OPTIONAL)? ; patternConstraint : PATTERN value ; exceptionSpec : ('!' exceptionIdentification)? ; exceptionIdentification : signedNumber | definedValue | type ':' value ; versionNumber : (NUMBER ':')? ; encodingControlSections: encodingControlSection* ; encodingControlSection : ENCODING_CONTROL encodingreference encodingInstructionAssignmentList; encodingInstructionAssignmentList : ~(END|ENCODING_CONTROL)* ;