Как я могу отобразить все местоимения в предложении и их лица, используя antlr - PullRequest
1 голос
/ 27 февраля 2010

отредактировано в соответствии с грамматикой WayneH

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

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');

и вот, что я имею в тестовом классе Java

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, ...)?

Ответы [ 3 ]

1 голос
/ 27 февраля 2010

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

1 голос
/ 27 февраля 2010

Я думаю, вам нужно больше узнать о правилах лексера в ANTLR, правила лексера начинаются с заглавной буквы и генерируют токены для потока, на который будет смотреть парсер. Правила фрагмента Lexer не будут генерировать токен для потока, но помогут другим правилам лексера генерировать токены, посмотрите на правила лексера WORDS и LETTER (LETTER не является токеном, но помогает WORDS создать токен).

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

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

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

Теперь, так как я не знаю, каковы ваши точные результаты, я поиграл с вашим грамматиком и сделал несколько небольших изменений и реорганизовал (переместил то, что я считал правилами синтаксического анализатора, на верх, сохранив все правила лексера внизу) и вставил некоторые действия, которые, я думаю, покажут вам, что вам нужно. Кроме того, может быть несколько разных способов сделать это, и я не думаю, что мое решение идеально подходит для любого из ваших возможных желаемых результатов, но вот грамматика, которую я смог получить, работая в 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 ();

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

1 голос
/ 27 февраля 2010

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

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

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 (например, пунктуация и т. Д.) Может быть немного утомительным.Потребуется санация ввода.

--- Редактировать: В ответ на второй OP:

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

    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 («я пнул тебя и их») возвращает массив [«я», «ты», «их»]

...