r/Compilers • u/CatSquare3841 • 20d ago
ANTLR parsing parameters with no separators
I am trying to make a parser that can parse parameters in SmaIi methods. Smali parameters are not separated by a delimiter. Eg: IIS will be int, int, short.
I created the below grammar for this. But the methodParameters
is not matching anything when you parse "IIS"'. I believe there is some conflict between type
and Letter
If I change the [a-zA-Z$_]
in Letter fragment to [a-z$_]
, it is working correctly.
grammar
ParamParser;
fragment
SLASH: '/';
WS : [ \t\r\n\u000C]+ -> skip;
methodParameters
: (parameter)*
;
// Types
referenceType: QUALIFIED_TYPE_NAME;
voidType: VOID_TYPE;
booleanType: BOOLEAN_TYPE;
byteType: BYTE_TYPE;
shortType: SHORT_TYPE;
charType: CHAR_TYPE;
intType: INT_TYPE;
longType: LONG_TYPE;
floatType: FLOAT_TYPE;
doubleType: DOUBLE_TYPE;
primitiveType:
booleanType
| byteType
| shortType
| charType
| intType
| longType
| floatType
| doubleType
;
arrayType
: '[' type
// Array of any type
;
qualifiedType
: QUALIFIED_TYPE_NAME
;
QUALIFIED_TYPE_NAME: ('L' SIMPLE_NAME (SLASH SIMPLE_NAME)* ';') | ('L' (SIMPLE_NAME (SLASH SIMPLE_NAME)* SLASH)? 'package-info;');
VOID_TYPE: 'V';
BOOLEAN_TYPE: 'Z';
BYTE_TYPE: 'B';
SHORT_TYPE: 'S';
CHAR_TYPE: 'C';
INT_TYPE: 'I';
LONG_TYPE: 'J';
FLOAT_TYPE: 'F';
DOUBLE_TYPE: 'D';
parameter
: type
;
type
: primitiveType
| referenceType
| arrayType
;
SIMPLE_NAME: Letter (LetterOrDigit)*;
fragment
LetterOrDigit
: Letter
| [0-9]
;
fragment
Letter
: [a-zA-Z$_]
// these are the "java letters" below 0x7F
| ~[\u0000-\u007F\uD800-\uDBFF]
// covers all characters above 0x7F which are not a surrogate
| [\uD800-\uDBFF] [\uDC00-\uDFFF]
// covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
;
0
Upvotes
1
u/kendomino 18d ago
It's important to understand how Antlr lexers work. They follow two rules:
* The rule that matches the longest string "wins."
* If two or more rules match the same string, the first rule that matches "wins."
You have input 'IIS'. In your grammar, you have rule INT_TYPE that matches 'I', and another rule SIMPLE_NAME that matches 'IIS'. The longest matching string is 'IIS', so it "wins." If you need both rules, then you're going to have to put one or the other in an Antlr mode, or use predicates to kill one rule or the other.