(我是Antlr的一个菜鸟).我在StringTemplates语法方面有困难。基本上我只是想写点DSL。我可以以我想要的方式获得我的语法(它正确地解析),但我无法让生成的目标代码与模板一起工作。下面是我语法的一个片段:
grammar Pfig;
options {
output=template;
language=CSharp2;
}
conf
: globalName
;
globalName
: 'GlobalName:' ID
-> localConf(name ={$ID.text})
;我把它简化了很多,只是为了让大家了解它的本质。基本上,当lex/解析遇到‘`GlobalName: Foo’时,我希望它能够根据名为'localConf‘的StringTemplate来吐出文本。超直率的。
现在,让我们在一个测试应用程序中启动解析器,并让它处理一个输入文件。
// 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生成了解析器,它做了同样的事情:
// 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一起工作的一些基本概念。,我很确定这是我的问题,但我不知道我做错了什么,.我看到的例子并没有真正显示出真实的模板代码。
发布于 2010-08-29 08:15:54
基本上,您需要显式地将模板输出转发到子规则:
conf
: a=globalName -> {$a.st}
;它不是美丽的,而是有效的。
发布于 2011-01-10 14:00:19
看来,我终于明白了模板的想法:)模板应该分层地“嵌套”。下面的示例运行得很好:
TemplatesTest.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})
;TemplatesTest.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;
endhttps://stackoverflow.com/questions/2807613
复制相似问题