首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >antlr v3上下文感知条件注释包含

antlr v3上下文感知条件注释包含
EN

Stack Overflow用户
提问于 2012-04-16 12:49:56
回答 3查看 202关注 0票数 2

我正在修改一个公共使用的产品的DSL语法。目前,所有的/*...*/注释都被默默地忽略了,但是我需要修改它,以便将放置在某些关键元素之前的注释解析到AST中。我需要保持向后兼容性,这样用户仍然可以在整个DSL中随意添加注释,并且只包括那些关键注释。

解析器语法目前看起来有点像这样:

代码语言:javascript
复制
grammar StateGraph;
graph: 'graph' ID '{' graph_body '}';
graph_body: state+;
state: 'state' ID '{' state_body '}';
state_body: transition* ...etc...; 
transition: 'transition' (transition_condition) ID ';';
COMMENT: '/*' ( options {greedy=false;} : . )* '*/' {skip();}

放置在“graph”和“state”元素之前的注释包含有意义的描述和注释,需要包含在已解析的AST中。所以我已经修改了这两条规则,不再跳过评论:

代码语言:javascript
复制
graph: comment* 'graph' ID '{' graph_body '}';
state: comment* 'state' ID '{' state_body '}';
COMMENT: '/*' ( options {greedy=false;} : . )* '*/'

如果我天真地使用上面的注释,那么在随后执行树解析器时,其他注释会导致不匹配的令牌错误。如何忽略没有放在'graph‘或'state’前面的所有注释实例?

DSL示例如下:

代码语言:javascript
复制
/* Some description
 * @some.meta.info
 */
graph myGraph {
  /* Some description of the state.
   * @some.meta.info about the state
   */
  state first {
    transition if (true) second; /* this comment ignored */
  }

  state second {
  }

  /* this comment ignored */
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-04-17 12:07:31

这就是我实际得到的解决方案。我希望得到反馈。

基本思想是将注释发送到隐藏通道,在我想要它们的地方手动提取它们,并使用重写规则在需要的地方重新插入注释。提取步骤的灵感来自这里的信息:http://www.antlr.org/wiki/pages/viewpage.action?pageId=557063

现在的语法是:

代码语言:javascript
复制
grammar StateGraph;

@tokens { COMMENTS; }

@members {
// matches comments immediately preceding specified token on any channel -> ^(COMMENTS COMMENT*)
CommonTree treeOfCommentsBefore(Token token) {
    List<Token> comments = new ArrayList<Token>();
    for (int i=token.getTokenIndex()-1; i >= 0; i--) {
       Token t = input.get(i);
       if (t.getType() == COMMENT) {
          comments.add(t);
       }
       else if (t.getType() != WS) {
          break;
       }
    }
    java.util.Collections.reverse(comments);

    CommonTree commentsTree = new CommonTree(new CommonToken(COMMENTS, "COMMENTS"));
    for (Token t: comments) {
       commentsTree.addChild(new CommonTree(t));
    }
    return commentsTree;
}
}

graph
    : 'graph' ID '{' graph_body '}'
      -> ^(ID {treeOfCommentsBefore($start)} graph_body);
graph_body: state+;
state
    : 'state' ID '{' state_body '}'
      -> ^(ID {treeOfCommentsBefore($start)} staty_body);
state_body: transition* ...etc...; 
transition: 'transition' (transition_condition) ID ';';
COMMENT: '/*' .* '*/' {$channel=HIDDEN;}
票数 1
EN

Stack Overflow用户

发布于 2012-04-16 21:56:50

这对你有效吗?

代码语言:javascript
复制
grammar StateGraph;
graph: 'graph' ID '{' graph_body '}';
graph_body: state+;
state: .COMMENT 'state' ID '{' state_body '}';
state_body: .COMMENT transition* ...etc...; 
transition: 'transition' (transition_condition) ID ';';
COMMENT: '/*' ( options {greedy=false;} : . )* '*/' {skip();}
票数 0
EN

Stack Overflow用户

发布于 2012-04-16 23:23:44

如何忽略没有放在'graph‘或'state’前面的所有注释实例?

您可以在注释的结束"*/"之后检查前面是否有'graph''state',中间有一些可选的空格,这样就可以做到这一点。如果是这样的话,什么都不要做,如果不是这样的话,谓词就会失败,您就会违反规则,简单地skip()注释令牌。

在ANTLR语法中,如下所示:

代码语言:javascript
复制
COMMENT
 : '/*' .* '*/' ( (SPACE* (GRAPH | STATE))=> /* do nothing, so keep this token */ 
                | {skip();}                  /* or else, skip it               */ 
                )
 ;

GRAPH  : 'graph';
STATE  : 'state';
SPACES : SPACE+ {skip();};

fragment SPACE : ' ' | '\t' | '\r' | '\n';

请注意,默认情况下,.*.+是不贪婪的:不需要设置options{greedy=false;}

另外,要注意不要在COMMENT规则中使用SPACES,因为SPACES在被调用时会执行skip()方法!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10168844

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档