Создание иерархии дерева моделей за один проход с целью C # - PullRequest
1 голос
/ 16 июня 2011

Короче говоря, мне интересно, как правильно построить иерархии моделей из грамматики 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 #документация (около 2008 года?) не упоминает никаких отклонений от стандартного образца действия в грамматиках.Я использую ANTLRWorks 1.4 (не последнюю версию 1.4.2 на момент написания статьи) из-за этого .Моя реализация, которая в основном заполняет 1 глубокую древовидную иерархию вложенными innerStats:

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 # и затем вызвать Model.Aliases.Last().AddChild(IStatement) изнутри innerStat, что нарушает инкапсуляцию.Спасибо за любую помощь.

edit: исправленный код можно найти здесь: https://github.com/keithharvey/Script-Parser/blob/master/Installer/Model/DAL/SourceExpr.g

1 Ответ

1 голос
/ 16 июня 2011

Обратите внимание, что примеры всегда ссылаются на атрибут правила:

$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 и т. Д.

...