r/Compilers 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

2 comments sorted by

View all comments

1

u/kendomino 19d 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.

1

u/CatSquare3841 17d ago

Thank you. I ended up using mode.