VisualBasic に対応する

VisualBasic に対応する

VisualBasic用に処理を変更しなければいけないのは、
・「'」以降は単一行コメント
・複数行コメントはない
・「"」〜「"」は文字列
・「#」〜「#」は日付
・「[」〜「]」は識別子
・8進表記は「&O」ではじまる
・16進表記は「&H」ではじまる
・「型文字」という先行する識別子の型を表す記号があり、
 「#」は、Double型をあらわす。
・「#End Region」「#End If」という「ディレクティブ」があるため、
 英字以外の文字が現れた時点では、「ディレクティブの終了」という判断ができない
・ファイルアクセス時の構文にも「Close #FileNumber」のように
 「#」を使用するので、「#」で始まる文字列を「ディレクティブ」とは判断できない
などである。

結局、「#」から始まる英字の文字列が「ディレクティブ」かどうかは判定のしようがなく、
予約語として扱う以外に方法がない。
また「#」から始まる文字列が「日付」かどうかは、
前のトークンが、「演算子」かどうかで判断することにした。


//読み込んだ文字の種類を取得・状態を更新
protected override Token getCurrToken(char cPrev, char cCurr, char cNext)
{
Token currToken = new Token(cCurr.ToString(), "その他");

do
{
if ((_state == "その他") || (_state == "区切り記号") || (_state == "不明"))
{
if (cCurr == '\"')
_state = "文字列";

else if (cCurr == '\'')
_state = "単一行コメント";

else if (cCurr == '[')
_state = "特殊文字";

else if (cCurr == '#')
{
_state = "区切り記号";

if ((prevToken != null) && (prevToken.tokenKind == "演算子"))
_state = "日付";
}
else if (cCurr == '&')
{
if (_state == "不明")
_state = "区切り記号";
else
{
if ((Char.ToLower(cNext) == 'o') || (Char.ToLower(cNext) == 'h'))
_state = "数字";
else
_state = "区切り記号";
}
}

else if (Char.IsLetter(cCurr) || (cCurr == '_'))
_state = "識別子";

else if (Char.IsDigit(cCurr))
_state = "数字";

else if (Char.IsPunctuation(cCurr) || Char.IsSymbol(cCurr))
_state = "区切り記号";

else
_state = "その他";

if (_state == "単一行コメント")
currToken.tokenKind = "コメント";

else if (_state == "特殊文字")
currToken.tokenKind = "識別子";

else if (_state == "区切り記号")
{
if (_operators.IndexOf(cCurr) >= 0)
currToken.tokenKind = "演算子";
else
currToken.tokenKind = "区切り記号";
}
else
currToken.tokenKind = _state;
}

else if (_state == "単一行コメント")
{
currToken.tokenKind = "コメント";

if (cCurr == '\n')
{
currToken.tokenKind = "その他";
_state = "その他";
}
}

else if (_state == "文字列")
{
currToken.tokenKind = "文字列";

if (cCurr == '\"')
_state = "その他";
}

else if (_state == "特殊文字")
{
currToken.tokenKind = "識別子";

if (cCurr == ']')
_state = "その他";
}

else if (_state == "識別子")
{
currToken.tokenKind = "識別子";

if (!Char.IsLetter(cCurr) && !Char.IsDigit(cCurr) && (cCurr != '_'))
{
_state = "不明";

//文字種が変わって、前のトークンが、"." でなければ、識別子が 予約語ではないか 確認する
if ((prevToken != null) && (prevToken.tokenString != "."))
{
int idxKeyWord = _keyWordsNoCase.IndexOf(mikakuteiToken.tokenString.ToLower());
if (idxKeyWord > 0)
{
mikakuteiToken.tokenKind = "予約語";
mikakuteiToken.tokenString = _keyWords[idxKeyWord];
}
}
}
}

else if (_state == "数字")
{
currToken.tokenKind = "数字";

if (!Char.IsLetter(cCurr) && !Char.IsDigit(cCurr) && (cCurr != '.'))
{
if ((cCurr == '+') || (cCurr == '-'))
{
//1つ前の文字が "e" か "E" か
if ((cPrev == 'e') || (cPrev == 'E'))
{
//16進表記か?
if ((mikakuteiToken.tokenString.Length > 1) && (mikakuteiToken.tokenString[0] == '&'))
_state = "不明";
}
else
_state = "不明";
}
else
_state = "不明";
}
}

else if (_state == "日付")
{
currToken.tokenKind = "日付";

if (cCurr == '#')
_state = "その他";
}

} while(_state == "不明");

return currToken;
}