1

要するに:ANTLRで動的変数を実装するにはどうすればよいですか?
ANTLRの基本的な質問でまたお会いしましょう。
私はこの文法を持っています:

grammar Amethyst;

options {
    language = Java;
}

@header {
    package org.omer.amethyst.generated;
    import java.util.HashMap;
}

@lexer::header {
    package org.omer.amethyst.generated;
}

@members {
    HashMap memory = new HashMap();
}

begin: expr;

expr: (defun | println)*
;

println:
    'println' atom {System.out.println($atom.value);}
;

defun:
    'defun' VAR INT {memory.put($VAR.text, Integer.parseInt($INT.text));}
    | 'defun' VAR STRING_LITERAL {memory.put($VAR.text, $STRING_LITERAL.text);}
;

atom returns [Object value]:
    INT {$value = Integer.parseInt($INT.text);}

    |   ID
    {
    Object v = memory.get($ID.text);
    if (v != null) $value = v;
    else System.err.println("undefined variable " + $ID.text);
    }

| STRING_LITERAL
  {
    String v = (String) memory.get($STRING_LITERAL.text);
    if (v != null) $value = String.valueOf(v);
    else System.err.println("undefined variable " + $STRING_LITERAL.text);
  }
;

INT: '0'..'9'+ ;
STRING_LITERAL: '"' .* '"';

VAR: ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')* ;
ID: ('a'..'z'|'A'..'Z'|'0'..'9')+ ;
LETTER: ('a..z'|'A'..'Z')+ ;
WS: (' '|'\t'|'\n'|'\r')+ {skip();} ;

これまでのところ、それが行う(または行うべき)ことは、あなたが思っていることを正確に行うための組み込みの「println」関数と、変数を定義するための「defun」ルールを持っていることです。
文字列または整数のいずれかで「defun」が呼び出されると、値は「メモリ」HashMapに入れられ、最初のパラメーターは変数の名前で、2番目のパラメーターはその値です。
printlnがアトムで呼び出されると、アトムの値が表示されます。アトムは文字列または整数のいずれかです。メモリから値を取得して返します。したがって、たとえば:

defun greeting "Hello world!"

println greeting

しかし、このコードを実行すると、次のエラーが発生します。

line 3:8 no viable alternative at input 'greeting'
null

注:この出力は、次の場合に表示されます。

println "greeting"

出力:

undefined variable "greeting"null

なぜそうなのか誰か知っていますか?よくわからない場合は申し訳ありませんが、ほとんど理解できません。

4

1 に答える 1

1
defun greeting "Hello world!"

println greeting

しかし、このコードを実行すると、次のエラーが発生します。

3:8行目入力'挨拶'で実行可能な代替手段はありません

入力"greeting"はaとしてトークン化されてVARおり、aVARはnoであるためatomです。したがって、入力はルールの2番目の選択肢defun greeting "Hello world!"と適切に一致します。defun

defun
 : 'defun' VAR INT               // 1st alternative
 | 'defun' VAR STRING_LITERAL    // 2nd alternative
 ;

ただし、入力をルールprintln "greeting"に一致させることはできません。println

println
 : 'println' atom
 ;

レクサーは、パーサーが特定の時間に照合しようとする内容に基づいてトークンを生成しないことを理解する必要があります。入力は、原則としてではなく、"greeting"常にとしてトークン化されます。VARID

あなたがする必要があるのはID、レクサーからルールを削除し、パーサールールの内部にID置き換えることです。VAR

于 2012-05-04T06:55:10.367 に答える