 
[例題のプログラミング言語の文法]
(1)構文解析の処理
文種別ごとに,
式部分を分離し,逆ポーランド変換を行い,文ごとの解釈を行います。
文の中には,IfブロックやWhileブロックのように,
離れた部分にジャンプしたり,
後から前の部分を参照するような処理が必要となります。
またこれらのブロック中に,同様のブロックを挿入できます。
すなわち,制御構造をネストさせることができます。
これらを処理するためのスタックを用意します。
public struct BlockData // ブロックコントロールデータ
{
public string Type;
public int BP;
public int IfP;
public int ThenP;
}
public BlockData [] IfStack=new
BlockData[200];
public int IfStackP=0;
public BlockData [] DoStack=new
BlockData[200];
public int DoStackP=0;
public int[] numBreak=new int[200]; //
Break処理用テーブル
public int[,] BreakP=new int[200,200];
トレース用ルーチン
private void debugSA(int i)
{
listBox2.Items.Clear();string
S="";
for(int k=0;k<numPolish;k++)
{
string X=Polish[k].operation+
"\t" + Polish[k].str;
S="\n"+X;
listBox2.Items.Add(X);
}
DialogResult result =
MessageBox.Show(S,"構文解析途中経過2",MessageBoxButtons.OKCancel);
if(result==DialogResult.Cancel)
checkBox1.Checked=false;
}
(2)中間コードの展開形式
デバッグでソースプログラムの文番号を表示可能とするために,
StNo 文番号
(文の中間コード群)
の形式で出力します。
代入文では,逆ポーランド記法そのものを中間コード群とします。
その他の文は,以下のとおりとします。
(a) if文
(論理式の逆ポーランド記法)
IfP: L1 push (elseでL1を設定)
then
(then以降のオブジェクト)
ThenP: L2 push (elseでThenP設定,endifでL2を設定)
goto
L1:
(Else以降のオブジェクト)
L2:
または,ThenPがないとき,すなわちelseがなかったとき
(論理式の逆ポーランド記法)
IfP: L2 push (endifでL2を設定)
then
(then以降のオブジェクト)
L2:
なお,「then」という命令は,
スタック上の2つデータをポップし,後からポップした値が偽であれば,
先にポップした値をプログラムカウンタの値にする(ジャンプする)命令と
とします。
「goto」という命令は,ポップした値を
プログラムカウンタの値にする(ジャンプする)命令とします。
(b) while文
Bp:
(論理式の逆ポーランド記法)
IfP: L1 push (wendでL1を設定)
then
(while以降のオブジェクト)
ThenP: Bp push
goto
L1:
(wendでL1をbreakに設定)
(c) repeat文
Bp:
(repeat以降のオブジェクト)
(論理式の逆ポーランド記法)
ThenP: Bp push
then
L1:
(untilでL1をbreakに設定)
(d) for文
(初期化式の逆ポーランド記法)
L1 push
goto
Bp: (増分式の逆ポーランド記法)
L1: (判定式の逆ポーランド記法)
L2 push (nextでL2を設定)
then
(for以降のオブジェクト)
Bp push
goto Bp
L2:
(nextでL2をbreakに設定)
(e) function文(関数名テーブルに登録)
*Pstart*
*Parm 引数名1
*Parm 引数名2
|