public class TokenReader extends Object
トークン定義に従ってトークン解析を行います.
正規表現でトークンパターンを指定するトークン解析機です。コンテキスト 制御や、開始パターン、終了パターン定義指定などの機能も持ちます。 トークン定義はXMLで行います。
単体でも使用できますが、通常はSyntaxReader
の中で使われます。
SyntaxReaderで指定する<TKN_DEF>によるトークン定義と
本クラスでの定義法は同じです。。
XMLによる定義をTokenReaderに与えた上で、解析すべき入力を与え、 後はreadで回るというのが使い方の基本です。
TokenReader reader= new TokenReader(); reader.readDefinitionXML("tokenDef.xml"); reader.parse("sampleSyntax.text"); Token token=new Token(); while( reader.read(token)!=Token.EOF ){ System.out.println("token="+token); //.. }
逆ポーランド方式の整数計算機(名前メモリー機能付き)のサンプルを載せました。 [an error occurred while processing this directive]
// サンプルプログラム import otsu.hiNote.*; import otsu.symphonie.*; import java.util.*; import java.io.*; class test01 { static Stack<Integer> stack = new Stack<Integer>(); static HashMap<String,Integer> variables = new HashMap<String,Integer>(); public static void main(String[] args_){ try{ TokenReader _reader= new TokenReader(); _reader.readDefinitionXML("tokenDef.xml"); _reader.parse("SampleIn.txt"); Token _token=new Token(); boolean assign_flag=false; while( _reader.read(_token)!=Token.EOF ){ if( _token.name.equals("NUMBER") ){ stack.push(Integer.parseInt(_token.text)); } else if( _token.name.equals("ASSIGN") ){ assign_flag= true; continue; } else if( _token.name.equals("NAME") ){ if( assign_flag ){ assign_flag=false; Integer _ans; if( stack.isEmpty() ) { System.out.println("error: value lacked"); continue; } _ans= stack.pop(); stack.clear(); variables.put(_token.text,_ans); System.out.println("Assign "+_ans+" to "+_token.text); continue; } else{ Integer _i= variables.get(_token.text); if( _i==null ){ System.out.println("error: "+_token.text+" not defined"); _i = 0; } stack.push(_i); } } else if( _token.name.equals("OPERATION") ){ if( stack.size()<2 ){ System.out.println("error: value lacked"); continue; } Integer _i2= stack.pop(); Integer _i1= stack.pop(); if( _token.text.equals("+") ){ stack.push(_i1+_i2); } else if( _token.text.equals("-") ){ stack.push(_i1-_i2); } else if( _token.text.equals("*") ){ stack.push(_i1*_i2); } else if( _token.text.equals("/") ){ stack.push(_i1/_i2); } } System.out.println(_token.text+" : "+stack); } } catch(Exception e){ e.printStackTrace(hiU.err); } } } // サンプルトークン定義 <?xml version="1.0" encoding="UTF-8"?> <definition> <TKN_DEF pattern="[ \t\n]*"/> <TKN_DEF pattern="//.*$"/> <TKN_DEF name="OPERATION" pattern="[\-+/*]" /> <TKN_DEF name="ASSIGN" pattern="="/> <TKN_DEF name="CLEAR" pattern=";"/> <TKN_DEF name="NUMBER" pattern="[0-9][9-9]*"/> <TKN_DEF name="NAME" pattern="[a-zA-Z_][0-9a-zA-Z_]*" /> </definition> // TokenReader 逆ポーランド計算機プログラム入力サンプル 1 2 3 * + = aa 4 aa * 5 3 - / = bb aa bb - = cc // 実行結果 1 : [1] 2 : [1, 2] 3 : [1, 2, 3] *: [1, 6] + : [7] Assign 7 to aa 4 : [4] aa : [4, 7] *: [28] 5 : [28, 5] 3 : [28, 5, 3] - : [28, 2] / : [14] Assign 14 to bb aa : [7] bb : [7, 14] - : [-7] Assign -7 to cc
トークン定義はXMLで与えます。
<!--トークン全体パターンを与える指定 --> <TKN_DEF name = "トークン名" 省略可※ pattern= "正規表現によるトークンパターン" 省略可※ on = "依存コンテキスト" 省略可 to = "新たなコンテキスト" 省略可 /> <!-- ※:name,patternのどちらかを省略することはできますが 両方省略することはできません --> <!-- トークンの開始パターンと終了パターンを指定する書き方 --> <TKN_DEF name = "トークン名" 省略可 start = "正規表現によるトークンの開始パターン" end = "正規表現によるトークンの終了パターン on = "依存コンテキスト" 省略可 to = "新たなコンテキスト" 省略可 > <TKN_ALT pttern= "正規表現による代替対象" alt = "代替文字列" /> 省略可複数可 </TKN_DEFv
これらの定義を複数並べます。基本的には先に書かれたパターンにマッチ すると後ろのパターンは検証されません。
空白や単純コメント
トークン名は省略可能で、省略した場合は、読み取った上で廃棄されます。
通常空白やコメントはトークン名を書かずに廃棄します。
<!-- 空白とC形式の行コメント --> <TKN_DEF pattern=" \t\n\r"/> <TKN_DEF pattern="//.*$"/>
単純キーワード
単純キーワードはnameとpatternに同じ値を書くか、nameだけを記述 することにより定義できます。
<!-- 単純キーワード定義 --> <TKN_DEF name="struct" pattern="struct"/> <TKN_DEF name="enum"/>
パターンワード
プログラム上での名前や数値などはname=でその型名を与え、pattern= で正規表現パターンを示します。
<!-- C風nameと整数値 --> <TKN_DEF name="NAME" pattern="[a-zA-Z_][0-9a-zA-Z_]*"/> <TKN_DEF name="INT_NUM" pattern="[0-9]+"/>
コンテキスト制御(例えばCのブロックコメントなどを実現)
特定コンテキスト(文脈)の場合のみ有効なパターンを定義できます。
パターンマッチ後移行するコンテキストを指定することもできます。
コンテキストは文字列による名前で示されます。デフォルトは"0"です。
特定のコンテキストの場合のみ有効な定義はon=で指定します。
移行するコンテキストはto=で指定します。
<!-- Cのブロックコメント --> <TKN_DEF pattern="/\*" to="com"/> "/*"でコンテキストをcomに切り替える <TKN_DEF pattern="\*/" on="com" to="0" /> "*/"でコンテキストをデフォルトに切り替える <TKN_DEF pattern="." on="com" /> コンテキストがcomの場合1文字を読み飛ばす 注意:このコードはjavadocの制限により半角の*の代わりに全角の*を使っています
開始終了パターン指定、文字置き換えのあるトークン(Cの文字列など)
開始パターンと終了パターンを指定してトークンを得ることができます。 開始パターン、終了パターン自体はトークンから外されます。
開始から終了の間に出てくるパターンの置き換え機能を持ちます。
次の定義は引用符から引用符までを1トークンとする定義です。
ただし、その中に現れるエスケープシーケンスとして\"を"に置き換え
\\を\に置き換えます。\は正規表現自体のエスケープ文字ですので
\を\\と書く必要があります。
<TKN_DEF name="string" start='"' end='"'> 引用符から引用符まで <TKN_ALT pattern="\\\\" alt="\"/> \\は\に置き換える <TKN_ALT pattern='\\"' alt='"'/> \"は"に置き換える </TKN_DEF>
コンストラクタと説明 |
---|
TokenReader() |
修飾子とタイプ | メソッドと説明 |
---|---|
String |
getContext()
文脈を得る.
|
void |
parse(BufferedReader br_)
解析するソースを設定する.
|
void |
parse(String fileName_)
解析するファイルを設定する.
|
void |
parse(String fileName_,
String charSet_)
解析するファイルを設定する.
|
int |
read(Token tkn_)
トークンを取得する.
|
void |
readDefinitionXML(InputStream is_)
XMLによるトークン定義を読み込む
|
void |
readDefinitionXML(String fileName_)
XMLによるトークン定義を読み込む
|
void |
setContext(String context_)
文脈を変える
|
void |
setSourceName(String sourceName_)
ソース名を設定する.
|
public int read(Token tkn_) throws Exception
tkn_
- トークン情報をセットするToken構造体Exception
- 失敗public String getContext()
public void setContext(String context_)
context_
- 文脈名public void parse(BufferedReader br_) throws Exception
この関数は直ちにリターンします。
この後read(Token)
を呼び出してください。
br_
- ソースException
- 失敗public void setSourceName(String sourceName_) throws Exception
parse(BufferedReader)
の場合ソースファイル名が
ないが、この関数で仮の名前を与えることができる。
parse(String)
の場合、この関数を呼ぶ必要はない
sourceName_
- ソース名Exception
- 失敗public void parse(String fileName_) throws Exception
この関数の中でオープンされます。
この関数は直ちにリターンします。
この後read(Token)
を呼び出してください。
fileName_
- ファイル名Exception
- 失敗public void parse(String fileName_, String charSet_) throws Exception
この関数の中でオープンされます。
この関数は直ちにリターンします。
この後read(Token)
を呼び出してください。
fileName_
- ファイル名charSet_
- 文字セットException
- 失敗public void readDefinitionXML(String fileName_) throws Exception
fileName_
- トークン定義ファイル名Exception
- 失敗public void readDefinitionXML(InputStream is_) throws Exception
is_
- トークン定義を読み込むストリームException
- 失敗