實驗內容
給定CP語言中簡單算術表達式文法G[E]:
E→TE’
E’→ATE’|ε
T→FT’
T’→MFT’ |ε
F→(E) | i
A → + | -
M → * | /
根據該文法,編寫遞歸下降分析子程序。
【說明】:終結符號i為用戶定義的簡單變量,即專題1中標識符的定義。
實驗要求
(1)為每個非終結符號寫一個函數,選擇合適的數據結構來存儲產生式規則。
(2)輸入:是詞法分析輸出的二元組序列,即任意簡單算術表達式經過專題1程序輸出后得到的結果。
(3)輸出:判定輸入串是否為該文法定義的合法算術表達式。
(4)測試數據至少包含3組正確輸入和2組錯誤輸入。
設計思路
先將上篇詞法分析器的二元組輸出作為輸入讀入到二維字符數組中,再將每個二元組的單詞和編號提取出來存入結構體中(這里記錄編號是為了能實現將題意中的i識別為任意的標識符)。根據題目給出的產生式規則為每個非終結符號編寫遞歸下降分析函數,使用變量p標記當前的單詞並開始逐步分析,若分析過程中出錯則直接停止。若執行完所有的函數后p指向了結構體的末尾,則該輸入串是該文法的合法算數表達式。
程序結構
(1)主要數據結構:
二維字符數組ch:用於讀入輸入的二元組。
結構體struct node{string str;string code;}:記錄二元組中的單詞及其編號。
(2)函數定義:
void E():非終結符E的函數,輸出E的產生式規則,並向下進行T()和E1()。
void E1():非終結符E’的函數,若此時的單詞為“+”或“-”,則輸出E’->ATE’這條產生式,並依次向下進行A()、T()和E1(),否則直接輸出E’->ε。
void T():非終結符T的函數,輸出T的產生式規則,並向下進行F()和T1()。
void T1():非終結符T’的函數,若此時的單詞為“*”或“/”,則輸出T’->MFT’這條產生式,並依次向下進行M()、F()和T1(),否則直接輸出T’->ε。
void F():非終結符F的函數,若此時單詞的編號為28(標識符編號),則輸出F產生該標識符,變量p指向后一個單詞;否則,若此時單詞為“(”,變量p指向后一個單詞,向下進行E()后,若此時單詞為“)”,則輸出F->(E),否則輸出錯誤並停止;否則,輸出錯誤並停止。
void A():非終結符A的函數,若此時的單詞為“+”或“-”,則輸出A->+或A->-,變量p指向后一個單詞;否則,輸出錯誤並停止。
void M():非終結符M的函數,若此時的單詞為“*”或“/”,則輸出M->*或M->/,變量p指向后一個單詞;否則,輸出錯誤並停止。
實現代碼
#include<bits/stdc++.h> using namespace std; char ch[100][20]; struct node { string str; string code; }a[100]; int p=0; void E(); void E1(); void T(); void T1(); void F(); void A(); void M(); void E(){ printf("E->TE'\n"); T(); E1(); } void E1(){ if(a[p].str=="+"||a[p].str=="-") { printf("E'->ATE'\n"); A(); T(); E1(); } else printf("E'->ε\n"); } void T(){ printf("T->FT'\n"); F(); T1(); } void T1(){ if(a[p].str=="*"||a[p].str=="/") { printf("T'->MFT'\n"); M(); F(); T1(); } else printf("T'->ε\n"); } void F(){ if(a[p].code=="28") { cout<<"F->"<<a[p].str<<endl; p++; } else if(a[p].str=="(") { p++; E(); if(a[p].str==")") { printf("F->(E)\n"); p++; } else{ printf("error!\n"); exit(0); } } else{ printf("error!\n"); exit(0); } } void A(){ if(a[p].str=="+"){ printf("A->+\n"); p++; } else if(a[p].str=="-"){ printf("A->-\n"); p++; } else{ printf("error!\n"); exit(0); } } void M(){ if(a[p].str=="*"){ printf("M->*\n"); p++; } else if(a[p].str=="/"){ printf("M->/ \n"); p++; } else{ printf("error!\n"); exit(0); } } int main(){ FILE *fp; fp=fopen("result2.txt","r"); if(fp==NULL) { cout<<"Open Error"; exit(1); } int len=0; while(fscanf(fp,"%s",ch[len])!=EOF) len++; fclose(fp); for(int i=0;i<len;i++)//輸入轉換 { string temp=""; int j; for(j=1;ch[i][j]!=',';j++) { temp+=ch[i][j]; } a[i].str=temp; j++; temp=""; for(j;ch[i][j]!='>';j++) { temp+=ch[i][j]; } a[i].code=temp; } E(); if(p==len) printf("succeed\n"); else printf("failed\n"); return 0; }