1

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、...) を表示するには、テスト ファイルに何を入力する必要がありますか?

4

3 に答える 3

1

話し言葉/書き言葉の高レベルな分析を行おうとしている場合は、何らかの自然言語処理ツールの使用を検討してください。たとえば、TagHelper ツールは、どの要素が代名詞 (および動詞、名詞、副詞、およびその他の難解な文法構造) であるかを示します。(THT は、私がよく知っているこの種の唯一のツールです。そのため、THT を特別に優れていると見なさないでください)。

于 2010-02-27T04:37:56.240 に答える
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 では、サンプル「i kicked you」はツリー構造を返しました: program -> [i, you].

Antlr は文から代名詞を削除するのはやり過ぎだと指摘せざるを得ません。正規表現の使用を検討してください。この文法では、大文字と小文字が区別されません。WORD を展開して、代名詞の辞書 (句読点など) 以外のすべてを消費するのは、少し面倒かもしれません。入力のサニタイズが必要になります。

--- 編集: 2 番目の 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')+;
    

変更点を説明します。

  • パーサー ルール プログラムを解決するには、バックトラッキングが必要になりました。おそらく、バックトラックを必要としないより良い書き方があるかもしれませんが、これが私の頭に浮かんだ最初のことです。
  • 代名詞をグループ化するために、架空のトークン PROGRAM が定義されています。
  • 一致した各プログラムは 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("i kicked you and they") を呼び出すと、配列 ["i", "you", "them"] が返されます

于 2010-02-27T03:27:43.367 に答える
1

ANTLR内のレクサールールについてもっと学ぶ必要があると思います。レクサールールは大文字で始まり、パーサーが見るストリームのトークンを生成します。レクサー フラグメント ルールはストリームのトークンを生成しませんが、他のレクサー ルールがトークンを生成するのに役立ちます。レクサー ルールの 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(); の 1 行だけを変更する必要があると思います。to: parser.sentence();

文法の他のいくつかの変更も必要になる場合があります。 SPACE : ' '; 文: (単語 | 代名詞) (SPACE (単語 | 代名詞))* ('.' | '?'); // その場合、文と単語/代名詞の間に規則を置きたいと思うかもしれません。

于 2010-02-27T13:55:25.387 に答える