系列第二更!
實驗二 自上而下語法分析
實驗目的
- 給出 PL/0 文法規范,要求編寫 PL/0 語言的語法分析程序。
- 通過設計、編制、調試一個典型的自上而下語法分析程序,實現對詞法分析程序所提供的單詞序列進行語法檢查和結構分析,進一步掌握常用的語法分析方法。
- 選擇最有代表性的語法分析方法,如遞歸下降分析法、預測分析法;選擇對各種常見程序語言都具備的語法結構,如賦值語句,特別是表達式,作為分析對象。
題目
【問題描述】
最基本的要求,能對一個算術表達式(a+15)*b做自上而下的語法分析,具體內容見實驗指導實驗二的內容,文法在實驗指導最開始幾頁,重點關注以下幾條文法的EBNF,若不習慣看文法的巴科斯范式EBNF,可先將文法改寫成常規的產生式形式P75:
<表達式> ::= [+|-]<項>{<加法運算符> <項>}
<項> ::= <因子>{<乘法運算符> <因子>}
<因子> ::= <標識符>|<無符號整數>| ‘(’<表達式>‘)’
<加法運算符> ::= +|-
<乘法運算符> ::= *|/
考慮到大家用的編程語言不同,且實驗一有少數同學沒有得到正確結果,為不影響實驗二的開展,實驗二的輸入統一采用詞法分析器的輸出結果為輸入。輸入形式如下:
【輸入形式】
(lparen,()
(ident,a)
(plus,+)
(number,15)
(rparen,))
(times,*)
(ident,b)
【輸出形式】
對於語法正確的表達式,報告“語法正確”,輸出為“Yes,it is correct.”
對於語法錯誤的表達式,報告“語法錯誤”,輸出為“No,it is wrong.”
【樣例輸入】
(lparen,()
(ident,a)
(plus,+)
(number,15)
(rparen,))
(times,*)
(ident,b)
【樣例輸出】
Yes,it is correct.
補充說明:學有余力的同學,可以在完成本實驗后思考如何將詞法分析的程序和語法分析的程序寫在一起?以語法分析程序為主程序,詞法分析程序為被調用程序,直接用(a+15)b做輸入。(注意:這個擴展的寫法請不要傳到編程題!!!可以寫在實驗報告中。因為實驗二的編程題的測試輸入形式我給的不是(a+15)b,而是用(a+15)*b的詞法分析的輸出作為實驗二語法分析的輸入,如上面的樣例輸入形式。)
設計思想
選擇遞歸下降分析方法:
1.設計出每個非終結符的文法識別過程
2.將輸入數據進行處理,提取出單詞的編碼
3.為每個非終結符寫識別遞歸函數
4.函數相互調用
源程序
數據讀入和錯誤處理部分我處理的不是很妥當,對於這個題目是OK的,但是不健壯。
#include <iostream>
#include <string>
#include<bits/stdc++.h>
#define N 8
using namespace std;
string words[N];//每個元素都是“lparen”/“ident”這樣的標志符
int sym=0;//words的指針
// 函數聲明
void E();
void T();
void F();
// 填充words數組
void getwords()
{
string line;
for(int i=0; i<N-1; i++)
{
cin >> line;
int pos = line.find(',', 0);
words[i] = line.substr(1, pos-1);
// cout << words[i];
}
}
// 指針前進
void advance()
{
++sym;
if(sym > N-1){
cout << "ERROR!words指針越界";
exit(0);
}
}
// 因子分析
void F()
{
//cout << "F正在分析" << words[sym] << endl;
if(words[sym] == "ident"){
advance();
}
else if(words[sym] == "number") {
advance();
}
else if(words[sym] == "lparen") {
advance();
E();
//cout << "E返回,F正在分析" << words[sym] << endl;
if(words[sym] == "rparen") {
advance();
}
else {
//cout << "ERROR!未能匹配右括號!語法錯誤" << endl;
exit(0);
}
}
return;
}
// 項分析
void T()
{
//cout << "T正在分析" << words[sym] << endl;
F();
//cout << "1F返回,T正在分析" << words[sym] << endl;
while(words[sym] == "times" || words[sym] == "slash"){
advance();
F();
//cout << "2F返回,T正在分析" << words[sym] << endl;
}
return;
}
// 表達式分析
void E()
{
//cout << "E正在分析" << words[sym] << endl;
if(words[sym] == "plus" || words[sym] == "minus"){
advance();
}
T();
//cout << "1T返回,E正在分析" << words[sym] << endl;
while(words[sym] == "plus" || words[sym] == "minus") {
advance();
T();
//cout << "2T返回,E正在分析" << words[sym] << endl;
}
return;
}
int main()
{
getwords();
E();
if(sym == N-1) {
cout << "Yes,it is correct." << endl;
}
else {
cout << "No,it is wrong.";
}
return 0;
}