АНТЛР: Как мне сделать дерево с более чем двумя детьми? - PullRequest
1 голос
/ 10 декабря 2010

Учитывая грамматику,

parse   : expr EOF -> ^(ROOT expr);
expr    : atom ('|'^ atom)*;
atom    : LITERAL | ('('! expr ')'!);

LITERAL : 'a'..'z';
WS      : (' '|'\t'|'\r'|'\n'){Skip();};

И ввод,

a|b|c

Я получаю дерево, которое выглядит как,

http://graph.gafol.net/pic/dsqoQhzgs.png

В то время как я хотел бы, чтобы дерево выглядело как

http://graph.gafol.net/pic/dsrGWVUfz.png

Как бы я выразил это в грамматике?

Ответы [ 2 ]

1 голос
/ 10 декабря 2010

Это немного сложно.Вы можете сделать это, используя синтаксический предикат (LOOK-AHEAD-TOKENS-HERE)=> перед сопоставлением с цепочкой ИЛИ:

expr
  :  (atom '|')=> atom ('|' atom)+ -> ^('|' atom+)
  |  atom
  ;

, которая правильно обрабатывает a|b|c, a|b и a.

Но вы, возможно, захотите объяснить, на каком языке вы на самом деле пытаетесь разобрать: возможно, есть лучшие (более элегантные?) Способы выразить это.

Почему бы вам не захотеть использовать AST, как на первой диаграмме?Оценивать выражения легко, когда корень (операнд) имеет только двух дочерних элементов, верно?

0 голосов
/ 10 декабря 2010
parse   : expr EOF -> ^(ROOT expr);
expr    : atom ('|'^ atom)* -> atom+;
atom    : LITERAL | ('('! expr ')'!);

LITERAL : 'a'..'z';
WS      : (' '|'\t'|'\r'|'\n'){Skip();};

Я думаю, что это будет сделано путем добавления правила перезаписи, но сейчас у меня нет antlrworks, поэтому я не уверен. Но это близко, так что попробуйте и измените синтаксис переписывания, если это необходимо.

...