« NonRuleBasedDamagerRepairerって | トップページ | IAdaptableとは?(前編) »

2004.01.08

キーワードRuleの作成方法

DbEditプラグインについてくるSQLエディタを逆コンパイルしたら・・・出てきました!参考になる代物が!

それはIRuleインタフェースの直実装として作成された,SQL文のキーワード(SELECTやCREATEなど)を検出するルールクラスです。

とりあえずソースはこれ。

class SQLWordRule implements IRule {
  private Map keywords;
  private IToken defaultToken;
  public IToken evaluate(ICharacterScanner scanner) {
    char c = (char)scanner.read();
    if (Character.isLetter(C)) {
      StringBuffer value = new StringBuffer();
      do {
        value.append(c);
        c = (char)scanner.read();
      } while(Character.isLetterOrDigit(c) || c == '_');
      scanner.unread();
      IToken token =
        (IToken)keywords.get(value.toString().toUpperCase());
      return (token != null) ? token : defaultToken;
    } else {
      scanner.unread();
      return Token.UNDEFINED;
    }
  }
}

keywordsフィールドは,キーワード文字列をキーとし,それに対応するITokenオブジェクトを値として持つコレクション。defaultTokenフィールドは,このルールに適用されないと判断された場合に返却するITokenオブジェクト。

そしてevaluateメソッドが,このルールクラスの心臓部。scannerオブジェクトのreadメソッドを呼んで,一文字ずつ文字列を取り出していき,文字ごとにチェックを行うという地道な作業。ここでは,SQL文のキーワードは「汎用文字で始まり,2文字目以降は汎用文字あるいは数字もしくはアンダーバーが許可される」というルールに基づいてチェックしている。そんでもって,キーワードのルール外の文字が来たらscannerから文字を取り出すのをやめて,最後に取り出した一文字をunreadメソッドでもどしておく(キーワードに含まれないため)。この作業でキーワードの候補の文字列が出来上がるので,keywordsコレクションにそのキーワードが存在するかどうかをチェックし,もしあればそのキーワードに対応するITokenオブジェクトを,もしなければdefaultTokenオブジェクトをevaluateメソッドの結果として返却しています。

一文字目から文字じゃなかった場合は,その文字をunreadメソッドで元にもどして,Token.UNDEFINEDを結果として返却している。これ,なぜdefaultTokenオブジェクトじゃないんだろう・・・?これだけ謎。

テキストエディタ内の任意の場所でのルールは,基本的に上記のコードがすべてを物語っていると思われる。これに,行中の左から何文字目からのルール,とか,行末まで,とかが加味されると,PlatformAPIについてくる各種Ruleクラスになるのね,って理解でいいかな。

このコードを見つけるまで,SingleLineやらWordRuleやらを見て四苦八苦してたけど,基本形がなんとなく見えてきたので何とかなりそうな気配。ちょっと進んだかな。

|

« NonRuleBasedDamagerRepairerって | トップページ | IAdaptableとは?(前編) »

コメント

IRuleインタフェースのAPIリファレンスを見ると,ルールに一致しないと判断された場合には,返却されるITokenオブジェクトはisUndefinedを呼び出したときにtrueが返られなければならない,と記載されていた。もしルールに一致しない場合はToken.UNDEFINEDを返すとともに,スキャナから読み込んだ文字をunreadメソッドを使って戻さなければならない(でないと他のルールが評価できなくなる?)。
上記のコードで単にdefaultTokenを返すところをToken.UNDEFINEDを返すようにしてしまっては,そこまで読み込んだ文字がunreadされないままになってしまう。実際にやってみると,ルールに適合と判断された文字列の途中で改行を入れた場合に本来はルールに適合されなくなるはずなのに,色付けが解除されないといった不具合が発生する。
用意されたキーワードに一致しない文字列だと判断された場合は,上記のコードのようにデフォルトのトークンを返すのではなく,読み込んだ文字をすべてunreadしてToken.UNDEFINEDを返すべきなのかもしれない。。。

投稿: よういちろう | 2004.01.10 04:54 午後

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/12631/83246

この記事へのトラックバック一覧です: キーワードRuleの作成方法:

« NonRuleBasedDamagerRepairerって | トップページ | IAdaptableとは?(前編) »