1 .PL/0 语言文 法的 的 EBNF
<程序>::=<分程序>.
<分程序> ::=[<常量说明>][<变量说明>][<过程说明>]<语句>
<常量说明> ::=CONST<常量定义>{,<常量定义>};
<常量定义> ::=<标识符>=<无符号整数>
<无符号整数> ::= <数字>{<数字>}
<变量说明> ::=VAR <标识符>{, <标识符>};
<标识符> ::=<字母>{<字母>|<数字>}
<过程说明> ::=<过程首部><分程序>{; <过程说明> };
<过程首部> ::=PROCEDURE <标识符>;
<语句> ::=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句>
|<复合语句>|<读语句><写语句>|<空>
<赋值语句> ::=<标识符>:=<表达式>
<复合语句> ::=BEGIN <语句> {;<语句> }END
<条件表达式> ::= <表达式> <关系运算符> <表达式> |ODD<表达式>
<表达式> ::= [+|-]<项>{<加法运算符> <项>}
<项> ::= <因子>{<乘法运算符> <因子>}
<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
<加法运算符> ::= +|-
<乘法运算符> ::= *|/
<关系运算符> ::= =|#|<|<=|>|>=
<条件语句> ::= IF <条件表达式> THEN <语句>
《编译原理》实验指导书
上海大学 计算机学院 《编译原理》课程组 4 of 39
<过程调用语句> ::= CALL 标识符
<当循环语句> ::= WHILE <条件表达式> DO <语句>
<读语句> ::= READ‘(’<标识符>{,<标识符>}‘)’
<写语句> ::= WRITE‘(’<表达式>{,<表达式>}‘)’
<字母> ::= a|b|…|X|Y|Z
<数字> ::= 0|1|…|8|9
要求:改变输入方式,使得普通语句也能进行语法分析(a+15)*b 作为输
入。
就是将本来的
(lparen,( )
(ident, a)
(plus, + )
(number, 15)
(rparen,) )
(times, * )
(ident, b )
二元组形式的输入转化成正常表达式(a+15)*b形式的输入(通过文件读取信息)
#include<iostream>
#include<stack>
#include<string>
#include<fstream>
using namespace std;
static int rg = 1;
static int rg1 = 1;
static int rg2 = 1;
struct newsym
{
char restr[15];
};
newsym sym[50];
int E(int n, newsym *sym);
int T(int n, newsym *sym);
int D(int n, newsym *sym);
int AExpression(int n, newsym *sym);
int Ass(int n, newsym *sym);
void quantity1(int n, newsym *sym);
int quantity2(int n, newsym *sym);
int quantity3(int n, newsym *sym);
int variable2(int n, newsym *sym);
int variable3(int n, newsym *sym);
int compound(int all, newsym *sym);
int call(int all, newsym *sym);
//判断常量说明及定义是否合法
void quantity1(int n, newsym *sym) {
int i, j;
for (i = 0; i<n; i++) {
if (!strcmp(sym[i].restr, "constsym")) {
j = quantity2(i, sym);
if (strcmp(sym[i - 1].restr, "semicolon") && i != 0) {
rg1 = 0;
printf("常量说明/定义前缺少分号\n");
}
else if (j == 1) {
rg1 = 0;
printf("常量说明/定义错误\n");
}
}
}
}
int quantity2(int n, newsym *sym) {
int i = n, k = -1, flag = 0;
while (k != i) {
k = i;
i = quantity3(i + 1, sym);
}
if ((!strcmp(sym[i + 1].restr, "ident") && !strcmp(sym[i + 2].restr, "eql") && !strcmp(sym[i + 3].restr, "number") && !strcmp(sym[i + 4].restr, "semicolon")))
flag = 0;
else
flag = 1;
return flag;
}
int quantity3(int n, newsym *sym) {
if (!strcmp(sym[n].restr, "ident") && !strcmp(sym[n + 1].restr, "eql") && !strcmp(sym[n + 2].restr, "number") && !strcmp(sym[n + 3].restr, "comma"))
return n = n + 3;
else
return n - 1;
}
//判断变量说明及定义是否合法
void variable1(int n, newsym *sym) {
int i, j = 0;
for (i = 0; i<n; i++) {
if (!strcmp(sym[i].restr, "varsym")) {
j = variable2(i, sym);
if (strcmp(sym[i - 1].restr, "semicolon") && i != 0) {
rg1 = 0;
printf("变量说明/定义前缺少分号\n");
}
else if (j == 1) {
rg1 = 0;
printf("变量说明/定义错误\n");
}
}
}
}
int variable2(int n, newsym *sym) {
int i = n, k = -1, flag = 0;
while (k != i) {
k = i;
i = variable3(i + 1, sym);
}
if ((!strcmp(sym[i + 1].restr, "ident") && !strcmp(sym[i + 2].restr, "semicolon")))
flag = 0;
else
flag = 1;
return flag;
}
int variable3(int n, newsym *sym) {
if (!strcmp(sym[n].restr, "ident") && !strcmp(sym[n + 1].restr, "comma"))
return n = n + 1;
else
return n - 1;
}
int E(int n, newsym *sym)//判断表达式
{
int k = 0;
if (!strcmp(sym[n].restr, "plus") || !strcmp(sym[n].restr, "minus"))
{
n++;
if (!strcmp(sym[n - 2].restr, "lparen"))
{
cout << "算数表达式出错" << endl;
rg = 0;
}
if (!strcmp(sym[n].restr, "ident") || !strcmp(sym[n].restr, "number") || !strcmp(sym[n].restr, "lparen"))
{
n = T(n, sym);
}
}
else if (!strcmp(sym[n].restr, "ident") || !strcmp(sym[n].restr, "number") || !strcmp(sym[n].restr, "lparen"))
{
n = T(n, sym);
}
if ((!strcmp(sym[n].restr, "ident") || !strcmp(sym[n].restr, "number")) && (!strcmp(sym[n - 1].restr, "ident") || !strcmp(sym[n - 1].restr, "number")))
{
n++;
cout << "缺运算符" << endl;
rg = 0;
}
if ((!strcmp(sym[n].restr, "ident") || !strcmp(sym[n].restr, "number")) && !strcmp(sym[n - 1].restr, "rparen"))
{
n++;
cout << "缺少运算符" << endl;
rg = 0;
}
while (!strcmp(sym[n].restr, "plus") || !strcmp(sym[n].restr, "minus"))
{
n++;
n = T(n, sym);
}
if (!strcmp(sym[n].restr, "rparen")) {
for (int i = n; i--; i>0)
if (!strcmp(sym[i].restr, "lparen"))
k = 1;
if (k == 0) {
rg = 0;
cout << "缺少左括号" << endl;
}
}
return n;
}
int T(int n, newsym *sym) //判断项
{
if (!strcmp(sym[n].restr, "ident") || !strcmp(sym[n].restr, "number") || !strcmp(sym[n].restr, "lparen"))
{
n = D(n, sym);
}
else
{
cout << "算数表达式出错" << endl;
rg = 0;
}
while (!strcmp(sym[n].restr, "times") || !strcmp(sym[n].restr, "slash"))
{
n++;
n = D(n, sym);
}
return n;
}
int D(int n, newsym *sym) //判断因子
{
if (!strcmp(sym[n].restr, "ident") || !strcmp(sym[n].restr, "number"))
{
n++;
}
else if (!strcmp(sym[n].restr, "lparen"))
{
n++;
n = E(n, sym);
if (!strcmp(sym[n].restr, "rparen"))
{
n++;
}
else
{
cout << "算术表达式出错" << endl;
rg = 0;
}
}
else
{
cout << "算数表达式出错" << endl;
rg = 0;
}
return n;
}
int AExpression(int n, newsym *sym) { //判断是否为算术表达式
n = E(n, sym);
return n;
}
int Ass(int n, newsym *sym) { //判断赋值语句
int i = 0;
while (i < n) {
if (strcmp(sym[i].restr, "becomes") == 0) {
if (strcmp(sym[i - 1].restr, "ident") == 0) {
if (!strcmp(sym[i + 1].restr, "becomes"))
cout << "赋值符重复" << endl;
else {
i++;
AExpression(i, sym);
}
}
else {
rg = 0;
cout << "赋值语句错误" << endl;
}
}
i++;
}
return i;
}
int CExpression(int n, newsym *sym) { //判断条件表达式
int i = 0;
rg = 1;
while (i < n) {
if (strcmp(sym[i].restr, "ifsym") == 0) {
if (strcmp(sym[i+1].restr, "oddsym") == 0)
AExpression(i + 2, sym);
else {
AExpression(i + 1, sym);
if (rg==1) {
if (strcmp(sym[i + 2].restr, "lss") == 0 || strcmp(sym[i + 2].restr, "leq") == 0 || strcmp(sym[i + 2].restr, "gtr") == 0 || strcmp(sym[i + 2].restr, "geq") == 0) {
if (strcmp(sym[i + 3].restr, "lss") == 0 || strcmp(sym[i + 3].restr, "leq") == 0 || strcmp(sym[i + 3].restr, "gtr") == 0 || strcmp(sym[i + 3].restr, "geq") == 0) {
rg2 = 0;
cout << "条件表达式中关系运算符重复" << endl;
}
else if (strcmp(sym[i + 3].restr, "neq") == 0 || strcmp(sym[i + 3].restr, "becomes") == 0 || strcmp(sym[i + 3].restr, "comma") == 0 || strcmp(sym[i + 3].restr, "semicolon") == 0) {
rg2 = 0;
cout << "条件表达式中符号错误" << endl;
}
else {
i=AExpression(i + 3, sym);
if (rg == 0)
{
rg2 = 0;
cout << "条件表达式出错" << endl;
}
}
}
else{
rg2 = 0;
cout << "条件表达式缺少关系运算符" << endl;
}
}
}
}
i++;
}
return i;
}
int compound(int all, newsym *sym) {
char queueb[200];
int flag = 0;//记录queueb中的位置
int correct = 1;
int i;
for (i = 0; i <= all; i++) {
if (strcmp(sym[i].restr, "beginsym") == 0 || strcmp(sym[i].restr, "proceduresym") == 0) {
if (strcmp(sym[i].restr, "beginsym") == 0) {
queueb[flag] = 'b';
flag++;
}
else if (strcmp(sym[i].restr, "proceduresym") == 0) {
queueb[flag] = 'p';
flag++;
}
}
//以下是a型和b型的判断
else if (strcmp(sym[i].restr, "endsym") == 0 && i != all) {
//没有begin
if (flag == 0) {
cout << " end前没有begin" << endl;
correct = 0;
}
//以下属于a型:end后应用";"
else if (queueb[flag - 1] == 'b'&&queueb[flag - 2] == 'p') {
if (strcmp(sym[i + 1].restr, "semicolon") != 0) {
cout << queueb[flag - 2] << endl;
cout << queueb[flag - 1] << endl;
cout << " end后面不是分号" << endl;
queueb[flag - 2] = '0';
queueb[flag - 1] = '0';
correct = 0;
}
else {
cout << queueb[flag - 2] << endl;
cout << queueb[flag - 1] << endl;
queueb[flag - 2] = '0';
queueb[flag - 1] = '0';
flag = flag - 2;
}
}
else {
if ((strcmp(sym[i + 1].restr, "semicolon") == 0 && i<all - 1) || (strcmp(sym[i + 1].restr, "period") == 0 && i<all - 1)) {
cout << " end在中间,但后面是分号或者句号" << endl;
queueb[flag - 1] = '0';
correct = 0;
}
else {
queueb[flag - 1] = '0';
flag = flag - 1;
}
}
}
//c型:end后面没有东西
else if (strcmp(sym[i].restr, "endsym") == 0 && i == all) {
queueb[flag - 1] = '0';
correct = 0;
cout << " end后没有标点符号" << endl;
}
//c型:end后面不是"."
else if (strcmp(sym[i].restr, "endsym") == 0 && i == all - 1) {
if (strcmp(sym[i + 1].restr, "period") != 0) {
correct = 0;
queueb[flag - 1] = '0';
cout << " end在末尾,end后面不是句号" << endl;
}
}
}
if (queueb[0] == 'b' || queueb[0] == 'p') {
correct = 0;
cout << " 缺少end" << endl;
}
return correct;
}
int call(int all, newsym *sym) {
int flag = 0;
int correct = 1;
for (int i = 0; i <= all; i++) {
if (strcmp(sym[i].restr, "callsym") == 0) {
if (strcmp(sym[i + 1].restr, "ident") != 0 || strcmp(sym[i + 2].restr, "semicolon") != 0) {
correct = 0;
}
}
}
if (correct == 0)
printf("call语句错误\n");
return correct;
}
int main()
{
ifstream infile("0.txt");
string buffer;
int i = 0, j, n, m, all,k1,k2;
for (n = 0; n <= 49; n++)
{
sym[n].restr[0] = '\0';
}
n = 0;
while (!infile.eof() && infile >> buffer) {
i = j = 0;
if (buffer[0] == '(')
{
while (buffer[i + 1] != ',')
{
i++;
sym[n].restr[j] = buffer[i];
j++;
}
sym[n].restr[j] = '\0';
n++;
}
}
m = n;
all = n - 1;
quantity1(m, sym);
variable1(m, sym);
Ass(m, sym);
CExpression(m, sym);
k1 = compound(all, sym);
k2 = call(all, sym);
if (rg == 1 && rg1 == 1&&rg2 == 1 && k1== 1 && k2 == 1)
cout << "语法正确" << endl;
else {
cout << "--------------" << endl;
cout << "语法错误" << endl;
}
return 0;
}
版权所有:留学生编程辅导网 2020 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。