【问题标题】:How to use antlr4 to analyze the grammar of .aidl files?如何使用antlr4分析.aidl文件的语法?
【发布时间】:2020-05-10 07:17:06
【问题描述】:

其实我是被指派分析.aidl文件的语法,用监听方法提取语法元素的。

为了完成这个,我想了很久,终于搞定了一个.g4文件。

grammar aidl3;
file  : pack* imp* parcelable? interfa? ;

pack : 'package' WS+ PAC_NAME WS* ';' WS* ;

imp : 'import'  WS+ IMP_NAME WS*  ';' WS*  ;

parcelable : 'parcelable' WS+  PARCE_NAME WS*  ';'  WS* ;

interfa :  INTER_TAG? WS* 'interface' WS+ INTER_NAME WS* '{' WS* methods+ WS* '}' WS*; 

methods :  RETURN_TYPE WS+  METHOD_NAME WS* '(' WS* argmentsa* WS* argmentsb* WS* ')' WS* ';' WS* ;

argmentsa : TAG? WS* ARG_TYPE WS+ ARG_NAME WS* ',' WS* ;

argmentsb : TAG? WS* ARG_TYPE WS+ ARG_NAME WS* ;



PAC_NAME : ~[; \n\r]+ ; 
//PAC_NAME : [_a-zA-Z] [_.a-zA-Z0-9]* ;
IMP_NAME : ~[ ;\n\r]+ ;

PARCE_NAME : ~[ ;\n\r.]+ ;

INTER_TAG : 'oneway';

INTER_NAME : ~[ ;\n\r{.]+ ;

RETURN_TYPE : ~[ ;\n\r.]+ ;

METHOD_NAME : ~[ ;\n\r(]+ ;

TAG : 'in' | 'out' | 'inout' ;

//ARG_TYPE : ~[) ,\n\r]+ ;

ARG_TYPE : [a-zA-Z] ~' '* | [a-zA-Z] ~' '* ' ' '[' ']' ;

ARG_NAME : ~[ ,\n\r).]+ ;

WS: [ \t\n\r];

但是,我遇到了一个奇怪的问题:那就是当我尝试分析 .aidl 文件时,例如

package android.view.accessibility;
oneway interface IAccessibilityInteractionConnection {
    void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, in Region bounds,
        int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
        int interrogatingPid, long interrogatingTid, in MagnificationSpec spec);
    void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, String viewId,
        in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback,
        int flags, int interrogatingPid, long interrogatingTid, in MagnificationSpec spec);
    void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, in Region bounds,
        int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
        int interrogatingPid, long interrogatingTid, in MagnificationSpec spec);
    void findFocus(long accessibilityNodeId, int focusType, in Region bounds, int interactionId,
        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
        long interrogatingTid, in MagnificationSpec spec);
    void focusSearch(long accessibilityNodeId, int direction, in Region bounds, int interactionId,
        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
        long interrogatingTid, in MagnificationSpec spec);
    void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
        int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
        int interrogatingPid, long interrogatingTid);
}

它会给出这个输出:

[@0,0:6='package',<'package'>,1:0]
[@1,7:7=' ',<WS>,1:7]
[@2,8:41='android.view.accessibility;\noneway',<ARG_TYPE>,1:8]
[@3,42:42=' ',<WS>,2:6]
[@4,43:51='interface',<'interface'>,2:7]
[@5,52:52=' ',<WS>,2:16]
[@6,53:87='IAccessibilityInteractionConnection',<PAC_NAME>,2:17]
[@7,88:88=' ',<WS>,2:52]
[@8,89:89='{',<'{'>,2:53]
[@9,90:90='\n',<WS>,2:54]
[@10,91:91=' ',<WS>,3:0]
[@11,92:92=' ',<WS>,3:1]
[@12,93:93=' ',<WS>,3:2]
[@13,94:94=' ',<WS>,3:3]
[@14,95:98='void',<PAC_NAME>,3:4]
[@15,99:99=' ',<WS>,3:8]
[@16,100:146='findAccessibilityNodeInfoByAccessibilityId(long',<PAC_NAME>,3:9]
[@17,147:147=' ',<WS>,3:56]
[@18,148:167='accessibilityNodeId,',<PAC_NAME>,3:57]

...

您可以在输出第 3 行 '[@2,8:41='android.view.accessibility;\noneway',ARG_TYPE,1:8]' 中看到,其中表达式 'pack' 使用 'ARG_TYPE'匹配'android.view.accessibility;\noneway'。但是..怎么可能? 'ARG_TYPE' 从未出现在表达式 'pack' 中,它应该使用 'PAC_NAME' 来匹配 'android.view.accessibility'

如果有人能帮我解决这个问题,那就太好了,因为我面临着最后期限。 事实上,我只是一个新手,我知道我的 g4 文件看起来不太好,所以如果可能的话,你能告诉我如何更好地为 .aidl 编写 g4 吗?或者甚至给我看写答案?

如果您能帮助我,我将不胜感激!谢谢!

【问题讨论】:

  • 欢迎来到 StackOverflow。您能否具体说明您如何称呼 antlr4?我无法重现你得到的输出。
  • 我可以重现它。

标签: parsing antlr antlr4 lexer aidl


【解决方案1】:

ANTLR 的词法分析器尝试使用尽可能多的字符创建标记。由于ARG_TYPE 能够匹配android.view.accessibility;\noneway(并且没有其他规则可以匹配更多字符),因此创建了ARG_TYPE 令牌。只有当 2 个或多个规则匹配相同的字符时,ANTLR 才会选择第一个定义的。

您必须了解,词法分析器不会根据解析器尝试匹配的内容创建标记。标记化是一个独立于解析阶段完成的过程。因此,大多数看起来像 ~[ ;\n\r(]+ 的规则都太宽泛了。

我建议您查看 an existing Java grammar,并使用它来处理 AIDL 文件。

编辑

如果我把上面贴的语法文件,改一下:

formalParameter
    :   variableModifier* unannType variableDeclaratorId
    ;

进入:

formalParameter
    :   'in'? variableModifier* unannType variableDeclaratorId
    ;

并改变:

interfaceModifier
    :   annotation
    |   'public'
    |   'protected'
    |   'private'
    |   'abstract'
    |   'static'
    |   'strictfp'
    ;

进入:

interfaceModifier
    :   annotation
    |   'public'
    |   'protected'
    |   'private'
    |   'abstract'
    |   'static'
    |   'strictfp'
    |   'oneway'
    ;

然后您的示例文件解析正确。

【讨论】:

    猜你喜欢
    • 2018-12-20
    • 2014-02-23
    • 1970-01-01
    • 1970-01-01
    • 2014-03-02
    • 1970-01-01
    • 2015-04-19
    • 2022-01-09
    • 1970-01-01
    相关资源
    最近更新 更多