Token ごとに処理する

Token ごとに処理する

これまで、ソースを1文字ずつ返す関数を利用して来たが、
文字列を1区切りごとに、文字列の種類とともに返してくれる関数 getToken があれば便利である。

たとえば、「private string s = "a"; //文字列」という文字列を読み込んだ場合、

1private 予約語
2  その他
3string 予約語
4  その他
5s 識別子
6  その他
7= 演算子
8  その他
9"a" 文字列
10; 区切り記号
11  その他
12//文字列コメント
13\n その他
が、返ってくる。

呼び出し側では、文字列の種類に応じた色指定タグで挟んで出力する。


//*********************************************************************
// HTML に書式化して出力
//*********************************************************************
public void tohtml(Reader reader, Writer writer)
{
//ファイルの終わりまで、1区切りずつ読んで
Token token;
while((token = getToken(reader)) != null)
{
//文字列の種類に応じた色指定タグで挟んで出力する
if (token.tokenKind == "予約語")
{
writer.putString("<FONT COLOR=\"BLUE\">");
writer.putString(token.tokenString);
writer.putString("</FONT>");
}
else if (token.tokenKind == "コメント")
{
writer.putString("<FONT COLOR=\"GREEN\">");
writer.putString(token.tokenString);
writer.putString("</FONT>");
}
else
{
writer.putString(token.tokenString);
}
}
}
//*********************************************************************
// 文字列情報クラス
//*********************************************************************
private class Token
{
internal string tokenString;
internal string tokenKind;
}

いきなり、Token ごとの処理を実現するのも骨が折れるので、
まずは、「1文字ずつ読んで1文字ずつ返す」
これまでと同じ処理のgetToken を作成する。


//*********************************************************************
// 1区切りの文字列と 文字列の種類を返す
//*********************************************************************
private int _col = 0; //現在位置を保持
private Token getToken(Reader reader)
{
//ファイルの終わりまで、1文字ずつ読んで
char c = reader.getChar();

//ファイルの終わり
if (c == EOF) return null;

Token token = new Token();

if (c == TAB) //TAB文字なら
{
//TAB位置まで空白で埋める
string s = "";
do
{
s += BLANK; //空白を追加
} while (!TabPos(++_col)); //TAB位置まで進んだら抜ける
token.tokenString = s; //文字列情報を設定
token.tokenKind = "その他";
return token;
}

//TAB でなければ
if (c == NEWLINE) //改行コードなら
{
_col = 0; //現在位置をクリア
}
else //TABでも 改行コードでも なければ
{
_col += getLength(c); //現在位置を文字幅だけ進める
}

token.tokenString = getHtmlChar(c); //"<",">","&" を変換して出力
token.tokenKind = "その他";
return token;
}