如何合并两个AST?

j3d*_*j3d 5 java parsing antlr abstract-syntax-tree lexer

我正在尝试实现一个合并某些源代码的不同版本的工具.给定相同源代码的两个版本,想法是解析它们,生成相应的抽象源树(AST),最后将它们合并到单个输出源中,保持语法一致性 - 词法分析器和解析器是ANTLR的问题:如何跳过多行注释.

我知道有一流的ParserRuleReturnScope帮助...但getStop()getStart()始终返回null :-(

这是一个片段,说明了我如何修改我的perser来打印规则:

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

...
Run Code Online (Sandbox Code Playgroud)

use*_*210 0

解析器代码中的调用log(retval)看起来像是将在规则末尾发生,但事实并非如此。您需要将呼叫移至一个@after块中。

我改为log吐出一条消息以及范围信息,并将对其的调用添加到我自己的语法中,如下所示:

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

解析测试输入产生以下输出:

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
Run Code Online (Sandbox Code Playgroud)

块中的调用after已填充stoptree字段。

我不能说这是否会帮助您使用合并工具,但我认为这至少会让您解决半填充范围对象的问题。