【问题标题】:ANTLR Template translator match part of grammarANTLR 模板翻译器匹配部分语法
【发布时间】:2011-11-04 03:12:21
【问题描述】:

我为一种语言编写了一个语法,现在我想处理一些语法糖结构,因为我正在考虑编写一个模板翻译器。

问题是我希望我的模板语法只翻译该语言的某些结构,其余部分保持原样。

例如:

我有这个作为输入:

class Main { 
   int a[10];
}

我想把它翻译成类似的东西:

class Main { 
   Array a = new Array(10);
}

理想情况下,我想在 ANTLR 中做一些这样的思考

grammer Translator
options { output=template;}

    decl 
         : TYPE  ID '[' INT ']' -> template(name = {$ID.text}, size ={$INT.text}) 
              "Array <name> = new Array(<size>);

我希望它保留与规则 decl 不匹配的其余输入。

在不编写语言的完整语法的情况下,如何在 ANTLR 中实现这一点?

【问题讨论】:

    标签: antlr antlr3 stringtemplate


    【解决方案1】:

    我会简单地在解析器语法中处理这些事情。

    假设您在解析器语法中构建 AST,我猜您将有一个规则来解析输入,例如 Array a = new Array(10);,类似于:

    decl
      :  TYPE ID '=' expr ';' -> ^(DECL TYPE ID expr)
      ;
    

    其中expr 最终匹配term,如下所示:

    term
      :  NUMBER
      |  'new' ID '(' (expr (',' expr)*)? ')' -> ^('new' ID expr*)
      |  ...
      ;
    

    为了说明你的简写声明int a[10];,你所要做的就是像这样扩展decl

    decl
      :  TYPE ID '=' expr     ';' -> ^(DECL TYPE    ID expr)
      |  TYPE ID '[' expr ']' ';' -> ^(DECL 'Array' ID ^(NEW ARRAY expr))
      ;
    

    这会将输入 int a[10]; 重写为以下 AST:

    这与为输入 Array a = new Array(10); 创建的 AST 完全相同。

    编辑

    这是一个小的工作演示:

    grammar T;
    
    options {
      output=AST;
    }
    
    tokens {
      ROOT;
      DECL;
      NEW='new';
      INT='int';
      ARRAY='Array';
    }
    
    parse
      :  decl+ EOF -> ^(ROOT decl+)
      ;
    
    decl
      :  type ID '=' expr     ';' -> ^(DECL type  ID expr)
      |  type ID '[' expr ']' ';' -> ^(DECL ARRAY ID ^(NEW ARRAY expr))
      ;
    
    expr
      :  Number
      |  NEW type '(' (expr (',' expr)*)? ')' -> ^(NEW ID expr*)
      ;
    
    type
      :  INT
      |  ARRAY
      |  ID
      ;
    
    ID     : ('a'..'z' | 'A'..'Z')+;
    Number : '0'..'9'+;
    Space  : (' ' | '\t' | '\r' | '\n') {skip();};
    

    可以用类测试:

    import org.antlr.runtime.*;
    import org.antlr.runtime.tree.*;
    import org.antlr.stringtemplate.*;
    
    public class Main {
      public static void main(String[] args) throws Exception {
        String src = "Array a = new Array(10); int a[10];";
        TLexer lexer = new TLexer(new ANTLRStringStream(src));
        TParser parser = new TParser(new CommonTokenStream(lexer));
        CommonTree tree = (CommonTree)parser.parse().getTree();
        DOTTreeGenerator gen = new DOTTreeGenerator();
        StringTemplate st = gen.toDOT(tree);
        System.out.println(st);
      }
    }
    

    【讨论】:

    • 我试过了,但是当我尝试在重写规则中传递一个字符串时,它会发出一个错误:在重写规则中引用未定义的标记:'Array' and same for 'new'跨度>
    • 其实语法是 TOKEN["literal"] 所以我需要做类似的事情: TYPE ID '[' expr ']' ';' -> ^(DECL TYPE["Array"] ID ^(NEW TYPE["Array"] expr))
    • @JohnRetallack,是的,我犯了一个错误:我在重写规则中使用了解析器规则中不存在的文字标记。我修复了它,并添加了一个工作示例。
    • @JohnRetallack,是的,干得好,T['text'] 也可以工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多