开发者

One Pass Model Tree Hierarchy Creation with a C# target

In short, I'm wondering how to properly build model hierarchies from within an ANTLR grammar in one pass and what the proper way to do that is with the current C# code generation. Accessing return variables does not currently seem to work, as described in the docs.

See this example from the documentation

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;}
    ;

My implementation is in C#, but the C# target documentation (circa 2008?) doesn't mention any deviations from the standard action pattern within grammars. I'm using ANTLRWorks 1.4 (not the latest 1.4.2 as of this writing) due to this. My implementation, which basically populates a 1 deep tree hierarchy with nested innerStats:

alias returns [IStatement alias]
    // Alias(string identifier, List<Statement> value, StatementTy开发者_JAVA百科pe 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(); }
    ;

This returns the following errors:

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

Currently, the only way I see to around this problem is to create a method within my C# model and then call Model.Aliases.Last().AddChild(IStatement) from within innerStat, which breaks encapsulation. Thanks for any help.

edit: The corrected code can be found here: https://github.com/keithharvey/Script-Parser/blob/master/Installer/Model/DAL/SourceExpr.g


Notice how the examples always refer to an attribute of a rule:

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

except the $ids, but that one isn't a rule because the += makes it a List.

Your code has 5 illegal usages of rule attributes (or the absence of them):

1

$id != null is invalid because you didn't use an attribute at all, try: $id.myInnerStat != null instead.

2

s=exec { myInnerStat = $s; } is wrong because you didn't use an attribute at all, you need to access an attribute of exec (you didn't post that rule, so I don't know what).

3, 4, 5

$ID.ToString(), $i1.ToString() and $i2.ToString() are wrong, ToString() isn't an valid attribute of ID. Try $ID.text, etc. instead.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜