最新消息:20210917 已从crifan.com换到crifan.org

【基本解决】用antlr匹配嵌套递归的代码

ANTLR crifan 2605浏览 0评论

【问题】

想要用antlr去实现匹配C语言代码。

其中有

{
xxx
    {
    xxx
    }
    xxx
}

 

之类的大括号的递归。

需要用antlr写对应的语法,去匹配此递归。

 

【解决过程】

1。关于递归,供参考的一些资料:

官网的:

Left-Recursion Removal – Print Edition

 

别人写的:

ANTLR analysis of recursive structures

 

2.貌似别人也可以正常实现递归的:

How to remove Left recursive in this ANTLR grammer?

 

3.经过折腾,暂时还未解决。

目前的语法是:

method_definition
	:	'DEFINITION' '{' eddl_c_code '}';
eddl_c_code
	:	( any_char | bracket_body)*;

any_char:	(options {greedy=true;} : (~('{' | '}'))+);

bracket_body
	:	'{' (bracket_body | any_char? ) '}';

 

4.参考:

ANTLR: how to parse a region within matching brackets with a lexer

去写了些代码:

eddl_c_code
//	:	( any_char | bracket_body)*;
	:	( any_char | bracket_body)*;

//any_char:	(options {greedy=true;} : (~('{' | '}')));
any_char:	(~('{' | '}'))+;

//bracket_body
//	:	'{'{depth++;} (any_char* | bracket_body )  '}';

bracket_body
@init{int depth = 1;}
	:	'{' 
		( {depth > 0}?=>              // keep reapeating `{ ... }*` as long as depth > 0
                     ( ~('{' | '}')           // match anything other than bracket
                     | '{'          {depth++;} // match a '{' in increase the var `open`
                     | '}'          {depth--;} // match a '}' in decrease the var `open`
                     )
                 )*;

但是结果编译debug代码时出错了。

结果发现parser中,没有对应的depth变量的定义,所以才出错的。

但是把bracket_body改为BRACKET_BODY,结果却又编译不通过。

有空继续参考该贴,去折腾,貌似可以去匹配嵌套的情况的。

 

5.后来的后来,无意间的折腾,使用:

eddl_c_code
	:	( any_char | bracket_body)+;

//any_char:	(options {greedy=true;} : (~('{' | '}')));
any_char:	(~('{' | '}'))+;

bracket_body
//	:	'{'{depth++;} (any_char* | bracket_body )  '}';
	:	'{' (any_char | bracket_body )+  '}';

竟然是可以正常识别那一堆的才代码了。

竟然没有再报错。

其中可见,使用加号’+’而不是星号’*’,会有个问题,那就是对于大括号内为空的情况,则是不允许的。

6.修改了一处的加号,变为星号,也是可以工作的:

eddl_c_code
	:	( any_char | bracket_body)+;

//any_char:	(options {greedy=true;} : (~('{' | '}')));
any_char:	(~('{' | '}'))+;

bracket_body
//	:	'{'{depth++;} (any_char* | bracket_body )  '}';
//	:	'{' (any_char | bracket_body )+  '}';
	:	'{' (any_char | bracket_body )*  '}';

 

7.最后改为:

method_definition
	:	'DEFINITION' '{' eddl_c_code '}';
eddl_c_code
//	:	( any_char | bracket_body)+;
	:	( any_char | bracket_body)*;

//any_char:	(options {greedy=true;} : (~('{' | '}')));
any_char:	(~('{' | '}'))+;

bracket_body
//	:	'{'{depth++;} (any_char* | bracket_body )  '}';
//	:	'{' (any_char | bracket_body )+  '}';
	:	'{' (any_char | bracket_body )*  '}';

也是可以正常工作的。

 

【总结】

好不容易,至少先让antlr的递归的语法,可以正常运行了。

注:

此处,还是会有些缺点,比如eddl_c_code和any_char会有多重匹配的问题,所以会有警告:

two rule has red warning

对应的提示为:

choose rule then can see detailed mutiple alternative

但是,至少暂时可以匹配到所有的C代码了。

转载请注明:在路上 » 【基本解决】用antlr匹配嵌套递归的代码

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
92 queries in 0.189 seconds, using 23.38MB memory