1.実験の目的:
特定の文法に従って再帰降下分析プログラムをコンパイルおよびデバッグして、入力シンボル文字列を分析します。この実験の目的は、再帰的降下分析の理解を深めることです。
2.実験前のリマインダー
1.再帰降下分析の機能
レキシカルアナライザーの機能は、関数間の再帰呼び出しを使用して、構文ツリーのトップダウン構造をシミュレートすることです。
2.再帰降下解析法の前提
文法の変更:曖昧さを排除し、左再帰を排除し、左因子を抽出し、それがLL(1)文法であるかどうかを判断し、
3.再帰的降下分析法の実験的設計アイデアとアルゴリズム
Gの非終端記号Uごとに再帰プロセスを作成します。これはUという名前にすることができます。
Uのプロダクションの右側は、このプロセスのコード構造を示しています。
(1)終末記号の場合は、前向き記号と比較して、
一致する場合は1シンボル進みます。一致しない場合は、エラーが発生します。
(2)非終端記号の場合は、この非終端記号に対応するプロシージャを呼び出します。Aの右側に複数の作品がある場合は、選択構造で実現できます。
具体的には:
(1)各非終端記号U→X1 | X2 | ... | Xnの処理方法は次のとおりです。
U()
{{
Read(ch); //現在のシンボル
First(X1)のchがX1のサブルーチンを呼び出す場合。
それ以外の場合、First(X2)のchがX2のサブルーチンを呼び出します。
…
else error()
}
(2)各右部X1→Y1Y 2 ... Ynの処理アーキテクチャは次のとおりです。
Y1のサブルーチンを呼び出します。
Y2のサブルーチンを呼び出します。
…
Ynのサブルーチンを呼び出す
(3)右の部分が空の場合、処理されません。
(4)右側の各記号Yiについて
①Yiが端末記号の場合:
if(Yi = =現在のシンボル)
{{
Read(ch); //
戻る;
}
else error()
②Yiが非終端記号の場合、対応するサブプロシージャYi()を直接呼び出します。
3.実験プロセスとガイダンス:
(1)準備:
1.教科書の関連する章を読みます。
2.設計計画を検討します。
3.モジュール構造を設計し、データをテストし、最初にプログラムを準備します。
(2)手順要件:
プログラムの入力/出力の例:
次の文法では、再帰的降下分析方法を使用して、入力シンボル文字列を分析します。
(1)E→TG
(2)G→+ TG | -TG
(3)G→ε
(4)T→FS
(5)S→* FS | / FS
(6)S→ε
(7)F→(E)
(8)F→i
出力形式は次のとおりです。
(1)再帰的降下分析プログラム、作成者:名前、学生番号、クラス
(2)#で終わる記号文字列を入力します(+ — /()i#を含む):この位置に記号文字列を入力します。例:i + i i#
(3)出力結果:i + i * i#は有効なシンボル文字列です
備考:i + i *#などの入力シンボル文字列では、出力が「不正なシンボル文字列」である必要があります。
注:1。演算子(+-* /)、区切り文字(括弧)、文字i、およびターミネーター#を式に使用できます。
2.誤った式に遭遇した場合は、エラーメッセージを出力する必要があります(情報が詳細であるほど良い)。
3.学習能力のある学生の場合、導出プロセスを詳細に出力できます。つまり、各ステップで使用された作品を詳細にリストできます。
(3)プログラムのアイデア(参照のみ):
0.定義部分:定数、変数、およびデータ構造を定義します。
1.初期化:入力シンボル文字列をファイルから文字バッファーに入力します。
2.再帰降下分析法を使用して、非終端記号ごとに関数を分析して記述し、メイン関数で文法開始記号の関数を呼び出します。
(4)実験の目的とアイデアを実践する:
プログラムはより複雑になり始め、プログラミング言語の知識と多数のプログラミングスキルを使用する必要があります。再帰降下分析はより実用的な分析方法です。この演習を通じて、ソフトウェア開発機能を大幅に向上させることができます。練習を通して、関数間で相互に呼び出す方法を習得します。
(2)優れたプログラムを設計するには、次の点に注意してください。
1.モジュールの設計:プログラムをいくつかの妥当なモジュール(関数)に分割すると、各モジュールは同じことを行います。
2.設計計画を作成(描画)します:モジュール関係図、フローチャート、グローバル変数、関数インターフェースなど。
3.プログラミング時には、空白行の使用、コメントの使用、インデントの使用などのプログラミングスタイルに注意してください。
第四に、実験プロセス
実験コード
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LEN 255
bool flag=true;
char src[LEN];
int i;
void E();
void T();
void G();
void F();
void S();
int main(){
printf("编制人:周江峰,20161209719,计科1601\n");
printf("请输入字符串(以#结束):");
scanf("%s",&src);
i=0;
E();
if(src[i]=='#'&&flag==true){
printf("语句合法");
}else
{printf("不合法");}
return 0;
}
void E(){
printf("E=>TG");
T();
G();
}
void T(){
printf("T=>FS");
F();
S();
}
void G(){
if(src[i]=='+'){
i++;
printf("G->+TG");
T();
G();
}else if(src[i]=='-'){
printf("G->-TG");
i++;
T();
G();
}
}
void F(){
if(src[i]=='('){
i++;
E();
if(src[i]==')')
{ i++;
printf("F->(E)");}
else flag=false;
}
else if(src[i]=='i')
{ printf("F->i");
i++;}
else flag=false;
}
void S(){
if(src[i]=='*'){
i++;
F();
S();
}else if(src[i]=='/'){
i++;
F();
S();
}
}
注:ファイルのサフィックスは.cppです
5.実験結果