2

公に使用されている製品の DSL 文法を変更しています。現在、すべての/*...*/コメントは黙って無視されていますが、特定の重要な要素の前に配置されたコメントが AST に解析されるように変更する必要があります。ユーザーが DSL 全体で任意にコメントを追加でき、それらの重要なコメントのみが含まれるように、下位互換性を維持する必要があります。

現在、パーサーの文法は次のようになっています。

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();}

「グラフ」要素と「状態」要素の前に配置されたコメントには、意味のある説明と注釈が含まれており、解析された AST 内に含める必要があります。したがって、これら 2 つのルールを変更し、COMMENT をスキップしなくなりました。

graph: comment* 'graph' ID '{' graph_body '}';
state: comment* 'state' ID '{' state_body '}';
COMMENT: '/*' ( options {greedy=false;} : . )* '*/'

上記を素朴に使用すると、後でツリーパーサーを実行するときに、他のコメントによってトークンの不一致エラーが発生します。「グラフ」または「状態」の前に配置されていない COMMENT のすべてのインスタンスを無視するにはどうすればよいですか?

DSL の例は次のようになります。

/* 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 */
}
4

3 に答える 3

1

これは私が実際に働いている解決策です。フィードバックをお待ちしています。

基本的な考え方は、HIDDEN チャネルにコメントを送信し、それらを必要な場所に手動で抽出し、必要に応じて書き換えルールを使用してコメントを再挿入することです。抽出手順は、http ://www.antlr.org/wiki/pages/viewpage.action?pageId=557063 の情報に着想を得ています。

文法は次のとおりです。

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;}
于 2012-04-17T04:07:30.557 に答える
0

これはうまくいきますか?

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();}
于 2012-04-16T13:56:50.413 に答える
0

「グラフ」または「状態」の前に配置されていない COMMENT のすべてのインスタンスを無視するにはどうすればよいですか?

コメントを閉じた後に、 または のどちらかが先にあるかどうかを確認することで、それを行うことができます。間にオプションのスペースがいくつかあります。この場合は何もしないでください。そうでない場合は、述語が失敗しルールに違反して、単にコメント トークンになります。"*/"'graph''state'skip()

ANTLR 構文では、次のようになります。

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;}

また、呼び出されたときにメソッドを実行するため、ルールでは使用SPACESしないことに注意してください。COMMENTSPACESskip()

于 2012-04-16T15:23:44.377 に答える