Совпадение с определенным количеством повторений не жадным способом в ANTLR - PullRequest
2 голосов
/ 13 марта 2012

В моей грамматике есть что-то вроде этого:

line : startWord (matchPhrase|
                  anyWord matchPhrase|
                  anyWord anyWord matchPhrase|
                  anyWord anyWord anyWord matchPhrase|
                  anyWord anyWord anyWord anyWord matchPhrase) 
       -> ^(TreeParent startWord anyWord* matchPhrase);

Итак, я хочу сопоставить первое вхождение matchPhrase, но я позволю до определенного числа anyWord до него. Токены, составляющие matchPhrase, также соответствуют anyWord.

Есть ли лучший способ сделать это?

Я думаю, что это может быть возможно путем объединения семантического предиката в этом ответе с не жадным параметром:

(options {greedy=false;} : anyWord)*

но я не могу понять, как именно это сделать.

Редактировать: Вот пример. Я хочу извлечь информацию из следующих предложений:

Picture of a red flower.

Picture of the following: A red flower.

Мой ввод фактически помечен английскими предложениями, а правила Lexer соответствуют тегам, а не словам. Таким образом, вход для ANTLR:

NN-PICTURE Picture IN-OF of DT a JJ-COLOR red NN-FLOWER flower

NN-PICTURE Picture IN-OF of DT the VBG following COLON : DT a JJ-COLOR red NN-FLOWER flower

У меня есть правила лексера для каждого тега:

WS :  (' ')+ {skip();};
TOKEN : (~' ')+;

nnpicture:'NN-PICTURE' TOKEN -> ^('NN-PICTURE' TOKEN);
vbg:'VBG' TOKEN -> ^('VBG' TOKEN);

А мои правила синтаксического анализа примерно такие:

sentence : nnpicture inof matchFlower;

matchFlower : (dtTHE|dt)? jjcolor? nnflower;

Но, конечно, это потерпит неудачу во втором предложении. Поэтому я хочу дать немного гибкости, допуская до N жетонов перед совпадением цветов. У меня есть anyWord токен, который соответствует чему угодно, и работает следующее:

sentence :  nnpicture inof ( matchFlower | 
                             anyWord matchFlower |
                             anyWord anyWord matchFlower | etc.

но это не очень элегантно и плохо работает с большими буквами N.

1 Ответ

2 голосов
/ 14 марта 2012

Вы можете сделать это, сначала проверив в правиле matchFlower, существует ли действительно на dt? jjcolor? nnflower впереди в своем потоке токенов, используя синтаксический предикат .Если такие токены можно увидеть , просто сопоставьте их, если нет, сопоставьте любой токен и рекурсивно сопоставьте matchFlower.Это будет выглядеть так:

matchFlower
 : (dt? jjcolor? nnflower)=> dt? jjcolor? nnflower -> ^(FLOWER dt? jjcolor? nnflower)
 |                           . matchFlower         -> matchFlower
 ;

Обратите внимание, что . (точка) внутри правила синтаксического анализатора не соответствует любому символу, кроме любого токена.

Вот краткая демонстрация:

grammar T;

options {
  output=AST;
}

tokens {
  TEXT;
  SENTENCE;
  FLOWER;
}

parse
 : sentence+ EOF -> ^(TEXT sentence+)
 ;

sentence
 : nnpicture inof matchFlower -> ^(SENTENCE nnpicture inof matchFlower)
 ;

nnpicture
 : NN_PICTURE TOKEN -> ^(NN_PICTURE TOKEN)
 ;

matchFlower
 : (dt? jjcolor? nnflower)=> dt? jjcolor? nnflower -> ^(FLOWER dt? jjcolor? nnflower)
 |                           . matchFlower         -> matchFlower
 ;

inof
 : IN_OF (t=IN | t=OF) -> ^(IN_OF $t)
 ;

dt
 : DT (t=THE | t=A) -> ^(DT $t)
 ;

jjcolor
 : JJ_COLOR TOKEN -> ^(JJ_COLOR TOKEN)
 ;

nnflower
 : NN_FLOWER TOKEN -> ^(NN_FLOWER TOKEN)
 ;

IN_OF      : 'IN-OF';
NN_FLOWER  : 'NN-FLOWER';
DT         : 'DT';
A          : 'a';
THE        : 'the';
IN         : 'in';
OF         : 'of';
VBG        : 'VBG';
NN_PICTURE : 'NN-PICTURE';
JJ_COLOR   : 'JJ-COLOR';
TOKEN      : ~' '+;
WS         : ' '+ {skip();};

Анализатор, сгенерированный из приведенной выше грамматики, проанализирует ваш ввод:

NN-PICTURE Picture IN-OF of DT the VBG following COLON : DT a JJ-COLOR red NN-FLOWER flower

следующим образом:

enter image description here

Как видите, все до того, как цветок опущен в дерево.Если вы хотите сохранить эти токены там, сделайте что-то вроде этого:

grammar T;

// ...

tokens {
  // ...
  NOISE;
}

// ...

matchFlower
 : (dt? jjcolor? nnflower)=> dt? jjcolor? nnflower -> ^(FLOWER dt? jjcolor? nnflower)
 |                           t=. matchFlower       -> ^(NOISE $t) matchFlower
 ;

// ...

, что приведет к следующему AST:

enter image description here

...