Сборка ANTLR AST: корневой узел в виде строки вместо символа - PullRequest
2 голосов
/ 25 октября 2010

Возможно, я задаю глупый / базовый вопрос, но я был озадачен построением ANTLR AST.

То, что я хочу сделать, - это своего рода синтаксический анализатор булевых выражений, такой, что на родительских узлах у меня есть оператор и его оператор.операнды как дети.например, предложение

((ABC & D) | (E & (F | G)))

в идеале должно представлять

              |
             / \
            /   \
           /     \
          /       \
         &         &
        / \       / \
       /   \     /   \
      /     D   E     |
     /|\             / \
    A B C           /   \
                   F     G 

Из следующей грамматики.

grammar Test;

options
{
   language = 'Java';
   output=AST;
}


exp    :    word (expRest^)? | '('! exp ')'! (expRest^)?  ;

expRest :    (('&'|'|'|'!'|'&!'|'|!')^) exp | (('~'^) digit+ exp);
word    :   letter letter* -> ^(letter letter*);
letter  :        '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'|'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m'|'n'|'o'|'p'|'q'|'r'|'s'|'t'|'u'|'v'|'w'|'x'|'y'|'z'|'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M'|'N'|'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z';
digit   :    '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9';

Проблема в том, что я получаю 'ABC' в виде списка (массива) узлов как потомков '&'.

Можно ли ограничить его одной строкой ???то есть 'ABC' или другими словами, возможно ли иметь несколько символов в корневом узле в AST ???Если да, то как мне этого добиться?

для справки, я хочу создать синтаксическое дерево «факторов риска и текущего экономического состояния»

PS У меня также естьпопробовал:

word    :   (letter letter*)^ ;

И просто для справки, я использую среду .NET.

Ответы [ 2 ]

3 голосов
/ 25 октября 2010

Вы можете вставить в свою грамматику воображаемые жетоны, которые будут корнем «групп» слов. Я не думаю, что это хорошая идея, чтобы склеить A, B и C вместе, так как вы, вероятно, нуждаетесь в них отдельно, верно?

Я не мог понять, что именно вы пытаетесь сделать, поэтому вот небольшая демонстрация, которую вы можете (попытаться) обдумать:

grammar BoolExp;

options { 
  output=AST; 
}

tokens {
  MultiWord;
}

parse
  :  booleanExp EOF!
  ;

booleanExp
  :  orExp
  ;

orExp
  :  andExp ('|'^ andExp)*
  ;

andExp
  :  notExp ('&'^ notExp)*
  ;

notExp
  :  '!'^ atom
  |  atom
  ;

atom
  :  '(' booleanExp ')' -> booleanExp
  |  WORD WORD+         -> ^(MultiWord WORD+)
  |  WORD
  ;

WORD
  :  ('a'..'z' | 'A'..'Z')+
  ;

SPACE
  :  (' ' | '\t' | '\r' | '\n'){skip();}
  ;

Если вы сгенерируете из него парсер и протестируете его с помощью ввода:

( ( A B C & D ) | ( E & ( F | G ) ) )

вы получите следующее AST:

alt text

Я не публиковал свой (Java) тестовый класс, который сгенерировал файл DOT, который использовался для создания образа AST выше, так как вы сказали, что используете цель .NET. Если вы хотите посмотреть его, оставьте комментарий, и я тоже опубликую его.

0 голосов
/ 25 октября 2010

Если вы хотите, чтобы «ABC» представлял собой отдельный узел, определите букву для включения «» между символами, например:

letter : character (space character)*;
character : '0'..'9'|'a'..'z'|'A'..'Z';
space : ' ';

, которая будет содержать пробелы в качестве дочерних элементов узла буквы.

...