代码之家  ›  专栏  ›  技术社区  ›  Kevin Won

ANTLR:使用stringTemplate

  •  2
  • Kevin Won  · 技术社区  · 16 年前

    (我是安特尔的一个笨蛋)。。。我在用StringTemplates获取语法时遇到了困难。基本上我在写一点DSL。我可以按我想要的方式获取语法(语法解析正确),但无法生成目标代码来处理模板。下面是我的语法片段:

    grammar Pfig;
    
    options { 
        output=template;  
     language=CSharp2;
     }
    
    conf 
        : globalName
        ;
    
    
    globalName 
        : 'GlobalName:'  ID
         -> localConf(name ={$ID.text})
        ;
    

    现在,让我们在测试应用程序中启动解析器,让它处理一个输入文件。

    // C# processing a file with the lex/parser.
    // the 'app.pfig' file just has one line that reads 'GlobalName: Bla'
    using (FileStream fs = File.OpenRead("c:\\app.pfig"))
            {
                PfigParser parser = new PfigParser(new CommonTokenStream(
                    new PfigLexer(new ANTLRInputStream(fs))));
    
                using (TextReader tr = File.OpenText("./Pfig.stg"))
                {
                    parser.TemplateLib = new StringTemplateGroup(tr);
                }
    
                var parseResult = parser.conf();
                string code = parseResult.Template.ToString(); // Fail: template is null
            }
    

    我可以单步遍历解析器代码,看看它是否正确地标识了我的文本并正确地应用了stringTemplate

    如果我去掉语法中的'conf'规则,直接调用'globalName',它就会工作(因为它是堆栈中唯一的规则)。但我显然想要不止一条规则。我已经用Java生成了解析器,它做了同样的事情:

    // antlr generated parser code
    public PfigParser.conf_return conf() // throws RecognitionException [1]
    {   
        PfigParser.conf_return retval = new PfigParser.conf_return();
    
        try 
     {
            {
             PushFollow(FOLLOW_globalName_in_conf30);
             globalName(); // <- it calls globalName() but doesn't keep the return.
             state.followingStackPointer--;
    
            }
    
            retval.Stop = input.LT(-1);
    
        }
    
    // snip
    

    我很确定这是我的问题,但我不知道我做错了什么 ... 我所看到的示例并没有真正显示代码的真实模板发射。

    2 回复  |  直到 16 年前
        1
  •  2
  •   Akira    16 年前

    基本上,您需要显式地将模板输出转发到子规则:

    conf 
        : a=globalName -> {$a.st}
        ;
    

        2
  •  2
  •   Vasily Kirichenko    15 年前

    似乎我终于抓住了模板的想法:)模板应该“嵌套”到另一个层次结构。下面的示例可以很好地工作:

    模板测试g:

    grammar TemplatesTest;
    
    options
    {
        output=template;
        language=CSharp2;
    }
    
    ID  :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
        ;
    
    INT :   '0'..'9'+
        ;
    
    COMMENT
        :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
        |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
        ;
    
    WS  :   ( ' '
            | '\t'
            | '\r'
            | '\n'
            ) {$channel=HIDDEN;}
        ;
    
    STRING
        :  '\'' ( ESC_SEQ | ~('\\'|'\'') )* '\''
        ;
    
    fragment
    HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
    
    fragment
    ESC_SEQ
        :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
        |   UNICODE_ESC
        |   OCTAL_ESC
        ;
    
    fragment
    OCTAL_ESC
        :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
        |   '\\' ('0'..'7') ('0'..'7')
        |   '\\' ('0'..'7')
        ;
    
    fragment
    UNICODE_ESC
        :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
        ;
    
    doc
        : (e+=expr)+ -> doc(expressions={$e})
        ;
    
    expr
        : ID '=' INT -> expression(id={$ID.text}, value={$INT.text})
        ;
    

    模板测试.stg:

    group TemplatesTest;
    
    doc(expressions) ::=
    <<
    srart expressions
    <expressions; separator="\n">
    end
    >>
    
    expression(id, value) ::= 
    <<
    <id> := <value>;
    >>
    

    测试C代码:

    var lexer = new TemplatesTestLexer(new ANTLRFileStream("sample.txt"));
    var parser = new TemplatesTestParser(new CommonTokenStream(lexer));
    
    using (var reader = new StreamReader("TemplatesTest.stg"))
    {
      parser.TemplateLib = new StringTemplateGroup(reader);
    }
    
    var doc = parser.doc();
    Console.WriteLine(doc.Template);
    

    样本输入:

    a = 5
    b = 6
    c = 7
    

    输出为:

    srart expressions
    a := 5;
    b := 6;
    c := 7;
    end
    
    推荐文章