使用解析器的OData v4的语法(Using parser for OData v4 gramma

2019-10-29 03:23发布

我尝试使用由OASIS组提供Antlr4的OData的V4语法。 请参阅以下链接: https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/grammar/ANTLR/#_trunk_spec_grammar_ANTLR_

根据这些文件,并ANTLR的V4 Maven插件,我成功生成类分析的OData网址。

我尝试使用的解析器,如下所述:

String expression = "http://192.168.1.1/odata/Category(1)/Products?$top=2&$orderby=name";
ANTLRInputStream in = new ANTLRInputStream(expression);

ODataParserLexer lexer = new ODataParserLexer(in);
ODataParserParser parser = new ODataParserParser(
            new CommonTokenStream(lexer));

ODataErrorListener errorListener = new ODataErrorListener();
parser.addErrorListener(errorListener);

ODataParseListener listener = new ODataParseListener();
parser.addParseListener(listener);

OdataUriContext ctx = parser.odataUri();

当调用方法odataUri,我在错误监听报告了以下错误:

line 1:66 mismatched input '<EOF>' expecting Protocol

这是奇怪的,因为词法分析器是能够得到令牌的字符串进行解析:

"http" 
"://" 
"192.168.1.1" 
"/" 
"odata" 
"/" 
"Category" 
"(" 
"1" 
")" 
"/" 
"Products" 
"?" 
"$top" 
"=" 
"2" 
"&" 
"$orderby" 
"=" 
"name"

也许方法odataUri不是一个对解析器调用。 但看了解析器语法文件后,它似乎是这样的。

- 编辑在12/01

我发现有一个规则名称的问题:

odataUri : Protocol ColSlaSla host ( COLON port )?
       serviceRoot
       ( ODataSignal_METADATA | ODataSignal_BATCH | odataRelativeUri )? EOF;

Protocol :  

规则Protocol无法找到。 如果我更新了它的名字protocol ,这是好多了...

继巴特的建议下,我打印的代币相关规则的名称。 随着与Antlr4 Maven插件生成的,我不能得到正确的。 随着一代经典,我有这样的:

"http" 
    index = 93, ODataParserLexer.tokenNames[index] = HTTPORHTTPS
"://" 
    index = 92, ODataParserLexer.tokenNames[index] = ColSlaSla
"192.168.1.1" 
    index = 23, ODataParserLexer.tokenNames[index] = Ls32
"/" 
    index = 60, ODataParserLexer.tokenNames[index] = '/'
"odata" 
    index = 4, ODataParserLexer.tokenNames[index] = 'odata'
"/" 
    index = 60, ODataParserLexer.tokenNames[index] = '/'
"Category" 
    index = 251, ODataParserLexer.tokenNames[index] = ODATA_ID_CHAR8
"(" 
    index = 28, ODataParserLexer.tokenNames[index] = SubDelims
"1" 
    index = 25, ODataParserLexer.tokenNames[index] = DecOctet
")" 
    index = 28, ODataParserLexer.tokenNames[index] = SubDelims
"/" 
    index = 60, ODataParserLexer.tokenNames[index] = '/'
"Products" 
    index = 251, ODataParserLexer.tokenNames[index] = ODATA_ID_CHAR8
"?" 
    index = 66, ODataParserLexer.tokenNames[index] = '?'
"$top" 
    index = 128, ODataParserLexer.tokenNames[index] = ODataSignal_TOP
"=" 
    index = 28, ODataParserLexer.tokenNames[index] = SubDelims
"2" 
    index = 25, ODataParserLexer.tokenNames[index] = DecOctet
"&" 
    index = 28, ODataParserLexer.tokenNames[index] = SubDelims
"$orderby" 
    index = 126, ODataParserLexer.tokenNames[index] = ODataSignal_ORDERBY
"=" 
    index = 28, ODataParserLexer.tokenNames[index] = SubDelims
"name" 
    index = 250, ODataParserLexer.tokenNames[index] = ODATA_ID_CHAR4

令牌和关联规则似乎是正确的。

我还启用了解析器(跟踪parser.setTrace(true) ),并再次执行我的代码。 我仍然有一个错误

enter   odataUri, LT(1)=<EOF>
enter   protocol, LT(1)=<EOF>
line 1:66 mismatched input '<EOF>' expecting HTTPORHTTPS
------------
Error on query : 
null
=> line 1 : mismatched input '<EOF>' expecting HTTPORHTTPS
Context : [590]
exit    protocol, LT(1)=<EOF>
exit    odataUri, LT(1)=<EOF>

非常感谢您的帮助。 蒂埃里

Answer 1:

指定的语法有很多不明确的匹配,需要进行重写,以消除可能使用语义谓词或词法分析器模式暧昧匹配。 对于expamle(我重写语法规则开始):

odataUri : serviceRoot? EOF  ;

serviceRoot : Protocol host segments relative? # OnSerivceRoot ;

segments    : Segments ;

host         : (addr | regName) port?;
addr         : ColSlaSla IPv4address ;

regName      : HOST ;

port          : PortDef ;

relative : (ODataSignal_METADATA | ODataSignal_BATCH) | odataRelativeUri;

odataRelativeUri : resourcePath ( question queryOptions )?;
question : QUESTION ;


PortDef     : COLON Digits ;
Segments    : SLASH ((Unreserved | PctEncoded | SubDelims | COLON | AT_SIGN)+ SLASH)* ;
HOST         : ColSlaSla HOST_DEF ;
HOST_DEF     : (Unreserved | PctEncoded | SubDelims)+ ;
QUESTION : '?';
Protocol :  HttpOrHttpsAnyCase;
Digits  : Digit+ ;
Digit  : [0-9] ;
Alpha  : [a-zA-Z];


文章来源: Using parser for OData v4 grammar