コードのどこにでも置くことができる 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( #endadd ( 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( #endadd ( 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