blob: e045dec4f2b0fbed3f74c862b5c862007a64614c [file] [log] [blame]
grammar Proguard;
options{
k = 3;
}
tokens {
NEGATOR = '!';
}
@header {
package com.android.jack.shrob.proguard;
import com.android.jack.shrob.spec.*;
import com.android.jack.shrob.spec.ClassTypeSpecification.TypeEnum;
import com.android.jack.shrob.spec.ModifierSpecification.*;
import com.android.jack.shrob.proguard.GrammarActions;
import com.android.jack.shrob.proguard.GrammarActions.FilterSeparator;
}
@lexer::header {
package com.android.jack.shrob.proguard;
import com.android.jack.shrob.spec.KeepModifier;
}
@members {
@Override
protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException {
throw new RecognitionException(input);
}
@Override
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
throw new RecoverableRecognitionException(e);
}
}
@lexer::members {
@Override
protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException {
throw new RecognitionException(input);
}
@Override
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
throw new RecoverableRecognitionException(e);
}
}
prog [Flags flags, String baseDirectory] throws ProguardFileParsingException
:
(
('-keepclassmembers' keepModifier=keepOptionModifier classSpec=classSpecification {GrammarActions.addKeepClassMembers($flags, $classSpec.classSpec, $keepModifier.modifier);})
| ('-keepclasseswithmembers' keepModifier=keepOptionModifier classSpec=classSpecification {GrammarActions.addKeepClassesWithMembers($flags, $classSpec.classSpec, $keepModifier.modifier);})
| ('-keep' keepModifier=keepOptionModifier classSpec=classSpecification {GrammarActions.addKeepClassSpecification($flags, $classSpec.classSpec, $keepModifier.modifier);})
| '-dontshrink' {$flags.setShrink(false);}
| '-dontoptimize' {$flags.setOptimize(false);}
| '-dontpreverify' {$flags.setPreverify(false);}
| ('-keepclassmembernames' classSpec=classSpecification {GrammarActions.addKeepClassMembers($flags, $classSpec.classSpec, new KeepModifier().setAllowShrinking());})
| ('-keepclasseswithmembernames' classSpec=classSpecification {GrammarActions.addKeepClassesWithMembers($flags, $classSpec.classSpec, new KeepModifier().setAllowShrinking());})
| ('-keepnames' classSpec=classSpecification {GrammarActions.addKeepClassSpecification($flags, $classSpec.classSpec, new KeepModifier().setAllowShrinking());})
| '-dontobfuscate' {$flags.setObfuscate(false);}
| ('-include'|'@') proguardFile=NAME {GrammarActions.parse($proguardFile.text, baseDirectory, $flags);}
| ('-basedirectory' baseDir=NAME {baseDirectory=$baseDir.text;})
| '-injars' inJars=classpath {GrammarActions.inJars($flags, baseDirectory, $inJars.text);}
| '-outjars' outJars=classpath {GrammarActions.outJars($flags, baseDirectory, $outJars.text);}
| '-libraryjars' libraryJars=classpath {GrammarActions.libraryJars($flags, baseDirectory, $libraryJars.text);}
| ('-applymapping' mapping=NAME {GrammarActions.mapping($flags, baseDirectory, $mapping.text);})
| ('-keepattributes' {List<FilterSpecification> attribute_filter = new ArrayList<FilterSpecification>();} filter[attribute_filter, FilterSeparator.ATTRIBUTE] {GrammarActions.attributeFilter($flags, attribute_filter);})
| '-keepparameternames' {$flags.setKeepParameterNames(true);}
| '-obfuscationdictionary' obfuscationDictionary=NAME {GrammarActions.obfuscationDictionary($flags, baseDirectory, $obfuscationDictionary.text);}
| '-classobfuscationdictionary' classObfuscationDictionary=NAME {GrammarActions.classObfuscationDictionary($flags, baseDirectory, $classObfuscationDictionary.text);}
| '-packageobfuscationdictionary' packageObfuscationDictionary=NAME {GrammarActions.packageObfuscationDictionary($flags, baseDirectory, $packageObfuscationDictionary.text);}
| '-printmapping' outputMapping=NAME? {GrammarActions.outputMapping($flags, baseDirectory, $outputMapping.text);}
| ('-keeppackagenames' {List<FilterSpecification> package_filter = new ArrayList<FilterSpecification>();} filter[package_filter, FilterSeparator.GENERAL] {GrammarActions.packageFilter($flags, package_filter);})
| ('-repackageclasses' ('\'' newPackage=NAME? '\'')? {GrammarActions.repackageClasses($flags, $newPackage.text); newPackage = null;})
| ('-flattenpackagehierarchy' ('\'' newPackage=NAME? '\'')? {GrammarActions.flattenPackageHierarchy($flags, $newPackage.text); newPackage = null;})
| '-dontusemixedcaseclassnames' {GrammarActions.dontUseMixedCaseClassnames($flags);}
| '-useuniqueclassmembernames' {GrammarActions.useUniqueClassMemberNames($flags);}
| ('-adaptclassstrings' {List<FilterSpecification> filter = new ArrayList<FilterSpecification>();} filter[filter, FilterSeparator.GENERAL] {GrammarActions.adaptClassStrings($flags, filter);})
| ('-printseeds' seedOutputFile=NAME? {GrammarActions.printseeds($flags, baseDirectory, $seedOutputFile.text);})
| ('-adaptresourcefilenames' {List<FilterSpecification> file_filter = new ArrayList<FilterSpecification>();} filter[file_filter, FilterSeparator.FILE] {GrammarActions.adaptResourceFileNames($flags, file_filter);})
| ('-renamesourcefileattribute' sourceFile=NAME? {GrammarActions.renameSourcefileAttribute($flags, $sourceFile.text);})
| ('-adaptresourcefilecontents' {List<FilterSpecification> file_filter = new ArrayList<FilterSpecification>();} filter[file_filter, FilterSeparator.FILE] {GrammarActions.adaptResourceFileContents($flags, file_filter);})
| unFlag=unsupportedFlag {GrammarActions.printUnsupportedFlag($unFlag.text);}
)*
EOF
;
catch [RecognitionException e] {
throw e;
}
private unsupportedFlag
:
('-skipnonpubliclibraryclasses'
| '-dontskipnonpubliclibraryclasses'
| '-dontskipnonpubliclibraryclassmembers'
| ('-keepdirectories' {List<FilterSpecification> directory_filter = new ArrayList<FilterSpecification>();} filter[directory_filter, FilterSeparator.FILE])
| ('-target' NAME) //version
| '-forceprocessing'
| ('-printusage' NAME) //[filename]
| ('-whyareyoukeeping' classSpecification)
| ('-optimizations' {List<FilterSpecification> optimization_filter = new ArrayList<FilterSpecification>();} filter[optimization_filter, FilterSeparator.GENERAL])
| ('-optimizationpasses' NAME) //n
| ('-assumenosideeffects' classSpecification)
| '-allowaccessmodification'
| '-mergeinterfacesaggressively'
| '-overloadaggressively'
| '-microedition'
| '-verbose'
| ('-dontnote' {List<FilterSpecification> class_filter = new ArrayList<FilterSpecification>();} filter[class_filter, FilterSeparator.CLASS])
| ('-dontwarn' {List<FilterSpecification> class_filter = new ArrayList<FilterSpecification>();} filter[class_filter, FilterSeparator.CLASS])
| '-ignorewarnings'
| ('-printconfiguration' NAME?) //[filename]
| ('-dump' NAME?) //[filename]
)
;
private classpath
: NAME ((':'|';') classpath)?
;
private filter [List<FilterSpecification> filter, FilterSeparator format]
:
nonEmptytFilter[filter, format]
| {GrammarActions.filter($filter, false, "**", format);}
;
private nonEmptytFilter [List<FilterSpecification> filter, FilterSeparator separator]
@init {
boolean negator = false;
}
:
((NEGATOR {negator=true;})? NAME {GrammarActions.filter($filter, negator, $NAME.text, separator);} (','
nonEmptytFilter[filter, separator])?)
;
private classSpecification returns [ClassSpecification classSpec]
@init{
ModifierSpecification modifier = new ModifierSpecification();
}
:
(annotation)?
cType=classModifierAndType[modifier]
classNames {classSpec = GrammarActions.classSpec($classNames.names, cType,
$annotation.annotSpec, modifier);}
(inheritanceSpec=inheritance {classSpec.setInheritance(inheritanceSpec);})?
members[classSpec]?
;
private classNames returns [List<NameSpecification> names]
@init{
names = new ArrayList<NameSpecification>();
}
:
firstName=className {names.add($firstName.nameSpec);}
(',' otherName=className {names.add($otherName.nameSpec);} )*
;
private className returns [NameSpecification nameSpec]
@init{
boolean hasNameNegator = false;
}
:
(NEGATOR {hasNameNegator = true;})?
NAME {nameSpec=GrammarActions.className($NAME.text, hasNameNegator);}
;
private classModifierAndType[ModifierSpecification modifier] returns [ClassTypeSpecification cType]
@init{
boolean hasNegator = false;
}
:
(NEGATOR {hasNegator = true;})?
(
'public' {GrammarActions.addAccessFlag(modifier, AccessFlags.PUBLIC, hasNegator);} cmat=classModifierAndType[modifier] {cType = $cmat.cType;}
| 'abstract' {GrammarActions.addModifier(modifier, Modifier.ABSTRACT, hasNegator);} cmat=classModifierAndType[modifier] {cType = $cmat.cType;}
| 'final' {GrammarActions.addModifier(modifier, Modifier.FINAL, hasNegator);} cmat=classModifierAndType[modifier] {cType = $cmat.cType;}
| '@' {GrammarActions.addModifier(modifier, Modifier.ANNOTATION, hasNegator);} cmat=classModifierAndType[modifier] {cType = $cmat.cType;}
| classType {cType=GrammarActions.classType($classType.type, hasNegator); }
)
;
private classType returns [TypeEnum type]
:
'interface' {$type = TypeEnum.INTERFACE;}
| 'enum' {$type = TypeEnum.ENUM;}
| 'class' {$type = TypeEnum.CLASS;}
;
private members [ClassSpecification classSpec]
:
'{'
member[classSpec]*
'}'
;
private member [ClassSpecification classSpec]
:
annotation? modifiers
(
(typeSig=type)? name=(NAME|'<init>') (signature=arguments {GrammarActions.method(classSpec, $annotation.annotSpec, typeSig, $name.text, signature, $modifiers.modifiers);}
| {assert $name != null; GrammarActions.fieldOrAnyMember(classSpec, $annotation.annotSpec, typeSig, $name.text, $modifiers.modifiers, $name.getInputStream());})
| '<methods>' {GrammarActions.method(classSpec, $annotation.annotSpec,
GrammarActions.getSourceNamePattern("***", 0), "*", "\\("+ GrammarActions.getSourceNamePattern("...", 0) + "\\)",
$modifiers.modifiers);}
| fields='<fields>' {GrammarActions.field(classSpec, $annotation.annotSpec, null, "*", $modifiers.modifiers, $fields.getInputStream());}
) ';'
;
private annotation returns [AnnotationSpecification annotSpec]
@init{
boolean hasNameNegator = false;
}
: '@' (NEGATOR {hasNameNegator = true;})? NAME {$annotSpec = GrammarActions.annotation($NAME.text, hasNameNegator);};
private modifiers returns [ModifierSpecification modifiers]
@init{
modifiers = new ModifierSpecification();
}
:
modifier[modifiers]*
;
private modifier [ModifierSpecification modifiers]
@init{
boolean hasNegator = false;
}
:
(NEGATOR {hasNegator = true;})?
(
'public' {modifiers.addAccessFlag(AccessFlags.PUBLIC, hasNegator);}
| 'private' {modifiers.addAccessFlag(AccessFlags.PRIVATE, hasNegator);}
| 'protected' {modifiers.addAccessFlag(AccessFlags.PROTECTED, hasNegator);}
| 'static' {modifiers.addModifier(Modifier.STATIC, hasNegator);}
| 'synchronized' {modifiers.addModifier(Modifier.SYNCHRONIZED, hasNegator);}
| 'native' {modifiers.addModifier(Modifier.NATIVE, hasNegator);}
| 'abstract' {modifiers.addModifier(Modifier.ABSTRACT, hasNegator);}
| 'strictfp' {modifiers.addModifier(Modifier.STRICTFP, hasNegator);}
| 'final' {modifiers.addModifier(Modifier.FINAL, hasNegator);}
| 'transient' {modifiers.addModifier(Modifier.TRANSIENT, hasNegator);}
| 'synthetic' {modifiers.addModifier(Modifier.SYNTHETIC, hasNegator);}
| 'bridge' {modifiers.addModifier(Modifier.BRIDGE, hasNegator);}
| 'varargs' {modifiers.addModifier(Modifier.VARARGS, hasNegator);}
| 'volatile' {modifiers.addModifier(Modifier.VOLATILE, hasNegator);}
)
;
private inheritance returns [InheritanceSpecification inheritanceSpec]
@init{
boolean hasNameNegator = false;
}
:
('extends' | 'implements')
annotation? (NEGATOR {hasNameNegator = true;})? NAME {inheritanceSpec = GrammarActions.createInheritance($NAME.text, hasNameNegator, $annotation.annotSpec);};
private arguments returns [String signature]
:
'(' {signature = "\\(";}
(
(
parameterSig=type {signature += $parameterSig.typeSourceNamePattern;}
(',' parameterSig=type {signature += ", " + $parameterSig.typeSourceNamePattern;})*
)?
)
')' {signature += "\\)";}
;
private type returns [String typeSourceNamePattern]
@init {
int dim = 0;
}
:
(
typeName=('%' | NAME) ('[]' {dim++;})* {String sig = $typeName.text; typeSourceNamePattern = GrammarActions.getSourceNamePattern(sig == null ? "" : sig, dim);}
)
;
private keepOptionModifier returns [KeepModifier modifier]
@init {
modifier = new KeepModifier();
}
: (','
('allowshrinking' {modifier.setAllowShrinking();}
| 'allowoptimization' // Optimizations not supported
| 'allowobfuscation' {modifier.setAllowObfuscation();}))*
;
private NAME : ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'?'|'$'|'.'|'*'|'/'|'\\'|'-'|'+'|'<'|'>'|':'|'~')+ ;
LINE_COMMENT
: '#' ~( '\r' | '\n' )* {$channel=HIDDEN;}
;
private WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;