2010-02-27 2 views
1

EDITED по грамматике WayneH вКак отобразить все местоимения в предложении и их лица с помощью Antlr

Вот что я имею в моем файле грамматики.

grammar pfinder; 

options { 
    language = Java; 
} 
sentence 
    : ((words | pronoun) SPACE)* ((words | pronoun) ('.' | '?')) 
    ; 

words 
    : WORDS {System.out.println($text);}; 

pronoun returns [String value] 
    : sfirst {$value = $sfirst.value; System.out.println($sfirst.text + '(' + $sfirst.value + ')');} 
    | ssecond {$value = $ssecond.value; System.out.println($ssecond.text + '(' + $ssecond.value + ')');} 
    | sthird {$value = $sthird.value; System.out.println($sthird.text + '(' + $sthird.value + ')');} 
    | pfirst {$value = $pfirst.value; System.out.println($pfirst.text + '(' + $pfirst.value + ')');} 
    | psecond {$value = $psecond.value; System.out.println($psecond.text + '(' + $psecond.value + ')');} 
    | pthird{$value = $pthird.value; System.out.println($pthird.text + '(' + $pthird.value + ')');}; 

sfirst returns [String value] : ('i' | 'me' | 'my' | 'mine') {$value = "s1";}; 
ssecond returns [String value] : ('you' | 'your'| 'yours'| 'yourself') {$value = "s2";}; 
sthird returns [String value] : ('he' | 'she' | 'it' | 'his' | 'hers' | 'its' | 'him' | 'her' | 'himself' | 'herself') {$value = "s3";}; 
pfirst returns [String value] : ('we' | 'us' | 'our' | 'ours') {$value = "p1";}; 
psecond returns [String value] : ('yourselves') {$value = "p2";}; 
pthird returns [String value] : ('they'| 'them'| 'their'| 'theirs' | 'themselves') {$value = "p3";}; 

WORDS : LETTER*;// {$channel=HIDDEN;}; 
SPACE : (' ')?; 
fragment LETTER : ('a'..'z' | 'A'..'Z'); 

и вот, с того, что я есть на тестовом ява класса

import java.util.Scanner; 
import org.antlr.runtime.*; 
import org.antlr.runtime.tree.*; 
import java.util.List; 

public class test2 { 
    public static void main(String[] args) throws RecognitionException { 
     String s; 
     Scanner input = new Scanner(System.in); 
     System.out.println("Eter a Sentence: "); 
     s=input.nextLine().toLowerCase(); 
     ANTLRStringStream in = new ANTLRStringStream(s); 
     pfinderLexer lexer = new pfinderLexer(in); 
     TokenStream tokenStream = new CommonTokenStream(lexer); 
     pfinderParser parser = new pfinderParser(tokenStream); 
     parser.pronoun(); 
    } 
} 

что мне нужно поставить в тестовый файл, так что он будет отображать все местоимения в предложении и их соответствующие значения (s1, s2, ...)?

+0

В заключение этой проблемы я оставлю вас с несколькими мыслями, чтобы помнить. «LEXER RULES» создают маркер каждый раз, когда они правильно соответствуют. «ПРАВИЛА ФРАГМЕНТОВ» не создают токенов. Когда-либо. Они используются в качестве сахара для написания более приятных правил Lexer. Они не принадлежат к Правилам Парсера. «ПАРСИОННЫЕ ПРАВИЛА» используются для GROUP TOKENS в определенном порядке («синтаксис»), однако они разрешаются в списке «ЛЕНТА» маркеров. Там нет отношений между родителями и детьми. «REWRITE RULES» используются для формирования правил Parser в TREE («parent> child, child, ...») для удобства INTERPRETING. – Kivin

+0

И, наконец, вы вполне можете направить меня по электронной почте (kivin [at] kivin/dot \ ca) или IM me (aim kivinkujata), если вы не понимаете ничего, что я написал. – Kivin

+0

В вашем тестовом классе java измените строку на parser.pronoun(); - parser.sentence(); И вы должны напечатать все слова и напечатать текст «s #» после ваших местоимений. Я не делал никакого форматирования, поэтому не стесняйтесь добавлять код для этого (напечатайте каждое слово в отдельной строке). Удачи. – WayneH

ответ

1

фрагменты не создают токенов, а размещение их в правилах парсера не даст желаемых результатов.

На моем тестовом поле, это произвело (я думаю!) Желаемый результат:

program : 
     PRONOUN+ 
    ; 

PRONOUN : 
     'i' | 'me' | 'my' | 'mine' 
    | 'you' | 'your'| 'yours'| 'yourself' 
    | 'he' | 'she' | 'it' | 'his' | 'hers' | 'its' | 'him' | 'her' | 'himself' | 'herself' 
    | 'we' | 'us' | 'our' | 'ours' 
    | 'yourselves' 
    | 'they'| 'them'| 'their'| 'theirs' | 'themselves' 
    ; 

WS : ' ' { $channel = HIDDEN; }; 

WORD : ('A'..'Z'|'a'..'z')+ { $channel = HIDDEN; }; 

В Antlrworks, образец «я пнул вы» вернули структуру дерева: program -> [i, you].

Я чувствую себя вынужденным указать, что Antlr является излишним для снятия местоимений из предложения. Рассмотрим использование регулярного выражения. Эта грамматика не чувствительна к регистру. Расширение WORD, чтобы потреблять все, кроме словаря PRONOUN (например, puncuation и т. Д.), Может быть немного утомительным. Будет требоваться дезинфекция ввода.

--- Edit: В ответ на второй ОП:

  • я переделал оригинальную грамматику, чтобы сделать легкость разбора. Новая грамматика:

    grammar pfinder; 
    
    options { 
        backtrack=true; 
        output = AST; 
    } 
    
    tokens { 
        PROGRAM; 
    } 
    
    program : 
         (WORD* p+=PRONOUN+ WORD*)* 
         -> ^(PROGRAM $p*) 
        ; 
    
    
    PRONOUN : 
         'i' | 'me' | 'my' | 'mine' 
        | 'you' | 'your'| 'yours'| 'yourself' 
        | 'he' | 'she' | 'it' | 'his' | 'hers' | 'its' | 'him' | 'her' | 'himself' | 'herself' 
        | 'we' | 'us' | 'our' | 'ours' | 'yourselves' 
        | 'they'| 'them'| 'their'| 'theirs' | 'themselves' 
    ; 
    
    WS : ' ' { $channel = HIDDEN; }; 
    
    WORD : ('A'..'Z'|'a'..'z')+; 
    

Я объясню изменения:

  • Откат теперь требуется решить программу правил синтаксического анализа. Возможно, есть лучший способ написать его, который не требует возврата, но это первое, что появилось на мой взгляд.
  • мнимый токен ПРОГРАММА определена для группировки наших местоимений.
  • Каждая соответствующая программа добавляется в Antlr var $ p и переписывается в AST под воображаемым правилом.
  • код переводчика теперь может использовать CommonTree для сбора совпавших местоимений
  • написано на C# (я не знаю, Java), но я написал это с намерением, что вы будете иметь возможность читать и понимать следующее Это.

    static object[] ReadTokens(string text) 
    { 
        ArrayList results = new ArrayList(); 
        pfinderLexer Lexer = new pfinderLexer(new Antlr.Runtime.ANTLRStringStream(text)); 
        pfinderParser Parser = new pfinderParser(new CommonTokenStream(Lexer)); 
        // syntaxTree is imaginary token {PROGRAM}, 
        // its children are the pronouns collected by $p in grammar. 
        CommonTree syntaxTree = Parser.program().Tree as CommonTree; 
        if (syntaxTree == null) return null; 
        foreach (object pronoun in syntaxTree.Children) 
        { 
         results.Add(pronoun.ToString()); 
        } 
        return results.ToArray(); 
    } 
    
  • Вызывающие ReadTokens ("я ударил вас и их") возвращает массив [ "я", "ты", "их"]

1

В случае, если вы пытаетесь сделать какой-то высокоуровневого анализа устного/письменного языка, вы можете использовать какой-то инструмент обработки естественного языка. Например, расскажет вам, какие элементы - местоимения (и глаголы, и существительные, и наречия, и другие эзотерические грамматические конструкции).(THT - единственный инструмент такого рода, с которым я знаком, поэтому не принимайте это как особое одобрение удивительности).

1

Я думаю, вам нужно узнать больше о правилах lexer в ANTLR, правила lexer начинаются с буквы верхнего регистра и генерируют токены для потока, на который будет смотреть парсер. Правила фрагмента Lexer не будут генерировать токен для потока, но помогут другим правилам lexer генерировать маркеры, просматривать правила lexer. СЛОВА И ПИСЬМО (ПИСЬМО не является токеном, но помогает СЛОВА создать токен).

Теперь, когда текстовый литерал помещается в правило анализатора (название правила начинается с строчной буквы), текстовый литерал также является допустимым маркером, который лексер будет идентифицировать и передать (по крайней мере, когда вы используете ANTLR-I не использовали никаких других инструментов, подобных ANTLR, чтобы отвечать за них).

Следующее, что я заметил, это то, что правила вашего '' и 'местоимения' выглядят одинаково. Я прокомментировал правило «s» и поместил все в правило «местоимения»

И последнее, что нужно узнать, как поместить действия в грамматик, у вас есть правило «s», устанавливающее возвращаемое значение , Я сделал правило местоимения верным строковым значением, так что, если вы хотите действия в правиле «предложения», вы легко сможете выполнить свой комментарий/ответ «-и местоимения».

Теперь, поскольку я не знаю, каковы ваши точные результаты, я играл с вашим грамматиком, делал некоторые небольшие изменения и реорганизовывал (перемещал то, что я считал правилом анализатора вверху, сохраняя все правила лексера внизу) и ставил в некоторых действиях, которые, я думаю, покажут вам, что вам нужно. Кроме того, может быть несколько различных способов сделать это, и я не думаю, что мое решение идеально подходит для любого из ваших возможно хотел результатов, но вот грамматику я смог работать в ANTLRWorks:

grammar pfinder; 

options { 
    language = Java; 
} 
sentence 
    : ((words | pronoun) SPACE)* ((words | pronoun) ('.' | '?')) 
    ; 

words 
    : WORDS {System.out.println($text);}; 

pronoun returns [String value] 
    : sfirst {$value = $sfirst.value; System.out.println($sfirst.text + '(' + $sfirst.value + ')');} 
    | ssecond {$value = $ssecond.value; System.out.println($ssecond.text + '(' + $ssecond.value + ')');} 
    | sthird {$value = $sthird.value; System.out.println($sthird.text + '(' + $sthird.value + ')');} 
    | pfirst {$value = $pfirst.value; System.out.println($pfirst.text + '(' + $pfirst.value + ')');} 
    | psecond {$value = $psecond.value; System.out.println($psecond.text + '(' + $psecond.value + ')');} 
    | pthird{$value = $pthird.value; System.out.println($pthird.text + '(' + $pthird.value + ')');}; 

//s returns [String value] 
// : exp=sfirst {$value = "s1";} 
// | exp=ssecond {$value = "s2";} 
// | exp=sthird {$value = "s3";} 
// | exp=pfirst {$value = "p1";} 
// | exp=psecond {$value = "p2";} 
// | exp=pthird {$value = "p3";} 
// ; 

sfirst returns [String value] : ('i' | 'me' | 'my' | 'mine') {$value = "s1";}; 
ssecond returns [String value] : ('you' | 'your'| 'yours'| 'yourself') {$value = "s2";}; 
sthird returns [String value] : ('he' | 'she' | 'it' | 'his' | 'hers' | 'its' | 'him' | 'her' | 'himself' | 'herself') {$value = "s3";}; 
pfirst returns [String value] : ('we' | 'us' | 'our' | 'ours') {$value = "p1";}; 
psecond returns [String value] : ('yourselves') {$value = "p2";}; 
pthird returns [String value] : ('they'| 'them'| 'their'| 'theirs' | 'themselves') {$value = "p3";}; 

WORDS : LETTER*;// {$channel=HIDDEN;}; 
SPACE : (' ')?; 
fragment LETTER : ('a'..'z' | 'A'..'Z'); 

Я думаю, что конечный результат заключается в том, что этот грамматик покажет вам, как выполнить то, что вы пытаетесь сделать, и потребует модификации независимо от того, что это за конечный результат.

Удачи.

Думаю, вам нужно изменить только одну строку в вашем тестовом классе, parser.pronoun(); : parser.sentence();

Возможно, вы захотите изменить еще несколько вещей в грамматике: SPACE: ''; предложение: (слова | местоимение) (ПРОСТРАНСТВО (слова | местоимение)) * ('.' | '?'); // тогда вы можете поставить правило между предложением и словами/местоимением.

+0

спасибо.Я не знал, что java-коды могут использоваться в antlr. другой вопрос. если я хочу отобразить все, смогу ли я это сделать? , потому что в приведенном выше коде, когда вы вводите «я пнул тебя», он отобразит «i (s1)», поэтому остальные части предложения игнорируются. Есть ли цикл или что-то такое, что он может отображать все предложения, например, он выводит «i (s1) пинает вас (s2)» или просто «i (s1) вы (s2)»? – XIII

+0

Если вы только получаете первое слово, в вашей контрольной программе будет что-то. Когда я положил «я пнул тебя», в ANTLRWorks отобразится: i (s1) нокаут вы (s2) В режиме отладки мне пришлось пройти весь путь. Можете ли вы показать строку в местоимении для ssecond – WayneH

+0

Я отредактировал свою тестовую программу. Я не знаю, почему он отображает только первое местоимение, которое находит – XIII

Смежные вопросы