【c++】インタプリタを初めから丁寧に第03回
前回に引き続き字句解析プログラムの内容について考えます。
成田さんに添削していただいた部分も合わせて冗長な部分を削除した・・・つもりです。
- 演算子
- 制御文判別子
1. 演算子
まず、演算子について考えます。
演算子とは、いまさら確認するまでもないかもしれませんが a = b や a++ にある '=' や '++' のことです。
ちなみに上記の例はただ単に2個出しただけではありません。
演算子にも区別をしなければいけない点があます。
- 単項演算子
- 二項演算子
これらを判断しなければいけません。・・・といってもやはり考えることは簡単で、単に前の項が
- 識別子
- 整数
- 文字列
- 右括弧
- ブール型定数
の、いずれでもない場合は単項演算子、そうでない場合は二項演算子と判断できます。
次にその演算子がなんであるかを判別します。これは前回と同じでその文字列が'='や'++'であるかどうか文字列比較すれば判断できます。 しかし、演算子数が増えてくれば当然ながら配列に文字列を突っ込みそれを一個ずつ比較することになります。
ここで こちらの記事 を見ていただければ分かるように配列の数字が何をさしているのかわからないのはマズイ、ということがわかります。
つまり a_Operator[3] = '+' なんて書き方をすると後々チェックミスが起こるだけでなく、添削という形で怒られるハメになります。(実際自分はこのような書き方をしていたため、そのまま書いて怒られるところでした・・・。)
よって配列の中に何が入っているか明確にするためにa_Operator[OP_PLUS] = '+'のような書き方をします。
これらをふまえた上で演算子について判別するコードを書きます。
これで演算子が何であるかについて理解することができました。
2.制御文判別子
制御文判別子とは if や for, switch、また宣言に使われる int や string などのことです。 これも前述の演算子と同じように文字列比較で判別すればよいです。注意すべき点は。
- 定数にif_calcやifabcなどの定数が存在した場合、ifと混同しないようにする
これについては第二回にあるIsChar(char c)を使用していましたが、標準関数のint isalpha(char c)が存在するのでこちらを使用します。
実装については次のとおりです。
static const string a_Keyword[] = {
"KEYWORD_DEF_BEGIN",
"int", "string", "bool",... // 型宣言に使用する名前です
"KEYWORD_DEF_END",
"KEYWORD_OP_BEGIN",
"if", "for",... // 制御命令に使用する名前です
"KEYWORD_OP_END"
}
enum {
KEYWORD_DEF_BEGIN,
KEY_INT, KEY_STR, KEY_BOOL,...
KEYWORD_DEF_END,
KEYWORD_OP_BEGIN,
KEY_IF, KEY_FOR,...
KYEWORD_OP_END
}
// 制御文判別子を読み取る
bool ReadKeyword()
{
for(int id = KEYWORD_DEF_BEGIN + 1; id != KEYWORD_OP_END; id++)
{
int length = a_Keyword[id].length();
// 制御文判別子と判断できた場合
if(str.compare(Pos, length, a_Keyword[id])==0 && !isalpha(str[Pos+length]))
break;
}
if(id == KEYWORD_OP_END) return false;
Tokens.push_back(CToken(id, 0, a_Keyword[id])
Pos += length;
return true;
} |
以上で制御文判別子も理解することができるようになりました。 次回に3.区切り記号と4.関数判別子を実装し、字句解析は終了になります。

コメント (1)
字句解析 (lexical analysis) と意味解析 (semantic analysis) がごっちゃになっています。
処理のフェイズをきちんと分離させた方が良いですね。
投稿者: なりた | 2007年12月09日 17:54