1

スキームのような言語通訳者のための文法を作成しました。最初は、評価を制御するif-then-elseステートメントのセマンティック述語が1つありました。つまり、条件がtrueの場合、「then」のみが評価されます。falseの場合、「else」のみが評価されます。タイプチェック機能を追加するために、最初の述語を囲む2番目のセマンティック述語を追加しました。ただし、タイプチェックまたは評価するには、グローバルブール値を手動でtypeChecktrueまたはfalseに変更する必要があるため、これはハックです。

IFステートメントのASTには2つのブランチがあります。1つ目(IFT)は、IFステートメントの引数の型チェック用です。[これが2つの述語の理由です。タイプチェックするには、すべての引数を評価する必要があります] 2番目のブランチ(IFE)は、短絡したif-then-elseを評価するためのものです。この問題は、最初の述語を囲む2番目のセマンティック述語を追加したときに始まり、悪名高い「入力時に実行可能な代替手段がありません」というエラーが発生しました。ゆっくりとどこにも行かなくなった後、私は必需品だけで新しい文法を作成しました。同じ問題。これがASTを取り除いたものです:

ASTの場合

私はこれを経験したことはありませんが、EclipseのANTLRIDEでSOについて報告された問題を見てきました。そこで、ANTLRWorksを起動し、パーサー文法をデバッグしてから、ツリー文法をデバッグしようとしました。バージョン1.4.3と1.4.2はどちらも、このボックスに「警告:リモートパーサーで使用される文法が同じではありません」と表示されます。[OK]をクリックし、デバッガーで[ステップフォワード]を1回クリックすると、java.exe*32プロセスが終了します。最後のテストとして、antlr-3.3およびantlr-3.4の完全なjarを使用して、コマンドラインから手動でコンパイルしました。変更はありません。

パーサー:

grammar NestedSemPreds;

options {
    output = AST;
    ASTLabelType = CommonTree;
}

tokens {
    IF;
    IFT;
    IFE;
}   

/** parser rules **/
ifstmt  : '(' 'if' COND THEN ELSE ')' NEWLN
            -> ^(IF ^(IFT COND THEN ELSE)
                    ^(IFE COND THEN ELSE)
                )
        ;

/** lexer rules **/
COND    : 'true' ; 
THEN    : 'then' ;
ELSE    : 'else' ;
COMMENT :   ('//' .* NEWLN) { skip(); } ; //for lines in datafile I don't want processed
NEWLN   :   '\r'? '\n' ;
WS      :   (' '|'\t')+ { skip(); } ;

ツリーの文法:

tree grammar treeEval;

options {
    tokenVocab = NestedSemPreds;
    ASTLabelType = CommonTree;
}

@members {
    boolean typeCheck = false;
}

ifstmt 
@init {
    boolean condition = true;
}
 : ^(IF (  
           {typeCheck}? => //{System.out.println("typeCheck is true");}
                            ^(IFT COND THEN ELSE) {System.out.println("IFT COND THEN ELSE");}
                            ^(IFE . . .) {System.out.println("    SKIP IFE WITH . WILDCARD");}
        | {!typeCheck}? => //{System.out.println("typeCheck is false");} 
                            ^(IFT . . .) {System.out.println("skip ift with . wildcard");}
                            ^(IFE COND
                                    (  {condition}? => ({System.out.println("    condition is true");}
                                                       THEN . {System.out.println("        evaluate THEN");})
                                    | {!condition}? => ({System.out.println("    condition is false");}
                                                      . ELSE {System.out.println("        evaluate else");})
                                    )//close inner predicate
                             )//close ^IFE
        )//close outer predicate
    )//close ^IF
 ;

ネストされたセマンティック述語に関する特定の問題は見つかりませんでしたが、例も見つかりませんでした。このコードが失敗するのはなぜですか?ANTLRWorksデバッガーの問題に関するアイデアはありますか?

4

1 に答える 1

2

「2番目の選択肢の前に述語を追加する」必要がないというBartのコメントを使用して、いくつかの追加のテストを行いました。テストされたオプションはすべて有効な構文だったので、これはANTLRのバグだと思います。追いかけるために、これがうまくいくものです:

ifstmt 
@init {
    boolean condition = true;
}
 : ^(IF (  
           {typeCheck}? => ^(IFT COND THEN ELSE) {System.out.println("IFT COND THEN ELSE");}
                           . //MUST use only one dot
        | {!typeCheck}? => . //also works with ^(IFT . . .) here
                            ^(IFE COND
                                    (  {condition}? => ({System.out.println("    condition is true");}
                                                       THEN . {System.out.println("        evaluate THEN");})
                                    | {!condition}? => //this inner 2nd predicate not required
                                                      . ELSE {System.out.println("        evaluate else");})
                                    )//close inner predicates
                             )//close ^IFE
        )//close outer predicates
    )//close ^IF
 ;

これらの2つのステップが必要です

  1. 外部述語{typeCheck}?{!typeCheck}?、の両方が必要です。
  2. 最初の外部述語、サブツリー全体をスキップする単一の.演算子

コードサンプルに記載されているように、次の2つの構文変更のいずれでも機能します。

  1. 2番目の外部述語、{!typeCheck}?は、単一.または元の^(IFT . . .)構文を使用できます。
  2. Bartが述べたように、2番目の内部述語はオプションです。

うまくいった別の解決策は、ノードストリームを手動で処理し、適切なコードを追加することでしたが、それはANTLRに任せるほどクリーンではありません。

于 2012-08-05T20:35:16.937 に答える