5

簡単な言語の文法を定義したいと思います。

この言語では、ある種の割り当てが可能です。

keyworda: this is the 1 keyword-A
keywordb: this is the second keywordb
...

重要なのは、キーワードと':'任意の文字の後に可能である必要があるということです(キーワードも)

私は多くのことを試しましたが、私はまだレクサーとパーサーの考え方にそれほど興味がないと思います...

私の最後のアイデアは失敗しました:

rule 
  :  'keyworda' ':' anychar* 'keywordb' ':' anychar* EOF 
  ;

anychar
  :  .
  ;

NEWLINE
  :  ('\r'? '\n') {$channel=HIDDEN;}
  ;

編集

まず第一に:あなたの答えに感謝します!

マニュアルを読み、scottstanchfieldによるチュートリアルを見ました。

問題は、私が「anychar」のものを取得できないことです!

あなたは正しいです、私が急いでいたので、私が上で投稿した文法は間違っていました。

より良い試みはこれを先に行うことです。問題は、Tokenizerが定義alaのkeywordaなどを認識することです。

keyworda : this is keyworda.
keywordb : this is another key!
...

文法:

rule
    :   KEYA ':' STRING_LITERAL* NEWLINE
        keybdefinition*
         EOF
    ;

keybdefinition
    :   KEYB ':' STRING_LITERAL* NEWLINE
    ;


KEYA: 'keyworda';
KEYB:'keywordb';
STRING_LITERAL: 'a'..'z' | 'A'..'Z' | '0'..'9' | ':' | '.' | '&' | '/' | '\\' | ';';

NEWLINE: '\r'? | '\n'; 
SPACE:  (' ' | '\t') {$channel=HIDDEN;};

編集II

なんてこった、あなたがそれを説明したようにそれをするのは静かに明白です。なぜ自分で手に入らなかったのかわからない!説明してくれたティムに感謝します!

残りの質問がもう1つあります。レクサーのトークンとパーサーの文法を定義する場合です。ツリーパーサーまたはパーサー自体のセマンティックをチェックする一般的な方法ですか?

たとえば、あなたが投稿したのと同じ文法が定義されているとしましょう。

keyworda : ab
keywordb : xy
keyworda : ab1
keywordb : xy1
...

ここで、keywordaを定義するたびに、keywordbが定義されているかどうかを確認したいと思います。後で、値が適切かどうかの意味を確認したいと思います。キーワードextends:'keyword value'があり、'keywordvalue'がすでに定義されているかどうかを確認する必要があると仮定します。

これは2つの方法で行うことができます。まず、パーサーの文法規則を変更し、そこにチェック用のJavaコードを追加します。次に、文法はそのままで、これらの条件をチェックするためにツリーパーサー文法を定義します。

どちらが良いのか、長所と短所は何なのか、私にはよくわかりません...

あなたの助けをどうもありがとう

4

1 に答える 1

19

.、レクサールールとパーサールール内で異なる意味を持ちます。レクサールール内では、範囲内の任意の文字に一致します\u000...。\uFFFFそして、パーサールール内で、.任意のトークンと一致します。

レクサールールは大文字で始まり、パーサールールは小文字で始まることに注意してください。パーサールール内のリテラルとしてトークン(レクサールール)を作成することもできます。つまり、文法は4つの異なるトークンのみを作成します(NEWLINE「非表示」であるため、実際には3つ)。

  • 'keyworda'
  • ':'
  • 'keywordb'
  • NEWLINE(デフォルトのトークンストリームから削除されます)

EOF組み込みトークンです)

つまり、anycharルールは、、またはのいずれかに一致し'keyworda'':'予想どおりの文字'keywordb'には一致しません。

また、key ':' valueエントリを改行で区切っているようですが、字句解析フェーズで改行を削除しています。valueそれらを削除することにより、aの終わりが何であるか、そしてaの始まりが何であるかをどのように知ることになっていますkeyか?トークンストリームは、キーワード任意の文字コロンの連続ストリームであるため、キーワードが実際にキーワードであるか、value(の右側':')の一部であるかを判断する方法はありません。そのためには改行トークンが必要です。

何をしているのかよくわからずにANTLRを使い始めたようです。IMO、これはこの特定のツールを学ぶ方法ではありません。続行する前に、 The Definitive ANTLR Referenceのコピーを入手するか、いくつかのANTLRチュートリアルを読んだり見たりすることをお勧めします。

頑張ってください!

編集

キーワードを「値」の一部にする方法の簡単なデモを次に示します。

ファイル:Tg

grammar T;

parse
  :  line+ EOF
  ;

line
  :  key COLON value eol 
     {System.out.printf("key='\%s', value='\%s'\n", $key.text, $value.text);}
  ;

value
  :  any_except_newline*
  ;

key
  :  KEYA
  |  KEYB
  ;

any_except_newline
  :  COLON
  |  KEYA
  |  KEYB
  |  WORD
  |  ANYCHAR
  ;

eol
  :  NEWLINE
  |  EOF
  ;

COLON   : ':';
KEYA    : 'keyworda';
KEYB    : 'keywordb';
WORD    : ('a'..'z' | 'A'..'Z')+;
NEWLINE : '\r'? '\n' | '\r';
SPACE   : (' ' | '\t') {$channel=HIDDEN;};
ANYCHAR : .; 

ファイル:Main.java

import org.antlr.runtime.*;

public class Main {
  public static void main(String[] args) throws Exception {
    String source = 
        "keyworda : this is keyworda.\n" + 
        "keywordb : this is another key!";
    TLexer lexer = new TLexer(new ANTLRStringStream(source));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    parser.parse();
  }
}

次の手順でデモを実行する場合:

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main

次のようにコンソールに出力されます。

key='keyworda', value='this is keyworda.'
key='keywordb', value='this is another key!'
于 2011-09-02T18:54:27.073 に答える