1

コードのどこにでも置くことができる ifdef ... else ... end ステートメントを評価する方法を知りたいです。2 つの基本関数 add(p1,p2) と diff(p1,p2) を実装する簡単な例から始めます。ここで、p1 と p2 は文字列です。p1 と p2 の間に + または - を追加するだけです。これが私の文法です:

grammar ifdef;

options {
  language = Java;
  output = AST;
  ASTLabelType=CommonTree;
}

tokens 
{
    EQUAL           = '=' ;
    HASH            = '#' ;
    DBLEQUOTE       = '"' ;
    SEMICOLON       = ';' ;
}


@header {
    package Grammar;

    import java.util.Map;
    import java.util.HashMap;

}

@lexer::header {
    package Grammar;    
}

@members {
    private Map<String, String> strMapID = new HashMap<String, String>();
    private Map<String, String> strMapDefine = new HashMap<String, String>();
}


rule returns [String strEval]
    :   {   StringBuilder strBuilder = new StringBuilder(); }
    (   command
        {   if ( $command.str != "" ) {
                strBuilder.append( $command.str );
                strBuilder.append( "\n" );
            }
        }

    )+ EOF
        { $strEval = strBuilder.toString(); }
    ;

command returns [String str]
    :   define      { $str=""; }
    |   undef       { $str=""; }
    |   set         { $str=""; }
    |   function    { $str = $function.str; }
    |   ifdef       { $str=""; }
    ;

define
    :   HASH 'define' ID
        { strMapDefine.put($ID.text, $ID.text); }       // save define ID into hash table
    ;

undef
    :   HASH 'undef' ID
        {   if ( strMapDefine.containsKey($ID.text) ) {
                strMapDefine.remove($ID.text);          // undef ID in hash table
                }
        }
    ;

set
    :   'set' ID EQUAL string SEMICOLON
        { strMapID.put($ID.text, $string.text); }       // save ID,string definition into hash table 
    ;

string
    :   DBLEQUOTE expr DBLEQUOTE
    ;

function returns [String str]
    :   add     { $str = $add.str; }
    |   diff    { $str = $diff.str; }
    ;

add returns [String str]
    :   'add' '(' p1=param ',' p2=param ')'
        {   StringBuilder strBuilder = new StringBuilder();
            strBuilder.append( $p1.str );
            strBuilder.append( "+" );
            strBuilder.append( $p2.str );
            $str = strBuilder.toString();
        }
    ;

diff returns [String str]
    :   'diff' '(' p1=param ',' p2=param ')'
        {   StringBuilder strBuilder = new StringBuilder();
            strBuilder.append( $p1.str );
            strBuilder.append( "-" );
            strBuilder.append( $p2.str );
            $str = strBuilder.toString();
        }
    ;

param returns [String str]
    :   ID          { $str = strMapID.get($ID.text); }      // assign ID definition to str
    |   string      { $str = $string.text; }
    |   function    { $str = $function.str; }
    ;

ifdef
    :   {   Boolean bElse= false;
            StringBuilder strBuilder = new StringBuilder(); }
        HASH 'ifdef' '(' ID ')' c1=expr ( HASH 'else' c2=expr { bElse= true; } )? HASH 'end'
        {   if ( strMapDefine.containsKey($ID.text) ) {
                strBuilder.append($c1.text);
            }
            else {
                if ( bElse ) {
                    strBuilder.append($c2.text);
                }
            }
            System.out.println("ifdef content is : " + strBuilder.toString() + "\n" );
        }
    ;

expr
    :   .+
    ;

ID
    :   ('a'..'z' | 'A'..'Z')+
    ;

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

およびJavaメインクラス

package Grammar;

import java.io.IOException;

import org.antlr.runtime.ANTLRFileStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenStream;

import Grammar.ifdefParser.rule_return;


public class mainifdef {

    public static void main(String[] args) throws RecognitionException {
        CharStream stream=null;
        try {
            stream = new ANTLRFileStream("src/input/test.txt");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        ifdefLexer lexer = new ifdefLexer(stream);
        TokenStream tokenStream = new CommonTokenStream(lexer);
        ifdefParser parser = new ifdefParser(tokenStream);
        rule_return evaluator = parser.rule();

        System.out.println("Parsing Tree is \n" + evaluator.tree.toStringTree() + "\n");
        System.out.println("Evaluation is \n" + evaluator.strEval + "\n");

    }
}

次のような入力ファイルの内容を使用します。

#undef Z
set AB = "toto";
セット CD = "titi";

diff(CD,"essai")
#ifdef(Z) add( #end

add ( AB , diff( CD,"essai") )

結果コンソールは期待どおりです

ifdef の内容は次のとおりです。

解析ツリーは
# undef Z set AB = "toto" です。セット CD = "titi"; diff(CD,"essai") #ifdef(Z) add(#end add(AB,diff(CD,"essai"))

評価は
「チチ」-「エッサイ」
「トト」+「チチ」-「エッサイ」

私の質問は、同じ結果が得られるはずの入力テキストを評価する方法です。

#undef Z
set AB = "toto";
セット CD = "titi";

diff(CD,"essai")
#ifdef(Z) add( #end

add ( AB , #ifdef(Z) add( #else diff( #end CD,"essai") )

結果のコンソールは次のとおりです (これは通常の ANTLR の動作です)。

ifdef の内容は次のとおりです。

src/input/test.txt 行 8:11 入力 '#' に実行可能な代替手段がありません
src/input/test.txt 行 8:43 'CD' に EOF がありません
ifdef の内容は : diff(

解析ツリーは
# undef Z set AB = "toto" です。セット CD = "titi"; diff ( CD , " essai " ) # ifdef ( Z ) add ( # end add ( AB , < 予想外: [@59,94:94='#',< 6 >,8:11], resync=# > < missing ')'> # ifdef ( Z ) add ( # else diff ( # end < missing EOF >

評価は
「チチ」-「エッサイ」
「トト」+ヌル

どこから始めるべきかについてのいくつかのガイダンスは、はるかに高く評価されます
よろしく JPM

4

0 に答える 0