【问题标题】:One Pass Model Tree Hierarchy Creation with a C# target使用 C# 目标创建一次性模型树层次结构
【发布时间】:2011-06-15 22:04:23
【问题描述】:

简而言之,我想知道如何从 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

【问题讨论】:

    标签: c# antlr antlr3 antlrworks


    【解决方案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等。

    【讨论】:

    • 谢谢大佬,我在迷茫的魔境中太久了。奇怪的是 3,4 和 5 没有抛出错误。我将发布更正后的代码。
    • @Daniel,很有趣。也许 C# 目标接受 ToString(),但 Java 目标不接受(接受 toString())。使用.text 属性使语法更便携,因为它适用于所有语言目标(或至少:应该工作!:))。
    猜你喜欢
    • 2017-04-18
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多