使用C#目标创建一次通过模型树层次结构

时间:2011-06-15 22:04:23

标签: c# antlr antlr3 antlrworks

简而言之,我想知道如何在一次传递中从ANTLR语法中正确构建模型层次结构,以及正确的方法是使用当前的C#代码生成。目前,访问返回变量似乎不起作用,如文档中所述。

请参阅文档

中的此示例
field
    : d=decl ';' {System.out.println("type "+$d.type+", vars="+$d.vars);}
    ;
decl returns [String type, List vars]
    : t=type ids+=ID (',' ids+=ID)* {$type = $t.text; $vars = $ids;}
    ;

我的实现是在C#中,但是C# target documentation(大约在2008年?)没有提到语法中与标准动作模式的任何偏差。由于this,我正在使用ANTLRWorks 1.4(截至本文撰写时不是最新的1.4.2)。我的实现,基本上用嵌套的innerStats填充1个深层树层次结构:

alias returns [IStatement alias]
    // Alias(string identifier, List<Statement> value, StatementType statementType, MetaData metaData)
    @init { List<IStatement> innerList = new List<IStatement>(); }
    :   ^(ALIAS ID ( id=innerStat{if($id != null) {innerList.Add($id.myInnerStat);}} )+ ) {$alias = new Alias($ID.ToString(), innerList , StatementType.Alias, null) as IStatement; }
    ;

innerStat returns [IStatement myInnerStat]
    :   s=simpleAlias { myInnerStat = $s; }
    |   s=simpleBind { myInnerStat = $s; }
    |   s=command { myInnerStat = $s; }
    |   increment { myInnerStat = null; }
    |   s=exec { myInnerStat = $s; }
    ;

simpleAlias returns [IStatement myAlias]
    // Alias(string identifier, List<Statement> value, StatementType statementType, MetaData metaData)
    @init{ myAlias= null; string id1 = null; string id2 = null; }
    @after{ myAlias = (new Alias(id1, id2, StatementType.Alias, null)) as IStatement; }
    :   ^(ALIAS ID) { id1 = $ID.ToString(); }
    |   ^(ALIAS i1=ID i2=ID) { id1 = $i1.ToString(); id2 = $i2.ToString(); }
    ;

这会返回以下错误:

error(117): D:/Files/.../SourceEval.g:39:29: missing attribute access on rule scope: id
error(117): D:/Files/.../SourceEval.g:43:18: missing attribute access on rule scope: s
error(117): D:/Files/.../SourceEval.g:44:17: missing attribute access on rule scope: s
error(117): D:/Files/.../SourceEval.g:45:14: missing attribute access on rule scope: s
error(117): D:/Files/.../SourceEval.g:47:11: missing attribute access on rule scope: s

目前,我唯一能看到这个问题的方法是在我的C#模型中创建一个方法,然后从innerStat中调用Model.Aliases.Last().AddChild(IStatement),这会破坏封装。谢谢你的帮助。

编辑:更正后的代码可在此处找到:https://github.com/keithharvey/Script-Parser/blob/master/Installer/Model/DAL/SourceExpr.g

1 个答案:

答案 0 :(得分:1)

请注意示例如何始终引用规则的属性:

$d.type
$d.vars
$t.text

除了$ids,但是那个不是规则,因为+=使其成为List

您的代码有5个非法用法的规则属性(或缺少它们):

1

$id != null无效,因为您根本没有使用属性,请尝试:$id.myInnerStat != null

2

s=exec { myInnerStat = $s; }错误,因为您根本没有使用属性,您需要访问exec的属性(您没有发布该规则,所以我不知道是什么)

3,4,5

$ID.ToString()$i1.ToString()$i2.ToString()错误,ToString()不是ID的有效属性。请改为$ID.text等。