当前位置:文档之家› 编译原理 算符优先分析程序设计

编译原理 算符优先分析程序设计

编译原理   算符优先分析程序设计
编译原理   算符优先分析程序设计

编译原理课程设计报告

评分:

签字:

编译原理课程设计二——算符优先分析程序设计

实验目的

了解掌握算符优先分析的基本方法、内容;

学会科学思考并解决问题,提高程序设计能力。

实验内容与要求

用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。

文法表示:

S→v=E|E?|clear

E→E+T|E-T|T

T→T*F|T/F|F

F→(E)|v|c

单词种别码设计:

= 1

? 2

+ 3

- 4

* 5

/ 6

(7

)8

v 9

c 10

clear 11

# 12

N 13

实验环境

系统环境为windows系统,编译环境为VS2015,编程语言为C++。

实验过程

过程一:构建firstVT()和lastVT()

算法分析:

对于firstVT()构建,对于每个非终结符F的产生式,第一个终结符或者‘|’后的第一个终结符应该在其firstVT()集合内,且若非终结符T能推出非终结符F则firstVT(T)包含first(F)。lastVT()的构造类似,对于每个非终结符F的产生式,非终结符后的第一个终结符都属于lastVT (F), 且若非终结符T能推出非终结符F则lastVT(T)包含first(F)。

算法实现主要函数:

void get_firstVT()//求firstVT();

void get_lastVT()//求lastVT();

结果:

FirstVT(S){=,?,l,+,-,*,/,(,v,c,}

FirstVT(E){+,-,*,/,(,v,c,}

FirstVT(T){*,/,(,v,c,}

FirstVT(F){(,v,c,}

LastVT(S){=,?,l,+,-,*,/,),v,c,}

LastVT(E){+,-,*,/,),v,c,}

LastVT(T){*,/,),v,c,}

LastVT(F){),v,c,}

过程二:构建优先符号表

算法分析:

(1)在产生式中两个相邻的终结符优先顺序相等

(2)对于小于关系,首先扫描终结符a标记flag=1,再扫描到非终结符Q,此时判断若flag=1,则对所有b∈FristVT{Q},a

(3)对于大于关系,首先扫描非终结符Q在前标记flag=1,再扫描终结符a在后此时判断若flag=1,对所有b∈LastVT{Q},b>a.

算法结果:

其中-2表示不会出现,1表示>,-1表示<,0表示=.

字母l表示clear.

过程三:词法分析

算法分析:详见课程设计一

算法主要函数:

int letter()//判断是否为字母

int digit()//判断是否为数字

int str_to_num()//数字字符串转化为整数

int reserve(char **k)//处理保留字

int sysmbol(identifier *id)//处理标识符,查找符号表并存放位置若没有则添加

int constant(constnumber *con)//存入常数表,并返回它在常数表中的位置

void WordAnalyze( constnumber *con, identifier *id, char sentence[],int &point,int &syn,int &sym_point)//词法分析

void Insert_to_symboltbl(int syn, int value, int &point)//把二元组加入symbol表

算法结果:

得到语句的所有单词二元组symbolTBL表,存放种别码syn及其值val,其中对于种别码为9的变量val为标志符的入口标志,对于种别码为10的的常量val为存放的值。

以及标志符表。

过程四:算符优先分析

算法分析:

1) 置栈底及输入串尾为# ,并设# < VT , VT > #;

栈顶终结符为θ,输入字为 a ;

2) 若θ

则a 移入栈中. 重复2);

若θ >a, 则在栈中寻找最左素短语,

归约为N ,并记录N的值重复2);

若θ=a=#, 且栈中为#N,

则分析成功;否则,输入串为非法字串.

数据结构设计:

构造堆栈结构存储分析句子

typedef struct {

SymbolTbl *elem;

int n;

int top;

}Stack;

堆栈相关操作

int CreateStack(Stack &s, int n)//初始化

void clearStack(Stack &s)//清空

int empty(Stack &s)//判断是否为空

void push(Stack &s,SymbolTbl t)//入栈

void pop(Stack &s)//出栈

主要函数:

void Clear_Symbol_Tbl()//清空符号表

void print_(Stack &s,int &point)//打印出堆栈和符号表的情况

void suanfu_main()//算符优先分析

测试分析

测试用例

a=5

b=a+10

测试结果

#a=5#

标识符表:

1 a -1

二元组表:

0 12 -1

1 9 1

2 1 -1

3 10 5

4 12 -1

当前堆栈情况:(12,-1) 当前符号表情况:(9,1) (1,-1) (10,5)

这里是小于等于关系,入栈

当前堆栈情况:(12,-1) (9,1)当前符号表情况:(1,-1) (10,5)

这里是小于等于关系,入栈

当前堆栈情况:(12,-1) (9,1) (1,-1)当前符号表情况:(10,5)

这里是小于等于关系,入栈

当前堆栈情况:(12,-1) (9,1) (1,-1) (10,5)当前符号表情况:

此处将常量归约为N

当前堆栈情况:(12,-1) (9,1) (1,-1) (13,5)当前符号表情况:

此处将v=c归约为N

当前堆栈情况:(12,-1) (13,5)当前符号表情况:

当前堆栈情况:(12,-1) (13,5)当前符号表情况:

归约成功结果为5

coninue ? y or n y

请输入句子,以#开始并且以#结束

#b=a+10#

标识符表:

1 a 5

2 b -1

二元组表:

0 12 -1

1 9 2

2 1 -1

3 9 1

4 3 -1

5 10 10

6 12 -1

当前堆栈情况:(12,-1)当前符号表情况:(9,2) (1,-1) (9,1) (3,-1) (10,10) 这里是小于等于关系,入栈

当前堆栈情况:(12,-1) (9,2)当前符号表情况:(1,-1) (9,1) (3,-1) (10,10) 这里是小于等于关系,入栈

当前堆栈情况:(12,-1) (9,2) (1,-1)当前符号表情况:(9,1) (3,-1) (10,10) 这里是小于等于关系,入栈

当前堆栈情况:(12,-1) (9,2) (1,-1) (9,1)当前符号表情况:(3,-1) (10,10)

此处将变量归约为N

当前堆栈情况:(12,-1) (9,2) (1,-1) (13,5)当前符号表情况:(3,-1) (10,10)

这里是小于等于关系,入栈

当前堆栈情况:(12,-1) (9,2) (1,-1) (13,5) (3,-1)当前符号表情况:(10,10)

这里是小于等于关系,入栈

当前堆栈情况:(12,-1) (9,2) (1,-1) (13,5) (3,-1) (10,10)当前符号表情况:

此处将常量归约为N

当前堆栈情况:(12,-1) (9,2) (1,-1) (13,5) (3,-1) (13,10)当前符号表情况:

此处将N+N归约为N

当前堆栈情况:(12,-1) (9,2) (1,-1) (13,15)当前符号表情况:

此处将v=c归约为N

当前堆栈情况:(12,-1) (13,15)当前符号表情况:

归约成功

结果为15

coninue ? y or n

结论

符合预期结果该赋值语句解释程序符合要求

感想与收获

赋值语句的词法分析包括了众多过程与步骤,通过完整的完成本次课程设计,我对构建算符优先表以及语法分析过程有了更深的理解与掌握。

同时在用代码实现的过程中我程序设计、程序优化、调试程序的能力也有较大提升。代码

#include

#include

using namespace std;

//单词种别码

int zb_c(char a)

{

switch (a) {

case '=':return 1;

case '?':return 2;

case '+':return 3;

case '-':return 4;

case '*':return 5;

case '/':return 6;

case '(':return 7;

case ')':return 8;

case 'v':return 9;

case 'c':return 10;

case 'l':return 11;

case '#':return 12;

case 'N':return 13;

default:return 0;

}

}

char zbc[12] = { '=','?','+','-','*','/','(',')','v','c','l','#' };

//是否为终结符

int ISzj_code(char ch)

{

if ((ch >= 97 && ch <= 122) || ch == '+' || ch == '*' || ch == '-' || ch == '/' || ch == '!' || ch == '(' || ch == ')' || ch == '#' || ch == '\?' || ch == '=')

return 1;

else

return 0;

}

char wenfa[4][30] = {

{"S→v = E | E ? | l"},{"E→E + T | E - T | T"},{"T→T*F | T / F | F"},{"F→(E) | v | c"}};

char First_VT[4][20];

char Last_VT[4][20];

char chc[4] = { 'S','E','T','F' };

int Fzj(char a)

{

switch (a)

{

case 'S':return 0;

case 'E':return 1;

case 'T':return 2;

case 'F':return 3;

default:return -1;

}

}

//求firstVT

void get_firstVT()

{

int i, j;

for ( i = 3;i >= 0;i--)

{

int k = 0,flag = 1;

for ( j = 2;wenfa[i][j] != '\0';j++)

{

if (ISzj_code(wenfa[i][j]) && flag == 1)

{

if (i == 0 && j == 3);

else

{

First_VT[i][k++] = wenfa[i][j];

flag = 0;

}

}

if (wenfa[i][j] == '|')flag = 1;

}

if (i!=3)

{

j = 0;

while (First_VT[i + 1][j] != '\0')

First_VT[i][k++] = First_VT[i + 1][j++];

}

First_VT[i][k] = '\0';

}

}

void get_lastVT()

{

int i, j;

for ( i = 3;i >= 0;i--)

{

int k = 0, flag = 0;

for ( j = 3;wenfa[i][j] != '\0';j++)

{

if (ISzj_code(wenfa[i][j]) && flag == 1)

{

Last_VT[i][k++] = wenfa[i][j];

flag = 0;

}

if (!ISzj_code(wenfa[i][j]))flag = 1;

}

if (i!=3)

{

j = 0;

while (Last_VT[i+1][j] != '\0')

Last_VT[i][k++] =Last_VT[i + 1][j++];

}

}

}

//打印fistVT与lastVT结果

void printFistlast()

{

get_firstVT();

for (int i = 0;i < 4;i++)

{

cout << "FirstVT(" << chc[i] << "){";

int j = 0;

while (First_VT[i][j] != '\0')

cout << First_VT[i][j++] << ",";

cout << '}' << endl;

}

get_lastVT();

for (int i = 0;i < 4;i++)

{

cout << "LastVT(" << chc[i] << "){";

int j = 0;

while (Last_VT[i][j] != '\0')

cout << Last_VT[i][j++] << ',';

cout << '}' << endl;

}

}

//优先关系表

int priority[13][13] ;

void prior()

{

int i, j,flag,p;

for (i = 0;i < 13;i++)

for (j = 0;j < 13;j++)

priority[i][j] = -2;

char ch1, ch2;

//求等号

for (i = 0;i < 4;i++)

{

flag = 0;

for (j = 3;wenfa[i][j] != '\0';j++)

{

if (ISzj_code(wenfa[i][j]))

{

flag++;

if (flag == 1)

ch1 = wenfa[i][j];

if (flag == 2)

{

ch2 = wenfa[i][j];

priority[zb_c(ch1)][zb_c(ch2)] = 0;

flag = 0;

}

}

if (wenfa[i][j] == '|')

flag = 0;

}

}

//求小于

for (i = 0;i < 4;i++)

{

flag = 0;

for (j = 3;wenfa[i][j] != '\0';j++)

{

if (ISzj_code(wenfa[i][j]))

{

flag = 1;

ch1 = wenfa[i][j];

}

if (!ISzj_code(wenfa[i][j]) && flag == 1)

{

ch2 = wenfa[i][j];

if(ch2=='S'||ch2=='T'||ch2=='F'||ch2=='E')

{int temp = Fzj(ch2);

for ( p = 0;First_VT[temp][p] != '\0';p++)

{

priority[zb_c(ch1)][zb_c(First_VT[temp][p])] = -1;

}

flag = 0;

}

if (wenfa[i][j] == '|')

flag = 0;

}

}

}

//求大于

for (i = 0;i < 4;i++)

{

flag = 0;

for (j = 3;wenfa[i][j] != '\0';j++)

{

if (wenfa[i][j] == 'S' || wenfa[i][j] == 'T' || wenfa[i][j] == 'F' || wenfa[i][j] == 'E')

{

flag = 1;

ch1 = wenfa[i][j];

}

if (ISzj_code(wenfa[i][j]) && flag == 1)

{

ch2 = wenfa[i][j];

int temp = Fzj(ch1);

for (p = 0;Last_VT[temp][p] != '\0';p++)

{

priority[zb_c(Last_VT[temp][p])][zb_c(ch2)] = 1;

}

flag = 0;

}

if (wenfa[i][j] == '|')

flag = 0;

}

} for (i = 0;i <= 12;i++)

{

priority[i][12] = 1;

priority[12][i] = -1;

}

priority[12][12] = 0;

}

void print_prior()

{

int i;

cout << setw(10);

for (i = 0;i < 12;i++)

{

cout << zbc[i];cout << setw(5);

}

cout << endl;

for (int i = 1;i <= 12;i++)

{

cout << zbc[i - 1]<

for (int j = 1;j <= 12;j++)

cout << priority[i][j]<< setw(5);

cout << endl;

}

}

typedef struct

{

int syn;//种别码

int value;//数值或者标识符入口指针

}SymbolTbl;

#define LENGTH 10

char ch;

char *CODE[] = { "identifier","constant","keyword"/*保留字*/,"+","-","*","/","<","<=",">",">=","!=","==","=","(",")",",",":",";","{","}" };

char *k[] = { "for","while","do","else","if","static","int","sizeof","break","continue" };//保留字

char token[16];//存放处理后的字符串

//标识符结构体

typedef struct

{

char I[30];

int value;

}identifier;

//变量表

typedef struct

{

int cont[300];

int len;

}constnumber;

//词法分析器

void contacat()//连接字符

{

char * cht = &(ch);

strcat_s(token, cht);

}

int letter()//判断是否为字母

{

return isalpha(ch);

}

int digit()//判断是否为数字

{

return isdigit(ch);

}

int reserve(char **k)//处理保留字

int i;

for (i = 0;i < LENGTH;i++)

{

if (strcmp(token, k[i]) == 0)

return (i + 1);

}

return 0;

}

identifier id[256];//标志符表

int idscan = 1;

int sysmbol(identifier *id)//处理标识符,查找符号表并存放位置若没有则添加{

int i;

for (i = 1;i

if (strcmp(token,id[i].I) == 0)

return i ;

strcpy_s(id[idscan].I, token);

id[idscan].value = -1;

idscan++;

return idscan-1;

}

int str_to_num()//数字字符串转化为整数

{

int i = 0;

int k = token[i] - '0';

for (i = 1;token[i] != '\0';i++)

{

k = k * 10 + token[i] - '0';

}

return k;

}

int constant(constnumber *con)//存入常数表,并返回它在常数表中的位置{

con->cont[con->len] = str_to_num();

con->len++;return con->cont[con->len-1];

}

SymbolTbl symbol[100];

void Insert_to_symboltbl(int syn, int value, int &point)//把二元组加入symbol表

symbol[point].syn = syn;

symbol[point].value = value;

point++;

}

void WordAnalyze( constnumber *con, identifier *id, char sentence[],int &point,int &syn,int &sym_point)//词法分析

{

int entry,val;

strcpy_s(token, "");//初始化为空字符串

ch = sentence[point];

if (ch == '#'&&point == 0)

{

point++;

ch = sentence[point];

}

if ((ch >= 'A'&&ch <= 'Z') || (ch >= 'a'&&ch <= 'z')) //分析标识符和保留字

{

//若字符为A~Z或0~9,则继续读取

while (letter() || digit())

{

contacat();

point++;

ch = sentence[point];

}

//retract(fp, c);

syn = 9;//代表找到了标识符

if (strcmp(token, "clear") == 0)

{//代表找到了保留字“clear”

syn = 11;

Insert_to_symboltbl(syn, -1, sym_point);

}

if (syn == 9)

{

entry = sysmbol(id);

Insert_to_symboltbl(syn, entry, sym_point);

}

}

else if (digit())//处理常数

{

while (digit())

{

contacat();

point++;

ch = sentence[point];

}

//retract(fp, c);

val = constant(con);

syn = 10;

Insert_to_symboltbl(syn, val, sym_point);

}

else //分析符号

{

switch (ch)

{

case'=':syn = 1; break;

case'?':syn = 2; break;

case'+':syn = 3; break;

case'-':syn = 4; break;

case'*':syn = 5; break;

case'/':syn = 6; break;

case'(':syn = 7; break;

case')':syn = 8; break;

case'#':syn = 12; break;

default:printf("输入句子有误!\n");exit(0);break;

}

point++;

Insert_to_symboltbl(syn, -1, sym_point);

}

}

void Analyse_main()//初始化与结果输出

{

constnumber *con = (constnumber *)malloc(sizeof(constnumber));con->len = 0;

char sentence[100] = "\0";

int syn = -1,scan_point=0;

int sym_point = 0;

printf("请输入句子,以#开始并且以#结束\n");

cin>>sentence;

Insert_to_symboltbl(12, -1, sym_point);

while (syn != 12)

{

WordAnalyze(con, id, sentence, scan_point, syn,sym_point);

}

for (int m1 = 1;m1 < idscan;m1++)

{

cout << m1<<" ";

printf("%s ", id[m1].I);cout << id[m1].value<<" " << endl;

}

for (int m2 = 0;m2

{//符号表

printf("\t%d %d %d\n", m2, symbol[m2].syn, symbol[m2].value);

}

}

//算符优先分析

typedef struct {

SymbolTbl *elem;

int n;

int top;

}Stack;

int CreateStack(Stack &s, int n)//初始化

{

if (n < 0) return 0;

s.n = n;s.top = -1;

s.elem = (SymbolTbl*)malloc(sizeof(SymbolTbl)*n);

if (!s.elem)

return 0;

return 1;

}

void clearStack(Stack &s)//清空

{

s.top = -1;

}

int empty(Stack &s)//判断是否为空

{

return s.top == -1;

}

void push(Stack &s,SymbolTbl t)//入栈

{

s.elem[++s.top] = t;

}

void pop(Stack &s)//出栈

SymbolTbl t;

t = s.elem[s.top--];

}

void Clear_Symbol_Tbl()//清空符号表

{

//将符号表的syn全部设置为0

for (int i = 0;i<100;i++)

{

symbol[i].syn = 0;//代表没定义

symbol[i].value = -1;//指定为-1

}

}

void print_(Stack &s,int &point)//打印出堆栈和符号表的情况

{

cout << endl;

cout << "当前堆栈情况:";

for (int i = 0;i <= s.top;i++)

cout << "(" << s.elem[i].syn << "," << s.elem[i].value << ") ";

cout << endl;

cout << "当前符号表情况:";

for(int j=point;symbol[j].syn!=12;j++)

cout << "(" << symbol[j].syn << "," << symbol[j].value << ") ";

cout << endl;

}

void error()

{

cout << "程序有错误";

exit(0);

}

void suanfu_main()//算符优先分析

{

int symbol_scan=1;//符号表扫描指针,从1开始

int stack_scan;

//初始化一个堆栈

Stack s;

CreateStack(s, 50);

SymbolTbl temp;

temp.syn = 12;temp.value = -1;

push(s, temp);

print_(s, symbol_scan);

stack_scan = s.top;

int prior_stack, prior_symbol;

while (1)

{

prior_stack = s.elem[stack_scan].syn;

prior_symbol = symbol[symbol_scan].syn;

int prio = priority[prior_stack][prior_symbol];

if (prio == -1 || (prio == 0 && prior_symbol != 12))

{

push(s, symbol[symbol_scan]);

symbol_scan++;

stack_scan = s.top;

cout << "这里是小于等于关系,入栈";

print_(s, symbol_scan);

}

else if (prio == 0 && s.elem[s.top].syn == 13 && prior_symbol == 12 && s.elem[s.top - 1].syn == 12) {

cout << "归约成功" << endl;

cout << "结果为" << s.elem[s.top].value << endl;

break;

}

else if (prio == 1)

{

stack_scan = s.top;

while (prio == 1)

{

int judge = s.elem[stack_scan].syn;

if (judge == 9)//栈顶元素为变量

{

if (id[s.elem[stack_scan].value - 1].value == -1);

else if (s.elem[stack_scan].value < 0)

{

cout << "该变量未定义";exit(0);

}

else

{

temp.syn = 13;

temp.value = id[s.elem[stack_scan].value].value;

pop(s);

push(s, temp);

stack_scan = s.top - 1;

if (stack_scan <0)

error();

prior_stack = s.elem[stack_scan].syn;

prio = priority[prior_stack][prior_symbol];

cout << "此处将变量归约为N" << endl;

print_(s, symbol_scan);

}

}

else if (judge == 10)//常量

{

temp.syn = 13;

temp.value = s.elem[stack_scan].value;

pop(s);

push(s, temp);

stack_scan = s.top - 1;

if (stack_scan < 0)

error();

prior_stack = s.elem[stack_scan].syn;

prio = priority[prior_stack][prior_symbol];

cout << "此处将常量归约为N" << endl;

print_(s, symbol_scan);

}

else if (judge == 1)//=

{

if (s.elem[stack_scan - 1].syn == 9)

{

id[s.elem[stack_scan - 1].value].value = s.elem[s.top].value;

temp.syn = 13;

temp.value = s.elem[s.top].value;

pop(s);

pop(s);

pop(s);

push(s, temp);

stack_scan = s.top - 1;

if (stack_scan < 0)

error();

prior_stack = s.elem[stack_scan].syn;

prio = priority[prior_stack][prior_symbol];

cout << "此处将v=c归约为N" << endl;

print_(s, symbol_scan);

}

else

{

error();

}

}

else if (judge == 3)//+

{

if (s.elem[stack_scan - 1].syn == 13 && s.elem[s.top].syn == 13)

{

temp.syn = 13;

temp.value = s.elem[stack_scan - 1].value + s.elem[s.top].value;

pop(s);

pop(s);

pop(s);

push(s, temp);

stack_scan = s.top - 1;

if (stack_scan < 0)

error();

prior_stack = s.elem[stack_scan].syn;

prio = priority[prior_stack][prior_symbol];

cout << "此处将N+N归约为N" << endl;

print_(s, symbol_scan);

}

else

{

error( );

}

}

else if(judge==4)//-

{

if (s.elem[stack_scan - 1].syn == 13 && s.elem[s.top].syn == 13)

{

temp.syn = 13;

temp.value = s.elem[stack_scan - 1].value - s.elem[s.top].value;

pop(s);

pop(s);

pop(s);

push(s, temp);

stack_scan = s.top - 1;

if (stack_scan < 0)

error();

prior_stack = s.elem[stack_scan].syn;

prio = priority[prior_stack][prior_symbol];

cout << "此处将N-N归约为N" << endl;

print_(s, symbol_scan);

}

else

{

error( );

}

编译原理实验--词法分析器

编译原理实验--词法分析器 实验一词法分析器设计 【实验目的】 1(熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。 2(复习高级语言,进一步加强用高级语言来解决实际问题的能力。 3(通过完成词法分析程序,了解词法分析的过程。 【实验内容】 用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符 串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字, 运算符,标识符,常数以及界符)输出。 【实验流程图】

【实验步骤】 1(提取pl/0文件中基本字的源代码 while((ch=fgetc(stream))!='.') { int k=-1; char a[SIZE]; int s=0; while(ch>='a' && ch<='z'||ch>='A' && ch<='Z') { if(ch>='A' && ch<='Z') ch+=32; a[++k]=(char)ch; ch=fgetc(stream); } for(int m=0;m<=12&&k!=-1;m++) for(int n=0;n<=k;n++) {

if(a[n]==wsym[m][n]) ++s; else s=0; if(s==(strlen(wsym[m]))) {printf("%s\t",wsym[m]);m=14;n=k+1;} } 2(提取pl/0文件中标识符的源代码 while((ch=fgetc(stream))!='.') { int k=-1; char a[SIZE]=" "; int s=0; while(ch>='a' && ch<='z'||ch>='A' && ch<='Z') { if(ch>='A' && ch<='Z') ch+=32; a[++k]=(char)ch; ch=fgetc(stream); } for(int m=0;m<=12&&k!=-1;m++) for(int n=0;n<=k;n++) { if(a[n]==wsym[m][n]) ++s; else s=0; if(s==(strlen(wsym[m]))) {m=14;n=k+1;} } if(m==13) for(m=0;a[m]!=NULL;m++) printf("%c ",a[m]);

编译原理课程设计报告_算符优先分析法

编译原理课程设计报告_算符优先分析法 编译原理课程设计报告 选题名称: 算符优先分析法 系(院): 计算机工程学院 专业: 计算机科学与技术 班级: 姓名: 学号: 指导教师: 学年学期: 7>2012 ~ 2013 学年第 1 学期 2012年 12 月 04 日 设计任务书 课题名称算符优先分析法 设计 目的 通过一周的课程设计,对算符优先分析法有深刻的理解,达到巩固理论知识、锻炼实践能力、构建合理知识结构的目的。实验环境Windows2000以上操作系统,Visual C++6.0编译环境 任务要求 1.判断文法是否为算符优先文法,对相应文法字符串进行算符优先分析; 2.编写代码,实现算符优先文法判断和相应文法字符串的算符优先分析; 3.撰写课程设计报告; 4提交报告。工作进度计划序号起止日期工作内容 1 理论辅导,搜集资料 2 ~编写代码,上机调试

3 撰写课程设计报告 4 提交报告 指导教师(签章): 年月日 摘要: 编译原理是计算机专业重要的一门专业基础课程,内容庞大,涉及面广,知识点多。本次课程设计的目的正是基于此,力求为学生提供一个理论联系实际的机会,通过布置一定难度的课题,要求学生独立完成。我们这次课程设计的主要任务是编程实现对输入合法的算符优先文法的相应的字符串进行算符优先分析,并输出算符优先分析的过程。算符优先分析法特别有利于表达式的处理,宜于手工实现。算符优先分析过程是自下而上的归约过程,但这种归约未必是严格的规范归约。而在整个归约过程中,起决定作用的是相继连个终结符之间的优先关系。因此,所谓算符优先分析法就是定义算符之间的某种优先关系,并借助这种关系寻找句型的最左素短语进行归约。通过实践,建立系统设计的整体思想,锻炼编写程序、调试程序的能力,学习文档编写规范,培养独立学习、吸取他人经验、探索前言知识的习惯,树立团队协作精神。同时,课程设计可以充分弥补课堂教学及普通实验中知识深度与广度有限的缺陷。 关键字:编译原理;归约;算符优先分析;最左素短语; 目录 1 课题综述 1 1.1 课题来源 1 1.2课题意义 1 1.3 预期目标 1 1.4 面对的问题 1 2 系统分析 2

编译原理词法分析器语法分析器实验报告

编译技术 班级网络0802 学号3080610052姓名叶晨舟 指导老师朱玉全2011年 7 月 4 日

一、目的 编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。 二、任务及要求 基本要求: 1.词法分析器产生下述小语言的单词序列 这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表: 单词符号种别编码助记符内码值 DIM IF DO STOP END 标识符 常数(整)= + * ** , ( )1 2 3 4 5 6 7 8 9 10 11 12 13 14 $DIM $IF $DO $STOP $END $ID $INT $ASSIGN $PLUS $STAR $POWER $COMMA $LPAR $RPAR - - - - - - 内部字符串 标准二进形式 - - - - - - 对于这个小语言,有几点重要的限制: 首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。例如,下面的写法是绝对禁止的: IF(5)=x 其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。也就是说,对于关键字不专设对应的转换图。但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。 再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。例如,一个条件语句应写为

编译原理 实验3 算符优先分析

编译原理实验3 算符优先分析 一、实验目的 通过设计编制调试构造FIRSTVT集、LASTVT集和构造算符优先表、对给定符号串进行分析的程序,了解构造算符优先分析表的步骤,对文法的要求,生成算符优先关系表的算法,对给定的符号串进行分析的方法。 二、实验内容 1. 给定一文法G,输出G的每个非终结符的FIRSTVT集和LASTVT集。 2. 构造算符优先表。 3. 对给定的符号串进行分析,包含符号栈,符号栈栈顶符号和输入串当前符号的优先级,最左素短语和使用的产生式和采取的动作。 三、程序思路 在文法框内输入待判断文法产生式,格式E->a|S,注意左部和右部之间是“->”,每个产生式一行,ENTER键换行。文法结束再输入一行G->#E# 1. 先做文法判断,即可判断文法情况。 2. 若是算符优先文法,则在优先表栏显示优先表。 3. 写入要分析的句子,按回车即可。 4. 在分析过程栏,可以看到整个归约过程情况 四、实验结果 FunctorFirst.h #include #include #include #include usingnamespace std;

#define rightlength 20 #define product_num 20 // 产生式最多个数 #define num_noterminal 26 // 非终结符最多个数 #define num_terminal 26 // 终结符最多个数 struct Production { char Left; char Right[rightlength]; int num; }; struct VT { bool vt[num_noterminal][num_terminal]; }; struct Stack { char P; char a; }; class CMyDlg { public:CMyDlg(); void InputRule(); CString showLastVT(); CString showFirstVT(); CString shownoTerminal(char G[]); CString showTerminal(char g[]); CString showLeftS(char S[], int j, int k); void InitAll(); CString showSentence(CString sen, int start); CString showStack(char S[], int n); void Initarry(char arry[], int n); CString ProdtoCStr(Production prod); int selectProd(int i, int j, char S[]); void preFunctor(CString sen); void insertFirstVT(Stack S[], int&sp, char P, char a); void insertLastVT(Stack S[], int&sp, char P, char a); void ShowPreTable(); void createPreTable();

编译原理词法分析和语法分析报告+代码(C语言版)

词法分析 一、实验目的 设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 二、实验要求 2.1 待分析的简单的词法 (1)关键字: begin if then while do end 所有的关键字都是小写。 (2)运算符和界符 : = + - * / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义: ID = letter (letter | digit)* NUM = digit digit* (4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。 2.2 各种单词符号对应的种别码: 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列: (1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)…… 三、词法分析程序的算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

3.1 主程序示意图: 主程序示意图如图3-1所示。其中初始包括以下两个方面: ⑴关键字表的初值。 关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表为一个字符串数组,其描述如下: Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,}; 图3-1 (2)程序中需要用到的主要变量为syn,token和sum 3.2 扫描子程序的算法思想: 首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。扫描子程序主要部分流程如图3-2所示。

编译原理实验4算符优先算法

一、实验目的与任务 算术表达式和赋值语句的文法可以是(你可以根据需要适当改变): S→i=E E→E+E|E-E|E*E|E/E|(E)|i 根据算符优先分析法,将赋值语句进行语法分析,翻译成等价的一组基本操作,每一基本操作用四元式表示。 二、实验涉及的相关知识点 算符的优先顺序。 三、实验内容与过程 如参考C语言的运算符。输入如下表达式(以分号为结束):(1)a = 10; (2)b = a + 20; 注:此例可以进行优化后输出(不作要求):(+,b,a,20) (3)c=(1+2)/3+4-(5+6/7); 四、实验结果及分析 (1)输出:(=, a,10,-) (2)输出:(=,r1,20,-)

(+,r2,a,r1) (=,b,r2,-) (3)输出:(+,r1,1,2) (/,r2,r1,3) (/,r3,6,7) (+,r4,5,r3,) (+,r5,r2,4) (-,r6,r5,r4) (=,c,r6,-) 五、实验有关附件(如程序、附图、参考资料,等) ... ... h == '#') o][Peek(n0).No]; if(r == '<') h == 'E'&& Peek(1).ch == '#' && Token[ipToken].ch == '#') return TRUE; else return FALSE; } h) { k = TRUE; h == 'E') { n ++; } return n; } 词结束(遇到“#”号),无法移进,需要规约,返回:1 词没有结束,需判断是否可以移进 栈单词<=单词:移进后返回:2 栈单词>单词:不能移进,需要规约,返回:1 单词没有优先关系:出错,返回:-1 int MoveIn() { SToken s,t; h = '#';

编译原理第六章答案

第6 章自底向上优先分析 第1 题 已知文法G[S]为: S→a|∧|(T) T→T,S|S (1) 计算G[S]的FIRSTVT 和LASTVT。 (2) 构造G[S]的算符优先关系表并说明G[S]是否为算符优先文法。 (3) 计算G[S]的优先函数。 (4) 给出输入串(a,a)#和(a,(a,a))#的算符优先分析过程。 答案: 文法展开为: S→a S→∧ S→(T) T→T,S T→S (1) FIRSTVT - LASTVT 表: 表中无多重人口所以是算符优先(OPG)文法。 友情提示:记得增加拓广文法 S`→#S#,所以# FIRSTVT(S),LASTVT(S) #。 (3)对应的算符优先函数为:

Success! 对输入串(a,(a,a))# 的算符优先分析过程为: Success! 第2 题 已知文法G[S]为: S→a|∧|(T) T→T,S|S

(1) 给出(a,(a,a))和(a,a)的最右推导,和规范归约过程。 (2) 将(1)和题1 中的(4)进行比较给出算符优先归约和规范归约的区别。答案:

(2)算符优先文法在归约过程中只考虑终结符之间的优先关系从而确定可归约串,而与 非终结符无关,只需知道把当前可归约串归约为某一个非终结符,不必知道该非终结符的名字是什么,因此去掉了单非终结符的归约。 规范归约的可归约串是句柄,并且必须准确写出可归约串归约为哪个非终结符。 第3题:

有文法G[S]: S V V T|ViT T F|T+F F )V*|( (1) 给出(+(i(的规范推导。 (2) 指出句型F+Fi(的短语,句柄,素短语。 (3) G[S]是否为OPG?若是,给出(1)中句子的分析过程。 因为该文法是OP,同时任意两个终结符的优先关系唯一,所以该文法为OPG。(+(i(的分析过程

编译原理C语言词法分析器

编译原理 C语言词法分析器 一、实验题目 编制并调试C词法分析程序。 a.txt源代码: ?main() { int sum=0 ,it=1;/* Variable declaration*/ if (sum==1) it++; else it=it+2; }? 设计其词法分析程序,能识别出所有的关键字、标识符、常数、运算符(包括复合运算符,如++)、界符;能过滤掉源程序中的注释、空格、制表符、换行符;并且能够对一些词法规则的错误进行必要的处理,如:标识符只能由字母、数字和下划线组成,且第一个字符必须为字母或下划线。实验要求:要给出所分析语言的词法说明,相应的状态转换图,单词的种别编码方案,词法分析程序的主要算法思想等。 二、实验目的 1、理解词法分析在编译程序中的作用; 2、掌握词法分析程序的实现方法和技术; 3、加深对有穷自动机模型的理解。 三、主要函数 四、设计 1.主函数void main ( )

2. 初始化函数void load ( ) 3. 保留字及标识符判断函数void char_search(char *word) 4. 整数类型判断函数void inta_search(char *word) 5. 浮点类型判断函数void intb_search(char *word)

6. 字符串常量判断函数void cc_search(char *word) 7. 字符常量判断函数void c_search(char *word) 同4、5函数图 8.主扫描函数void scan ( ) 五、关键代码 #include #include

编译原理作业集-第五章-修订(精选.)

第五章语法分析—自下而上分析 本章要点 1. 自下而上语法分析法的基本概念: 2. 算符优先分析法; 3. LR分析法分析过程; 4. 语法分析器自动产生工具Y ACC; 5. LR分析过程中的出错处理。 本章目标 掌握和理解自下而上分析的基本问题、算符优先分析、LR分析法及语法分析器的自动产生工具YACC等内容。 本章重点 1.自下而上语法分析的基本概念:归约、句柄、最左素短语; 2.算符优先分析方法:FirstVT, LastVT集的计算,算符优先表的构造,工作原理;3.LR分析器: (1)LR(0)项目集族,LR(1)项目集簇; (2)LR(0)、SLR、LR(1)和LALR(1)分析表的构造; (3)LR分析的基本原理,分析过程; 4.LR方法如何用于二义文法; 本章难点 1. 句柄的概念; 2. 算符优先分析法; 3. LR分析器基本; 作业题 一、单项选择题: 1. LR语法分析栈中存放的状态是识别________的DFA状态。 a. 前缀; b. 可归前缀; c. 项目; d. 句柄; 2. 算符优先分析法每次都是对________进行归约: (a)句柄(b)最左素短语(c)素短语(d)简单短语

3. 有文法G=({S},{a},{S→SaS,S→ε},S),该文法是________。 a. LL(1)文法; b.二义性文法; c.算符优先文法; d.SLR(1)文法; 4. 在编译程序中,语法分析分为自顶向下分析和自底向上分析两类,和LL(1)分析法属于自顶向下分析; a. 深度分析法 b. 宽度优先分析法 c. 算符优先分析法 d. 递归下降子程序分析法 5. 自底向上语法分析采用分析法,常用的是自底向上语法分析有算符优先分析法和LR分析法。 a. 递归 b. 回溯 c. 枚举 d. 移进-归约 6. 一个LR(k)文法,无论k取多大,。 a. 都是无二义性的; b. 都是二义性的; c. 一部分是二义性的; d. 无法判定二义性; 7. 在编译程序中,语法分析分为自顶向下分析和自底向上分析两类,和LR分析法属于自底向上分析。 a. 深度分析法 b. 宽度优先分析法 c. 算符优先分析法 d. 递归下降子程序分析法 8. 在编译程序中,语法分析分为自顶向下分析和自底向上分析两类,自顶向下分析试图为输入符号串构造一个; a. 语法树 b. 有向无环图 c. 最左推导 d. 最右推导 9. 在编译程序中,语法分析分为自顶向下分析和自底向上分析两类,自底向上分析试图为输入符号串构造一个。 a. 语法树 b. 有向无环图 c. 最左推导 d. 最右推导 10. 采用自顶向下分析方法时,要求文法中不含有。 a. 右递归 b. 左递归 c. 直接右递归 d. 直接左递归 11. LR分析是寻找右句型的;而算符优先分析是寻找右句型的。 a. 短语; b. 素短语; c. 最左素短语; d. 句柄 12. LR分析法中分析能力最强的是;分析能力最弱的是。 a. SLR(1); b. LR(0); c. LR(1); d. LALR(1) 13. 设有文法G: T->T*F | F F->F↑P | P P->(T) | a 该文法句型T*P↑(T*F)的最左直接短语是下列符号串________。 a. (T*F), b. T*F, c. P, d. P↑(T*F) 14. 在通常的语法分析方法中,()特别适用于表达式的分析。 a.算符优先分析法b.LR分析法c.递归下降分析法d.LL(1)分析法 15. .运算符的优先数之间有几种关系。 a.3种 b. 2种 c. 4种 d. 1种 16. 算符优先法属于() a.自上而下分析法 b.LR分析法 c.SLR分析法 d.自下而上分析法 17. 在LR分析法中,分析栈中存放的状态是识别规范句型的DFA状态。 a.句柄 b. 前缀 c. 活前缀 d. LR(0)项目 一.答案: 1. b; 2. b; 3. b; 4. d; 5. d; 6. a; 7. c; 8. c; 9. d;10. b;11. d,c;12. c,b;13. a;14. a 15. a;16. d;17. c;

编译原理实验报告(词法分析器语法分析器)

编译原理实验报告

实验一 一、实验名称:词法分析器的设计 二、实验目的:1,词法分析器能够识别简单语言的单词符号 2,识别出并输出简单语言的基本字.标示符.无符号整数.运算符.和界符。 三、实验要求:给出一个简单语言单词符号的种别编码词法分析器 四、实验原理: 1、词法分析程序的算法思想 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 2、程序流程图 (1 (2)扫描子程序

3

五、实验内容: 1、实验分析 编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符。字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。 2 实验词法分析器源程序: #include #include #include int i,j,k; char c,s,a[20],token[20]={'0'}; int letter(char s){ if((s>=97)&&(s<=122)) return(1); else return(0); } int digit(char s){ if((s>=48)&&(s<=57)) return(1); else return(0); } void get(){ s=a[i]; i=i+1; } void retract(){ i=i-1; } int lookup(char token[20]){ if(strcmp(token,"while")==0) return(1); else if(strcmp(token,"if")==0) return(2); else if(strcmp(token,"else")==0) return(3); else if(strcmp(token,"switch")==0) return(4); else if(strcmp(token,"case")==0) return(5); else return(0); } void main() { printf("please input string :\n"); i=0; do{i=i+1; scanf("%c",&a[i]);

编译原理简答

1、给出算符优先文法的定义,算符优先表是否都存在对应的优先函数给出优先函数的定义。 设有一不含ε产生式的算符文法G,如果对任意两个终结符对a,b之间至多只有、和h三种关系的一种成立,则称G一个算符优先文法。 算符优先关系表不一定存在对应的优先函数 优先函数为文法字汇表中 2、考虑文法G[T]: T→T*F|F F→F↑P|P P→(T)|i 证明T*P↑(T*F)是该文法的一个句型,并指出直接短语和句柄。 首先构造T*P↑(T*F)的语法树如图所示。 句型T*P↑(T*F)的语法树 由图可知,T*P↑(T*F)是文法G[T]的一个句型。 直接短语有两个,即P和T*F;句柄为P。

3、文法G[S]为: S→SdT | T T→T

4、目标代码有哪几种形式生成目标代码时通常应考虑哪几个问题 三种形式:可立刻执行的机器语言代码;汇编语言程序;待装配的机器语言代码模块 考虑的问题包括: 每一个语法成分的语义; 目标代码中需要哪些信息,怎样截取这些信息。 5、符号表的作用是什么符号表的查找的整理技术有哪几种 作用:登记源程序中出现的各种名字及其信息,以及编译各阶段的进展状况。主要技术:线性表,对折查找与二叉树,杂凑技术。 1、实现高级语言程序的途径有哪几种它们之间的区别 计算机执行用于高级语言编写的程序主要有两种途径:解释和编译。 在解释方式下,翻译程序并不对高级语言进行彻底的翻译,而是读入一条语句,就解释其含义并执行,然后再读入下一条语句,再执行。 在编译方式下,翻译程序先对高级语言进行彻底的翻译并生成目标代码,然后再对目标代码进行优化,即对源程序的处理是先翻译后执行。 从速度上看,编译方式下,源程序的执行比解释方式下快,但在解释方式下,有

编译原理词法分析器语法分析课程设计报告书

《编译原理》 课程设计 院系信息科学与技术学院 专业软件工程 年级 2011级 学号 20112723 姓名林苾湲 西南交通大学信息科学与技术学院 2013年 12月

目录 课程设计1 词法分析器 (2) 1.1 设计题目 (2) 1.2 设计容 (2) 1.3 设计目的 (2) 1.4 设计环境 (2) 1.5 需求分析 (2) 1.6 概要设计 (2) 1.7 详细设计 (4) 1.8 编程调试 (5) 1.9 测试 (11) 1.10 结束语 (13) 课程设计2 赋值语句的解释程序设计 (14) 2.1 设计题目 (14) 2.2 设计容 (14) 2.3 设计目的 (14) 2.4 设计环境 (14) 2.5 需求分析 (15) 2.6 概要设计 (16) 2.7 详细设计 (16) 2.8 编程调试 (24) 2.9 测试 (24) 2.10 结束语 (25)

课程设计一词法分析器设计 一、设计题目 手工设计c语言的词法分析器(可以是c语言的子集)。 二、设计容 处理c语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中。 三、设计目的 了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。 四、设计环境 该课程设计包括的硬件和软件条件如下: 4.1.硬件 (1)Intel Core Duo CPU P8700 (2)存4G 4.2.软件 (1)Window 7 32位操作系统 (2)Microsoft Visual Studio c#开发平台 4.3.编程语言 C#语言 五、需求分析 5.1.源程序的预处理:源程序中,存在许多编辑用的符号,他们对程序逻辑功能无任何影响。例如:回车,换行,多余空白符,注释行等。在词法分析之前,首先要先剔除掉这些符号,使得词法分析更为简单。 5.2.单词符号的识别并判断单词的合法性:将每个单词符号进行不同类别的划分。单词符号可以划分成5中。 (1)标识符:用户自己定义的名字,常量名,变量名和过程名。 (2)常数:各种类型的常数。 (3) 保留字(关键字):如if、else、while、int、float等。 (4) 运算符:如+、-、*、<、>、=等。 (5)界符:如逗号、分号、括号等。 5.3.将所有合法的单词符号转化为便于计算机处理的二元组形式:(单词分类号,单词自身值);以图形化界面显示出来。 5.4.可选择性地将结果保存到文件中。 六、概要设计 6.1.数据类型 6.1.1.单词的分类:本词法分析器演示的是C语言的一个子集,故字符集如下:

编译原理 六章 算符优先分析法

第六章算符优先分析法 课前索引 【课前思考】 ◇什么是自下而上语法分析的策略? ◇什么是移进-归约分析? ◇移进-归约过程和自顶向下最右推导有何关系? ◇自下而上语法分析成功的标志是什么? ◇什么是可归约串? ◇移进-归约过程的关键问题是什么? ◇如何确定可归约串? ◇如何决定什么时候移进,什么时候归约? ◇什么是算符文法?什么是算符优先文法? ◇算符优先分析是如何识别可归约串的? ◇算符优先分析法的优缺点和局限性有哪些? 【学习目标】 算符优先分析法是自下而上(自底向上)语法分析的一种,尤其适应于表达式的语法分析,由于它的算法简单直观易于理解,因此,也是学习其它自下而上语法分析的基础。通过本章学习学员应掌握: ◇对给定的文法能够判断该文法是否是算符文法 ◇对给定的算符文法能够判断该文法是否是算符优先文法 ◇对给定的算符文法能构造算符优先关系表,并能利用算符优先关系表判断该文法是否是算符优先文法。 ◇能应用算符优先分析算法对给定的输入串进行移进-归约分析,在分析的每一步能确定当前应移进还是归约,并能判断所给的输入串是否是该文法的句子。 ◇了解算符优先分析法的优缺点和实际应用中的局限性。 【学习指南】 算符优先分析法是自下而上语法分析的一种,它的算法简单、直观、易于理解,所以通常作为学习其它自下而上语法分析的基础。为学好本章内容,学员应复习有关语法分析的知识,如:什么是语言、文法、句子、句型、短语、简单短语、句柄、最右推导、规范归约基本概念。 【难重点】 ◇通过本章学习后,学员应该能知道算符文法的形式。 ◇对一个给定的算符文法能构造算符优先关系分析表,并能判别所给文法是否为算符优先文法。 ◇分清规范句型的句柄和最左素短语的区别,进而分清算符优先归约和规范归约的区别。 ◇算符优先分析的可归约串是句型的最左素短语,在分析过程中如何寻找可归约串是算符优先分析的关键问题。对一个给定的输入串能应用算符优先关系分析表给出分析(归约)步骤,并最终判断所给输入串是否为该文法的句子。 ◇深入理解算符优先分析法的优缺点和实际应用中的局限性。 【知识点】

编译原理词法分析器

一、实验目的 了解词法分析程序的两种设计方法:1.根据状态转换图直接编程的方式;2.利用DFA 编写通用的词法分析程序。 二、实验内容及要求 1.根据状态转换图直接编程 编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。在此,词法分析程序作为单独的一遍,如下图所示。 具体任务有: (1)组织源程序的输入 (2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件 (3)删除注释、空格和无用符号 (4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。将错误信息输出到屏幕上。 (5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。 标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址 注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。 常量表结构:常量名,常量值 2.编写DFA模拟程序 算法如下: DFA(S=S0,MOVE[][],F[],ALPHABET[]) /*S为状态,初值为DFA的初态,MOVE[][]为状态转换矩阵,F[] 为终态集,ALPHABET[] 为字母表,其中的字母顺序与MOVE[][] 中列标题的字母顺序一致。*/ { Char Wordbuffer[10]=“”//单词缓冲区置空 Nextchar=getchar();//读 i=0; while(nextchar!=NULL)//NULL代表此类单词 { if (nextcha r!∈ALPHABET[]){ERROR(“非法字符”),return(“非法字符”);} S=MOVE[S][nextchar] //下一状态 if(S=NULL)return(“不接受”);//下一状态为空,不能识别,单词错误 wordbuffer[i]=nextchar ;//保存单词符号 i++; nextchar=getchar(); } Wordbuffer[i]=‘\0’;

编译原理-语法分析-算符优先文法分析器

编译原理实验报告 实验名称:编写语法分析分析器实验类型: 指导教师: 专业班级: 学号: 电子邮件: 实验地点: 实验成绩:

一、实验目的 通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。 1、选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析程序和LR分析分析程序,至少选一题。 2、选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。 二、实验过程 编写算符优先分析器。要求: (a)根据算符优先分析算法,编写一个分析对象的语法分析程序。读者可根据自己的能力选择以下三项(由易到难)之一作为分析算法中的输入: Ⅰ:通过构造算符优先关系表,设计编制并调试一个算法优先分析程序Ⅱ:输入FIRSTVT,LASTVT集合,由程序自动生成该文法的算符优先关系矩阵。 Ⅲ:输入已知文法,由程序自动生成该文法的算符优先关系矩阵。(b)程序具有通用性,即所编制的语法分析程序能够使用于不同文法以及各种输入单词串,并能判断该文法是否为算符文法和算符优先文法。 (c)有运行实例。对于输入的一个文法和一个单词串,所编制的语法分析程序应能正确地判断,此单词串是否为该文法的句子,并要求输出分析过程。 三、实验结果 算符优先分析器: 测试数据:E->E+T|T T->T*F|F F->(E)|i 实验结果:(输入串为i+i*i+i)

四、讨论与分析 自下而上分析技术-算符优先分析法: 算符文法:一个上下无关文法G,如果没有且没有P→..QR...(P ,Q ,R属于非终结符),则G是一个算符文法。 FIRSTVT集构造 1、若有产生式P →a...或P →Qa...,则a∈FIRSTVT(P)。 2、若有产生式P→...,则FIRSTVT(R)包含在FIRSTVT(P)中。由优先性低于的定义和firstVT集合的定义可以得出:若存在某个产生式:…P…,则对所有:b∈firstVT(P)都有:a≦b。 构造优先关系表: 1、如果每个非终结符的FIRSTVT和LASTVT集均已知,则可构造优先关系表。 2、若产生式右部有...aP...的形式,则对于每个b∈FIRSTVT(P)都有

编译原理算符优先算法语法分析实验报告

数学与计算机学院编译原理实验报告 年级专业学号姓名成绩 实验题目算符优先分析法分析器的设计实验日期 一、实验目的: 设计一个算符优先分析器,理解优先分析方法的原理。 二、实验要求: 设计一个算符优先分析器 三、实验内容: 使用算符优先分析算法分析下面的文法: E’→#E# E →E+T | T T →T*F | F F →P^F | P P →(E) | i 其中i可以看作是一个终结符,无需作词法分析。具体要求如下: 1、如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的变化情况; 2、如果输入符号串不是正确句子,则指示出错位置。 四、实验结果及主要代码: 1.主要代码 void operatorp()

{ char s[100]; char a,Q; int k,j,i,l; string input,temp; cin>>input; cout<<"步骤"<<'\t'<<"栈"<<'\t'<<"优先关系"<<'\t'<<"当前符号"<<'\t'<<"剩余输入串"<<'\t'<<"移进或归约"<') { cout<<'('<

for(l=1;l'<<'\t'<

编译原理词法分析实验报告

词法分析器实验报告 一、实验目的 选择一种编程语言实现简单的词法分析程序,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 二、实验要求 2、1 待分析的简单的词法 (1)关键字: begin if then while do end 所有的关键字都就是小写。 (2)运算符与界符 : = + - * / < <= <> > >= = ; ( ) # (3)其她单词就是标识符(ID)与整型常数(SUM),通过以下正规式定义: ID = letter (letter | digit)* NUM = digit digit* (4)空格有空白、制表符与换行符组成。空格一般用来分隔ID、SUM、运算符、界符与关键字,词法分析阶段通常被忽略。 2、2 各种单词符号对应的种别码: 表2、1 各种单词符号对应的种别码 2、3 词法分析程序的功能: 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列: (1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)…… 三、词法分析程序的算法思想: 算法的基本任务就是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想就是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 3、1 主程序示意图:

主程序示意图如图3-1所示。其中初始包括以下两个方面: ⑴ 关键字表的初值。 关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表为一个字符串数组,其描述如下: Char *rwtab[6] = {“begin ”, “if ”, “then ”, “while ”, “do ”, “end ”,}; (2)3、2 扫描子程序的算法思想: 首先设置3个变量:①token 用来存放构成单词符号的字符串;②sum 用来整型单词;③syn 用来存放单词符号的种别码。扫描子程序主要部分流程如图3-2所示。

编译原理实验-词法分析器的设计与实现.docx

南华大学 计算机科学与技术学院实验报告 (2018~2019学年度第二学期) 课程名称编译原理 实验名称词法分析器的设计与 实现 姓名学号 专业班级 地点教师

1.实验目的及要求 实验目的 加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。 实验要求 1.对单词的构词规则有明确的定义; 2.编写的分析程序能够正确识别源程序中的单词符号; 3.识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护 符号表; 4.对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误 提示,保证顺利完成整个源程序的词法分析; 2.实验步骤 1.词法分析规则 <标识符>::=<字母>|<标识符><字母>|<标识符><数字> <常数>::=<数字>|<数字序列><数字> <数字序列>::=<数字序列><数字>|<数字>|<.> <字母>::=a|b|c|……|x|y|z <数字>::=0|1|2|3|4|5|6|7|8|9 <运算符>::=<关系运算符>|<算术运算符>|<逻辑运算符>|<位运算符>|<赋值运算符> <算数运算符>::=+|-|*|/|...|-- <关系运算符>::=<|>|!=|>=|<=|== <逻辑运算符>::=&&| || |! <位运算符>::=&| | |! <赋值运算符>::==|+=|-=|/=|*= <分界符>::=,|;|(|)|{|}|:| // |/**/ <保留字>::=main|if|else|while|do|for|...|void

编译原理词法分析及语法分析

编译原理 实验报告 实验名称:词法分析及语法分析专业班级: 姓名: 学号: 完成日期:

实验一、sample语言的词法分析 一、实验目的 给出SAMPLE文法规范,要求编写SAMPLE语言的词法分析程序。 二、实验准备 了解sample语言单词的定义,选择任一种编程语言实现词法分析。 三、实验内容 给出SAMPLE语言文法,输出单词(关键字、专用符号以及其它标记)。 1、格式 输入:源程序文件。输出:关键字、专用符号以及其它标记。 2、实现原理 程序中先判断这个句语句中每个单元为关键字、常数、运算符、界符,对与不同的单词符号给出不同编码形式的编码,用以区分之。 3、实验方法 读懂Sample源代码,自己重点独立实现对常量的判别。 四、实验设计 1、设计SAMPLE语言的词法分析器 A、字符集定义 1. <字符集> → <字母>│<数字>│<单界符> 2. <字母> → A│B│…│Z│a│b│…│z 3. <数字> → 0│1│2│…│9 4. <单界符> → +│-│*│/│=│<│>│(│)│[│]│:│. │; │, │' B、单词集定义 5.<单词集> → <保留字>│<双界符>│<标识符>│<常数>│<单界符> 6.<保留字> → and│array│begin│bool│call│case│char│constant│dim│do│else │end│false│for│if│input│integer│not│of│or│output│procedure│program │read│real│repeat│set│stop│then│to│true│until│var│while│write 7.<双界符> → <>│<=│>=│:= │/*│*/│.. 8.<标识符> → <字母>│<标识符> <数字>│<标识符> <字母> 9.<常数> → <整数>│<布尔常数>│<字符常数> 10.<整数> → <数字>│<整数> <数字> 11.<布尔常数> → true│false 12.<字符常数> → ' 除 {'} 外的任意字符串 ' 2、词法分析系统流程设计

相关主题
文本预览
相关文档 最新文档