parsing - 如何使用antlr4分析.aidl文件的语法?
问题描述
实际上,我被指派分析 .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 吗?或者甚至给我看写答案?
如果您能帮助我,我将不胜感激!谢谢!
解决方案
ANTLR 的词法分析器尝试使用尽可能多的字符创建标记。并且由于ARG_TYPE
能够匹配android.view.accessibility;\noneway
(并且没有其他规则可以匹配更多字符),ARG_TYPE
因此创建了一个令牌。只有当 2 个或多个规则匹配相同的字符时,ANTLR 才会选择第一个定义的。
您必须了解词法分析器不会根据解析器尝试匹配的内容创建标记。标记化是一个独立于解析阶段完成的过程。因此,您的大多数规则看起来~[ ;\n\r(]+
都太宽泛了。
我建议您查看现有的 Java 语法,并使用它来处理 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'
;
那么您的示例文件将正确解析。
推荐阅读
- python-3.x - Python 3 通过 Raspberry Pi 上的 UDP 与子进程交互
- java - Spring 集成 DSL 关闭策略
- javascript - 为什么某些操作不适用于具有两个 CSS 类的元素?
- javascript - 承诺链
- python-3.x - TinyDb 在执行更新时缓存数据,但从不更新 json 文档
- flutter - CupertinoIndicator for refreshindicator Flutter
- javascript - 如何在 Mongo 查询中传递变量,例如 /variable/?
- c++ - 将 AT 命令字符串解析为整数
- reactjs - React.js - 无法将 DataRows 显示到 TBody
- sql - 从数据库更新 webclient 响应