パーサを作り始めよう

ゲームに簡単なプログラムを組み込むためにスクリプト言語とそれを実行するインタープリタをC++で作ってしまおうというコーナーです。
前回で数式に使う字句のスキャナができました。

木構造の接点(ノード)

タイトルの通り、いよいよ構文解析を行うパーサを作り始めます。
構文解析をするということは、つまり前回まででできたトークン列から木構造を作るというわけで、木構造を構成するのは接点とそれらを繋ぐ枝であって、接点と接点の繋がりがつまり枝というわけで、要するに何が言いたいのかというと、木の接点というものを用意してやればとりあえず始められるかなと思ったわけです。

class CMSNode
{
};

接点はノードとも言うのでノードのクラスを作ってみました。

ノードの種類とか

さて、ノードの種類として、第7回でEとかTとかFとか決めたので、それらを表現できるようにこれを拡張してみましょう。
やっぱりまた第11回の時のように派生クラスにしてみましょうか。
とりあえずEを表すクラスでも作ってみましょう。

class CMSNodeE : public CMSNode
{
};

でも、Eといったって、分解したら「T」になるEと「E PM T」になるEの2種類があるわけです。そしたらそれぞれについて更に派生クラスを作らなきゃいけません。

class CMSNodeE_T : public CMSNodeE
{
};

class CMSNodeE_E_PM_T : public CMSNodeE
{
};

う~ん……これだったらいちいちCMSNodeEを経由せずにいきなりCMSNodeからCMSNodeE_TやCMSNodeE_E_PM_Tにしちゃっていいかも…。
もうちょっと考えてみましょう。
ノードの種類には今のところ、E、T、F、N、PM、MD、BS、BE、の8種類があります。
どの種類のノードなのか判別がつかないと構文解析のしようがないのでCMSNode及び派生クラスにはそのあたりの情報を乗せるべきでしょう。

enum EMSNodeType {
	eMSNodeE,
	eMSNodeT,
	eMSNodeF,
	eMSNodeN,
	eMSNodePM,
	eMSNodeMD,
	eMSNodeBS,
	eMSNodeBE,
};

class CMSNode
{
public:
	virtual EMSNodeType GetNodeType() = 0;
};

class CMSNodeE : public CMSNode
{
public:
	EMSNodeType GetNodeType() { return eMSNodeE; }
};

class CMSNodeE_T : public CMSNodeE
{
};

class CMSNodeE_E_PM_T : public CMSNodeE
{
};

う~ん……CMSNodeEの段階では何の動作が起こるかわからないので動作は何もできないし、GetNodeType関数を派生クラスのほうに移動すればCMSNodeEは何もやらなくてよくなるし、やっぱりCMSNodeEはいらなさそうです。
まあ、要するに、外から見える種類としては「E」だけど、中身でやってることは「E ::= T」や「E ::= E PM T」ですよ、ということです。
だから、実際にはCMSNodeE_TやCMSNodeE_E_PM_Tとして異なる動作をしながら、外向きにはGetNodeTypeで同じeMSNodeEを見せておくというわけです。
なんだかわかりにくい説明でごめんなさい。

値がどうたら

第10回で何でもかんでも値をもつと書いたのは、つまり木のノード全てが値を持つということなんです。
あまり深く考えずにまたポインタを保持しておくことにします。
具体的にどうするかは後で考えます。

class CMSNode
{
public:
	virtual EMSNodeType GetNodeType() = 0;
	CMSValue* m_pValue;
};

今回までのソース(VC++6)