首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ANTLR:使用stringTemplate

ANTLR:使用stringTemplate
EN

Stack Overflow用户
提问于 2010-05-11 01:58:59
回答 2查看 3.7K关注 0票数 2

(我是Antlr的一个菜鸟).我在StringTemplates语法方面有困难。基本上我只是想写点DSL。我可以以我想要的方式获得我的语法(它正确地解析),但我无法让生成的目标代码与模板一起工作。下面是我语法的一个片段:

代码语言:javascript
复制
grammar Pfig;

options { 
    output=template;  
 language=CSharp2;
 }

conf 
    : globalName
    ;


globalName 
    : 'GlobalName:'  ID
     -> localConf(name ={$ID.text})
    ;

我把它简化了很多,只是为了让大家了解它的本质。基本上,当lex/解析遇到‘`GlobalName: Foo’时,我希望它能够根据名为'localConf‘的StringTemplate来吐出文本。超直率的。

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

代码语言:javascript
复制
// 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的。问题是,由于这个'globalName‘规则是'conf’的一个子规则,所以它不会直接执行--这个方法只是找到它并返回。但是调用'Conf‘方法并不能保留子规则中的返回值--它会掉进稀薄的空气。这意味着我在最后一行上得到的模板为null。

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

代码语言:javascript
复制
// 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

很简单,我不了解模板方法应该如何与Antlr一起工作的一些基本概念。,我很确定这是我的问题,但我不知道我做错了什么,.我看到的例子并没有真正显示出真实的模板代码。

EN

回答 2

Stack Overflow用户

发布于 2010-08-29 08:15:54

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

代码语言:javascript
复制
conf 
    : a=globalName -> {$a.st}
    ;

它不是美丽的,而是有效的。

票数 2
EN

Stack Overflow用户

发布于 2011-01-10 14:00:19

看来,我终于明白了模板的想法:)模板应该分层地“嵌套”。下面的示例运行得很好:

TemplatesTest.g:

代码语言:javascript
复制
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})
    ;

TemplatesTest.stg:

代码语言:javascript
复制
group TemplatesTest;

doc(expressions) ::=
<<
srart expressions
<expressions; separator="\n">
end
>>

expression(id, value) ::= 
<<
<id> := <value>;
>>

测试C#代码:

代码语言:javascript
复制
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);

样本输入:

代码语言:javascript
复制
a = 5
b = 6
c = 7

产出如下:

代码语言:javascript
复制
srart expressions
a := 5;
b := 6;
c := 7;
end
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2807613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档