2012-05-03 5 views
1

要約:ANTLRで動的変数を実装するにはどうすればよいですか?
私は基本的な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"が文字列または整数のいずれかで呼び出されると、その値は "メモリ" 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 

これはなぜですか そう?申し訳ありませんが、私は明確でない場合、私はこれのほとんどを理解していません。入力"greeting"VARとしてトークン化されており、VAR無​​ないので

答えて

1
defun greeting "Hello world!" 

println greeting 

But when I run this code, I get this error:

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

。だから、入力defun greeting "Hello world!"は適切defunルールの2回目代替で一致している:

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

が、入力println "greeting"printlnルールにマッチすることはできません。

println 
: 'println' atom 
; 

あなたがいることを認識しなければなりませんレクサーは、パーサーが特定の時刻に照合しようとしているものに基づいてトークンを生成しません。入力"greeting"は常にVARとしてトークン化され、決してIDルールとしてトークン化されません。

レキシバーからIDルールを削除し、パーサールール内のIDVARに置き換えてください。

+0

私はそれがそれほど単純ではないと信じられません。参照してください、私は任意の識別子としてIDを持っていて、VARは有効な変数名として使っていました。ありがとう! – leaf

+0

@OmerEnnourは大歓迎です。 –