5

いくつかのソースコードの異なるバージョンをマージするためのツールを実装しようとしています。同じソースコードの2つのバージョンがある場合、それらを解析し、それぞれの抽象ソースツリー(AST)を生成し、最後に文法の一貫性を維持しながら単一の出力ソースにマージするというアイデアがあります。レクサーとパーサーはANTLRの質問です。複数行のコメントをスキップする方法

ParserRuleReturnScope私は助けるクラスがあることを知っています...しかしgetStop()そしてgetStart()常にnullを返します:-(

これは、ルールを印刷するためにパーサーを変更した方法を示すスニペットです。

parser grammar CodeTableParser;

options {
    tokenVocab = CodeTableLexer;
    backtrack = true;
    output = AST;
}

@header {
    package ch.bsource.ice.parsers;
}

@members {
    private void log(ParserRuleReturnScope rule) {
        System.out.println("Rule: " + rule.getClass().getName());
        System.out.println("    getStart(): " + rule.getStart());
        System.out.println("    getStop(): " + rule.getStop());
        System.out.println("    getTree(): " + rule.getTree());
    }
}

parse
    : codeTabHeader codeTable endCodeTable eof { log(retval); }
    ;

codeTabHeader
    : comment CodeTabHeader^ { log(retval); }
    ;

...
4

2 に答える 2

1

ASTがあると仮定すると(最初から取得するのが難しい場合が多く、実際の言語の解析は見た目よりも難しい場合が多い)、最初にASTの共通点を特定し、その情報を収集するマッピングを作成する必要があります。それは見た目ほど簡単ではありません。移動したが、「共通」とまったく同じサブツリーであるコードのブロックを数えますか?識別子の一貫した名前変更を除いて同じである2つのサブツリーはどうですか?変更されたコメントはどうですか?(ほとんどのASTはコメントを失います。ほとんどのプログラマーは、これは本当に悪い考えだと思います)。

「最長の共通部分文字列」アルゴリズムのバリエーションを作成して、ツリーを比較できます。私が作成したツールでそれを使用しました。

最後に、ツリーをマージした後、テキストを再生成する必要があります。理想的には、元のコードのレイアウトのほとんどを保持します。(プログラマーは、彼らがとても愛情を込めて作成したレイアウトを変更することを嫌います)。したがって、ASTは位置情報をキャプチャする必要があり、再生は可能な限りそれを尊重する必要があります。

于 2012-11-11T22:16:40.657 に答える
0

パーサーコードでのへの呼び出しlog(retval)は、ルールの最後で発生するように見えますが、そうではありません。呼び出しを@afterブロックに移動する必要があります。

logメッセージとスコープ情報を吐き出すように変更し、次のように自分の文法に呼び出しを追加しました。

script    
    @init {log("@init", retval);}
    @after {log("@after", retval);}
    : statement* EOF  {log("after last rule reference", retval);} 
        -> ^(STMTS statement*) 
    ;

テスト入力を解析すると、次の出力が生成されました。

Logging from @init
    getStart(): [@0,0:4='Print',<10>,1:0]
    getStop(): null
    getTree(): null
Logging from after last rule reference
    getStart(): [@0,0:4='Print',<10>,1:0]
    getStop(): null
    getTree(): null
Logging from @after
    getStart(): [@0,0:4='Print',<10>,1:0]
    getStop(): [@4,15:15='<EOF>',<-1>,1:15]
    getTree(): STMTS

afterブロック内の呼び出しには、フィールドstoptreeフィールドの両方が入力されています。

これがマージツールに役立つかどうかはわかりませんが、少なくとも、半分入力されたスコープオブジェクトの問題を乗り越えることができると思います。

于 2012-10-19T07:53:38.373 に答える