まとめ 【トークン読み込み用クラス (各言語共通)】

TokenReaderCommon.cs


using System;

namespace SourceToHtml
{
//*******************************************************************************************************
// トークンごとに 文字列と その種類を返す ( 共通 )
//*******************************************************************************************************
public abstract class TokenReaderCommon : TokenReader
{
//予約語 コレクション
protected System.Collections.Specialized.StringCollection _keyWords;

//演算子 コレクション
protected string _operators;
//---------------------------------------------------------------------------------------------------
// 初期化
//---------------------------------------------------------------------------------------------------
protected TokenReaderCommon(Reader reader, string langType) : base(reader, langType)
{
//予約語 コレクションを設定
initKeyWord(langType);

//演算子 コレクションを設定
initOperator(langType);
}
//---------------------------------------------------------------------------------------------------
// 終了
//---------------------------------------------------------------------------------------------------
~TokenReaderCommon()
{
_keyWords = null;
}
//---------------------------------------------------------------------------------------------------
// 予約語 コレクションを設定
//---------------------------------------------------------------------------------------------------
private void initKeyWord(string langType)
{
//予約語 コレクションを設定 (".\cs7\key.txt")
_keyWords = new System.Collections.Specialized.StringCollection();

//予約語ファイルがなければ、予約語コレクションは空っぽ
if (System.IO.File.Exists(System.Windows.Forms.Application.StartupPath + "\\" + langType + "\\key.txt"))
{
System.IO.StreamReader keyReader = new System.IO.StreamReader(System.Windows.Forms.Application.StartupPath + "\\" + langType + "\\key.txt", System.Text.Encoding.GetEncoding("Shift_JIS"));
string s;
while ((s = keyReader.ReadLine()) != null)
{
_keyWords.Add(s);
}
keyReader.Close();
keyReader = null;
}
}
//---------------------------------------------------------------------------------------------------
// 演算子 コレクションを設定
//---------------------------------------------------------------------------------------------------
private void initOperator(string langType)
{
_operators = "";

//演算子ファイルがなければ、演算子コレクションは空っぽ
if (System.IO.File.Exists(System.Windows.Forms.Application.StartupPath + "\\" + langType + "\\ope.txt"))
{
System.IO.StreamReader opeReader = new System.IO.StreamReader(System.Windows.Forms.Application.StartupPath + "\\" + langType + "\\ope.txt", System.Text.Encoding.GetEncoding("Shift_JIS"));
string s;
while ((s = opeReader.ReadLine()) != null)
{
_operators += s;
}
opeReader.Close();
opeReader = null;
}
}
//---------------------------------------------------------------------------------------------------
// 状態を更新
//---------------------------------------------------------------------------------------------------
protected override void getNextToken()
{
base.getNextToken();

do
{
if (_context.State == "その他") getNextStateOther();
else if (_context.State == "演算子") getNextStateOther();
else if (_context.State == "区切り記号") getNextStateOther();
else if (_context.State == "不明") getNextStateOther();
else if (_context.State == "単一行コメント") getNextStateComSin();
else if (_context.State == "複数行コメント") getNextStateComMul();
else if (_context.State == "文字列") getNextStateStr();
else if (_context.State == "文字列中のエスケープシーケンス") getNextStateStrEsc();
else if (_context.State == "逐語的文字列") getNextStateStrLit();
else if (_context.State == "文字") getNextStateCha();
else if (_context.State == "文字中のエスケープシーケンス") getNextStateChaEsc();
else if (_context.State == "識別子") getNextStateIdw();
else if (_context.State == "エスケープされた識別子") getNextStateIdwEsc();
else if (_context.State == "数字") getNextStateNum();
else if (_context.State == "ディレクティブ") getNextStateDir();
else if (_context.State == "日付") getNextStateDtm();

} while(_context.State == "不明");
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (その他・区切り記号・不明)
//---------------------------------------------------------------------------------------------------
private void getNextStateOther()
{
_context.State = "その他";
_context.nextToken.tokenKind = "その他";

// 状態を更新
if (IsIdent()) _context.State = "識別子";
else if (IsEscape()) _context.State = "エスケープされた識別子";
else if (IsNumber()) _context.State = "数字";
else if (IsDirective()) _context.State = "ディレクティブ";
else if (IsComSingle()) _context.State = "単一行コメント";
else if (IsComMulti()) _context.State = "複数行コメント";
else if (IsString()) _context.State = "文字列";
else if (IsChar()) _context.State = "文字";
else if (IsLiteral()) _context.State = "逐語的文字列";
else if (IsDate()) _context.State = "日付";
else if (IsDelim()) _context.State = "区切り記号";
else if (IsOperator()) _context.State = "演算子";
else _context.State = "その他";

// トークンの種類を取得
if (_context.State == "逐語的文字列") _context.nextToken.tokenKind = "文字列";
else if (_context.State == "エスケープされた識別子") _context.nextToken.tokenKind = "識別子";
else if (_context.State == "単一行コメント") _context.nextToken.tokenKind = "コメント";
else if (_context.State == "複数行コメント") _context.nextToken.tokenKind = "コメント";
else if (_context.State == "日付") _context.nextToken.tokenKind = "文字列";
else _context.nextToken.tokenKind = _context.State;
}
//---------------------------------------------------------------------------------------------------
// 単一行コメントか?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsComSingle()
{
return ((_context.currChar == '/') && (_context.nextChar == '/'));
}
//---------------------------------------------------------------------------------------------------
// 複数行コメントか?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsComMulti()
{
return ((_context.currChar == '/') && (_context.nextChar == '*'));
}
//---------------------------------------------------------------------------------------------------
// 文字列か?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsString()
{
return false;
}
//---------------------------------------------------------------------------------------------------
// 文字か?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsChar()
{
return false;
}
//---------------------------------------------------------------------------------------------------
// 逐語的文字列か?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsLiteral()
{
return false;
}
//---------------------------------------------------------------------------------------------------
// ディレクティブか?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsDirective()
{
return false;
}
//---------------------------------------------------------------------------------------------------
// 識別子か?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsIdent()
{
return (Char.IsLetter(_context.currChar) || (_context.currChar == '_'));
}
//---------------------------------------------------------------------------------------------------
// エスケープされた識別子か?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsEscape()
{
return false;
}
//---------------------------------------------------------------------------------------------------
// 数字か?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsNumber()
{
return (Char.IsDigit(_context.currChar));
}
//---------------------------------------------------------------------------------------------------
// 演算子か?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsOperator()
{
if (Char.IsPunctuation(_context.currChar) || Char.IsSymbol(_context.currChar))
{
if (_operators.IndexOf(_context.currChar) >= 0) return true;
}
return false;
}
//---------------------------------------------------------------------------------------------------
// 区切り記号か?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsDelim()
{
if (Char.IsPunctuation(_context.currChar) || Char.IsSymbol(_context.currChar))
{
if (_operators.IndexOf(_context.currChar) < 0) return true;
}

return false;
}
//---------------------------------------------------------------------------------------------------
// 日付か?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsDate()
{
return false;
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (単一行コメント)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateComSin()
{
_context.State = "単一行コメント";
_context.nextToken.tokenKind = "コメント";

if (_context.currChar == '\n')
{
_context.State = "その他";
_context.nextToken.tokenKind = "その他";
}
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (複数行コメント)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateComMul()
{
_context.State = "複数行コメント";
_context.nextToken.tokenKind = "コメント";

if ((_context.prevChar == '*')
&& (_context.currChar == '/'))
_context.State = "その他";
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (文字列)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateStr()
{
_context.State = "文字列";
_context.nextToken.tokenKind = "文字列";

// 各派生クラスで処理する
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (文字列中のエスケープシーケンス)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateStrEsc()
{
_context.State = "文字列";
_context.nextToken.tokenKind = "文字列";
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (逐語的文字列)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateStrLit()
{
_context.State = "逐語的文字列";
_context.nextToken.tokenKind = "文字列";

// 各派生クラスで処理する
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (文字)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateCha()
{
_context.State = "文字";
_context.nextToken.tokenKind = "文字";

// 各派生クラスで処理する
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (文字中のエスケープシーケンス)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateChaEsc()
{
_context.State = "文字";
_context.nextToken.tokenKind = "文字";
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (識別子)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateIdw()
{
_context.State = "識別子";
_context.nextToken.tokenKind = "識別子";

if (!Char.IsLetter(_context.currChar) && !Char.IsDigit(_context.currChar) && (_context.currChar != '_'))
{
_context.State = "不明";

//文字種が変わったら、識別子が 予約語ではないか 確認する
string keyWord;
if ((keyWord = getKeyWord()) != "")
{
_context.currToken.tokenKind = "予約語";
_context.currToken.tokenString = keyWord;
}
}
}
//---------------------------------------------------------------------------------------------------
// 予約語ではないか?
//---------------------------------------------------------------------------------------------------
protected virtual string getKeyWord()
{
return "";
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (エスケープされた識別子)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateIdwEsc()
{
_context.State = "エスケープされた識別子";
_context.nextToken.tokenKind = "識別子";

// 各派生クラスで処理する
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (数字)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateNum()
{
_context.State = "数字";
_context.nextToken.tokenKind = "数字";

if ((_context.currChar == '.') && (_context.nextChar == '.'))
_context.State = "不明";

else if (!Char.IsLetter(_context.currChar) && !Char.IsDigit(_context.currChar) && (_context.currChar != '.'))
{
_context.State = "不明";

// "+" か "-" で
if ((_context.currChar == '+') || (_context.currChar == '-'))
{
//1つ前の文字が "e" か "E" で
if ((_context.prevChar == 'e') || (_context.prevChar == 'E'))
{
//16進表記でなければ、数字
if (IsNotHex())
_context.State = "数字";
}
}
}
}
//---------------------------------------------------------------------------------------------------
// 16進表記か?
//---------------------------------------------------------------------------------------------------
protected virtual bool IsNotHex()
{
// 0x で始まっていたら、16進
if (_context.currToken.tokenString.Length > 1)
if (_context.currToken.tokenString[0] == '0')
if ((_context.currToken.tokenString[1] == 'x') || (_context.currToken.tokenString[1] == 'X'))
return false;

return true;
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (ディレクティブ)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateDir()
{
_context.State = "ディレクティブ";
_context.nextToken.tokenKind = "ディレクティブ";

// 各派生クラスで処理する
}
//---------------------------------------------------------------------------------------------------
// 状態を更新 (日付)
//---------------------------------------------------------------------------------------------------
protected virtual void getNextStateDtm()
{
_context.State = "日付";
_context.nextToken.tokenKind = "文字列";

// 各派生クラスで処理する (VBだけ)
}
}
}