当前位置:首页 » 编程软件 » 编译原理switch实验

编译原理switch实验

发布时间: 2022-08-27 03:17:35

‘壹’ 编译原理实验报告

#include<stdio.h>
void main()
{

int m=0,n=0,n1=0,n2=0,n3=0,zg,fzg,flag;
int bz[7]=;/*状态改变控制,1 表示可以改变状态zt值,0 表示不可以*/
int zt[7]=;/*状态值,2表示未定状态,1表示 是,0表示 否*/

char temp[100]="\0";/*用于求first集*/
char z[7];/*非总结符*/
char z1[7];/*总结符*/
char z2[7]="\0";/*gs[]文法中出现的标记个数的辅助字符 01234*/
char gs[100]="\0";/*文法,按顺序排成字符串*/

printf("请依次输入非终结符(不超过7个):");
gets(z);
while(z[m]!='\0')

fzg=m;//zg是非终结符个数

while(n<m)
//生成01234辅助字符
printf("您输入了:");
puts(z);
fflush(stdin);

printf("请依次输入终结符(不超过7个):");
gets(z1);
while(z1[n1]!='\0')

zg=n1;
printf("您输入了:");
puts(z1);
fflush(stdin);

printf("按照正确格式输入所有文法(总长度不超过100格式如下):");
printf("如果文法为(字符'k'表示空):\n");
printf("S-->AB S-->bC A-->k A-->b\n");
printf("输入:0SAB0SbC1Ak1Ab\n");
printf(" (注:数字01234表示第一二三四个非终结符)\n");

gets(gs);
fflush(stdin);
printf("您输入了:");
puts(gs);
m=0;
//对于输入文法字符串的转换,将每个文法式左部去除
while(gs[m]!='\0')
{
n=m;
if(gs[m]>='0'&&gs[m]<='9')
{
m++;
while(gs[m]!='\0')
{
gs[m]=gs[m+1];
m++;
}
//gs[m-1]='\0';
}
m=++n;
}

m=0;

//puts(gs);

/*情况一,直接判定是 形如: (A-->k) */
while(gs[m]!='\0')
{
if(gs[m]=='k')
{
zt[gs[m-1]-48]=1;
bz[gs[m-1]-48]=0;
}
m++;
}

/*情况二,直接判定--否 形如: (D-->aS ,D-->c) */
for(n=0;n<fzg;n++)
{
if(bz[n]==1)
{
m=0;
n2=0;
while(gs[m]!='\0')
{
if(z2[n]==gs[m])
{
if(gs[m+1]>=z1[0]&&gs[m+1]<=z1[n1-1])
zt[n]=0;
else //gs[m+1] 是非终结符n2做标记
}
//跳出循环,无法解决该情况,推到下面情况三
m++;
}
if(n2!=99) //完成所有扫描,未出现非终结符,得出结论zt[n]=0.bz[n]=0不允许再改变zt[n]
}
}

/*情况三,最终判定*/
do
{
flag=0;
for(n=0;n<fzg;n++)
{
if(bz[n]==1) //未得到判定
{ m=0;
while(gs[m]!='\0')
{
if(gs[m]==z2[n]) //判定gs[m]是辅助字符0123
{
m++;
while(gs[m]>='A'&&gs[m]<='Z')
{

n1=0;
for(n2=0;n2<fzg;n2++) //循环查找是gs[m]哪个非终结符
{
if(gs[m]==z[n2])
{
if(zt[n2]==1) //这个非终结符能推出空
zt[n]=1;
else if(bz[n2]==1) //这个非终结符 现在 不能推出空,但它的状态可改即它最终结果还未判定

else
//设 m1 做标记供下一if参考
break; //找到gs[m]是哪个非终结符,for循环完成任务,可以结束
}

}
if(n1==99) break;
m++;
}
}
m++;
}
if(zt[n]==1) bz[n]=0;
if(bz[n]==0) flag=1;//对应for下的第一个if(zt[n]==2)
}

}
}while(flag);

printf("结果是:\n");

for(m=0;m<5;m++)
{
switch(zt[m])
{
case 0:printf("%c---否\n",z[m]);break;
case 1:printf("%c---是\n",z[m]);break;
case 2:printf("%c---未定\n",z[m]);break;
}

}
/*
puts(gs);
puts(zt);
puts(z);
puts(z1);
puts(z2);
printf("%d,,,%d",fzg,zg);
*/

//下面求first集
//下面求first集

for(n=0;n<fzg;n++)

m=0;n=0;n1=0;n2=0;
while(gs[n]>='0'&&gs[n]<='9')
{
for(;m<fzg;m++)
{
if(n2!=m)
n1=0; //m=n2用于第二次以后的for循环中还原上次m的值

if(gs[n]==z2[m])
{
while(gs[n+1]>'9')
{
if(n1==0)
//如果是第一个直接保存

//不是第一个,先与字符数组中其它字符比较,没相同的才保存
else if(gs[n]>='a'&&gs[n]<='z'&&gs[n+1]>='A'&&gs[n+1]<='Z') //gs[n]是终结符 且 gs[n+1]是非终结符
;//什么也不做,程序继续n++,扫描下一个gs[n]

else
{
for(n3=0;n3<=n1;n3++)
{
if(temp[m*13+n3]==gs[n+1])
break;
}

if(n3>n1) //for循环结束是因为n3而不是break

}
n++;
}
break; //break位于if(gs[n]==z2[m]),对于gs[n]已找到z2[m]完成任务跳出for循环
}
}
n2=m; //存放该for循环中m的值
n++;
}
//进一步处理集除去非终结符
m=0;n=0;n1=0;n2=0;
for(m=0;m<fzg;m++)
{
if(flag!=m)
n1=0; //m=flag用于第二次以后的for循环中还原上次m的值

while(temp[m*13+n1]!='\0')
{
while(temp[m*13+n1]>='A'&&temp[m*13+n1]<='Z') //搜索非终结符
{
for(n=0;n<fzg;n++) //确定是哪个非终结符
{if(temp[m*13+n1]==z[n])
break;
}
while(temp[m*13+n1]!='\0') //从temp[n*13+n1]开始每个字符依次往前移动一

n1--;
while(temp[n*13+n2]!='\0') //把z[n]对应的first加入temp[m*13+n1]这个first中,每个字符依次加在最后
{
for(n3=0;n3<n1;n3++) //循环判定是否有相同的字符
{
if(temp[m*13+n3]==temp[n*13+n2])
break;
}
if(temp[n*13+n2]=='k'&&zt[m]==0) //那些不能推出 空,但是因为要加入 其他非终结符的first集 而可能含有 空
n2++;
else if(n3>=n1) //for循环结束是因为n3而不是break ,即无相同字符

else n2++;
}

n1=0;
n2=0;
}

n1++;
}
flag=m; //存放该for循环中m的值
}

//非终结符的first集输出
m=0;n1=0;
for(m=0;m<fzg;m++)
{
n1=0;
printf("非终结符 %c 的first集是: ",z[m]);
while(temp[m*13+n1]!='\0')
{
printf("%c",temp[m*13+n1]);
n1++;
}
printf("\n");
}

}

‘贰’ 这个编译会出现错误,说switch是非法的类型开始,我觉得一点问题都没有啊,求指教

因该是警告,因为你switch定值。在预编译的时候会把不必要的代码过滤掉。因为必然是'c'。并警告

‘叁’ 学了编译原理这门课,要求编一个:词法分析的程序,要求对词法分析至少选择三种不同类型的句子进行单词识

给你一个toyl语言的
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<windows.h>
#define is_end_of_input(ch) ((ch)=='#')
#define is_letter(ch) ('A'<=(ch)&&(ch)<='Z'||'a'<=(ch)&&(ch)<='z')
#define is_digit(ch) ('0'<=(ch)&&(ch)<='9')
#define is_digit_or_letter(ch) (is_letter(ch)||is_digit(ch))
#define is_operator(ch) ((ch)=='+'||(ch)='-'||(ch)='*')
#define is_layout(ch) (!is_end_of_input(ch)&&(ch)<=' ')
#define Step 10 //字符串每次增长的长度.

typedef struct
{
char * Class;
char seman[];
int len;
int value;
}mytoken;

typedef struct node
{
char words[20];
int length;
int time;
struct node *next;
}mynode;
//全局变量
char ch;
char *fp;
mytoken token;
int TYPE=-1;
int num=1;
int j=0;
int Length=0;
void error()//报错
{
printf("错误\n");
}

char * getstr() //从键盘获取任意长度的输入函数实现
{
char *temp, *str=(char *)malloc(10);
int c=0, len=0, times=1, number=0;
if(!str)
{
printf("内存不足!");
return (char *)NULL;
}
number+=times*Step;

do //遇到#则输入结束。
{
c=getchar();
if(len==number)
{
times++;
number=times*Step;
temp=str;
str=(char *)realloc(str,number);
if(str==NULL)
{
printf("内存不足!");
str=temp;
break;
}
}
*(str+len)=c;
len++;
}while(c!='#');
str=(char *)realloc(str,len+1); //字符串的最终长度调整.
*(str+len)='\0';
return str;
}

void next_char(void)//获取下一个字符
{
ch=*fp;
fp=fp+1;

}

void next_valchar(void)//获取第一个有效的字符,过滤空格等。
{
next_char();
if(ch=='#')exit(0);//当文件只有空格和#号时
while(is_layout(ch))
{
next_char();
//if(ch=='#')exit(0);
}
}

void back()//指针回走
{
fp=fp-1;
}

void recongnize_name(char chr)//识别字符串
{
char name[10];
int i=0;
name[i++]=ch;
next_char();
while(is_digit_or_letter(ch))
{
name[i++]=ch;
next_char();

}

if((ch!=' ')&&(ch!='\t')&&(ch!='\n')&&(ch!='#')&&(ch!=':')&&(ch!='(')&&(ch!=')')&&(ch!=';'))//转非法字符串处理
{

do
{
name[i++]=ch;
next_char();

}while((ch!=' ')&&(ch!='\t')&&(ch!='\n')&&(ch!='#'));
if((name[i-1]=='#')||(name[i-1]=='\n'))//去掉结束符#或回车
{
name[i-1]='\0';
}
back();//指针回走
name[i]='\0';
printf("非法字符串\t%s\n",name);

}
else{
name[i]='\0';
if (name== "begin")
{
token.Class="BEGIN";
}
else if (name== "end")
{
token.Class="END";
}
else if (name=="read")
{
token.Class=="READ";
}
else if (name=="write")
{
token.Class="WRITE";
}
else
{
token.Class="IDEN";
int n=0;
Length=0;
while(name[n]!='\0')
{

token.seman[n]=name[n];
n++;
}
Length=n;
token.seman[n]=name[n];

}
back();
}
}

void recongnize_number(char cha)//识别数字
{
int N=0;
int m;
char name[10];//存非法字符串
int i=0;
while((m=is_digit(ch)))
{
N=N*10+(ch-'0');

name[i++]=ch;
next_char();
}
if(ch==' '||ch=='\t'||ch=='\n'||ch=='#'||(ch==';'))
{
token.Class="NUMB";
token.value=N;
back();
}
else//转非法字符串处理
{

do
{
name[i++]=ch;
next_char();

}while((ch!=' ')&&(ch!='\t')&&(ch!='\n')&&(ch!='#'));
if((name[i-1]=='#')||(name[i-1]=='\n'))//去掉结束符#或回车
{
name[i-1]='\0';
}
back();//指针回走
name[i]='\0';
printf("非法字符串\t%s\n",name);
TYPE=-1;

}

}

int next_token(void)//读下一个单词
{
next_valchar();
char name[10];//存首字母非法的字符串
int fg=0;
int i=0;
if('0'<=(ch)&&(ch)<='9')
{
TYPE=0;
}
else if('A'<=(ch)&&(ch)<='Z'||'a'<=(ch)&&(ch)<='z')
{
TYPE=1;
}
else
{
TYPE=2;
}

switch(TYPE)
{
case 0:
recongnize_number(ch);break;
case 1:
recongnize_name(ch);break;
case 2:
switch(ch)
{
case '+' :
token.Class="ADD";
token.seman[0]='+';
token.seman[1]='\0';
TYPE=2;
break;
case '*' :
token.Class="MULT";
token.seman[0]='*';
token.seman[1]='\0';
TYPE=2;
break;
case ':' :
next_char();
if(ch!='=')
{
error();
TYPE=-1;
break;
}
token.Class="ASS";
token.seman[0]=':';
token.seman[1]='=';
token.seman[2]='\0';
TYPE=2;
break;
case ';' :
token.Class="SEMI";
token.seman[0]=';';
token.seman[1]='\0';
TYPE=2;
break;
case '(' :
token.Class="OPEN";
token.seman[0]='(';
token.seman[1]='\0';
TYPE=2;
break;
case ')' :
token.Class="CLOSE";
token.seman[0]=')';
token.seman[1]='\0';
TYPE=2;
break;
default :
fg=1;
break;

}
}
if(fg==1)//非法字符串处理
{
name[i++]=ch;
while((ch!=' ')&&(ch!='\t')&&(ch!='\n')&&(ch!='#'))
{
next_char();
name[i++]=ch;
}
if((name[i-1]=='#')||(name[i-1]=='\n'))//去掉结束符#或回车

{
name[i-1]='\0';
}
back();//指针回走
name[i]='\0';
printf("非法字符串\t%s\n",name);
TYPE=-1;//置TYPE为-1
}

}

int compare(node *head,char words[],int Length)//单词的比较
{
node *p;
p=head;
if(head==NULL)
{
return 0;
}
else
{

int fg=1;

do
{
int i,j,succ;
i=0;
succ=0;
while((i<=p->length-Length)&&(!succ))
{
j=0;
succ=1;
while((j<Length)&&succ)
{
if(words[j]==(p->words[i+j]))
{
j++;
}
else
{
succ=0;
}

}
i++;
}
if(succ&&(j>=p->length))
{
(p->time)++;
fg=0;

}
if(p->next!=NULL)
{
p=p->next;
}

}while((p->next!=NULL)&&fg);

if(fg==0)
{
return 1;
}
else
{
return 0;
}

}
}

node *insert(node *head) //将读到的新单词加入链表
{
node *p;
p=(mynode*)malloc(sizeof(mynode));/*分配空间*/
strcpy(p->words,token.seman);
int n=0;
p->length=0;
p->time=1;
while(p->words[n]!='\0')
{
p->length++;
n++;
}
p->next=NULL;
if(head==NULL)
{
head=p;
}
else
{
p->next=head->next;
head->next=p;
}

return head;
}

void display(node *head)//打印链表的内容
{
node *p;
p=head;
if(!p) printf("\n无标识符!");
else
{
printf("\n各标识符或保留字及其出现的次数为:\n");
printf("标识符\t出现次数\n");
while(p) { printf("%s\t%d\n",p->words,p->time);p=p->next;}

}
}

int main(int argc, char *argv[])
{
char *str1=NULL;
printf("请输入程序代码:\n");
str1=getstr();//获取用户程序段的输入
fp=str1;
mynode *head=NULL;
do{
next_token();

switch(TYPE)
{
case 0:
printf("[%d]\t(%s,\t\"%d\")\n",num++,token.Class,token.value);
break;
case 1:
case 2:
printf("[%d]\t(%s,\t\"%s\")\n",num++,token.Class,token.seman);
int f;
f=0;
f=compare(head,token.seman,Length);
if((TYPE==1)&&(f==0))
{

head=insert(head);
}
break;
default:
break;
}

}while(*fp!='#');

display(head);
return 0;
}

‘肆’ 反汇编中的switch结构

因为switch 有一个参数,他要存储表达式的值,比如你写swtch(a*4),那么就要有个存储单元来存a*4的值,也就是[ebx-8]指的单元就是表达式的值,[ebx-4]是a的值,这个值要传给switch做参数,所以就多4个字节,包括while也是一个道理,他需要有一个bool型的参数,虽然你没声明这个变量,但因为用了这些语句就隐含进去了,你这个只是因为表达式只是个a,但是编译器并不会管你是否表达式只是个变量,你把你的switch(a),看成switch(1*a)就很容易理解。。。
有时候你表达式很长,总有几个中间值要存,没地方存总要入栈,虽然你没有定义这些变量,
但汇编代码是要用的所以就要多几个字节,入栈数量并不总和参数以及自动变量之和相等。。。

‘伍’ 编译原理课设实现C/C++语言词法分析器

既然是c语言词法分析器,那就是用c/c++对一段c语言文本进行词法分析,c语言中的for语句、while语句、switch语句、if语句等等的进行分析并将其提取出来的一个设计和实现过程而矣
这是大学专门有一门《编译原理》的课程而矣

‘陆’ 编译原理用C语言实现基于LR(1)或SLR(1)语法分析程序代码,最好还有报告,急。。。

这个是精简的语法分析程序,如果符合的话,hi我
给你实验报告

#include <stdio.h>
#include<dos.h>
#include<stdlib.h>
#include<string.h>
char a[50] ,b[50];
char ch;
int n1,i1=0,n=5;
int E();int T();int E1();int T1();int F();
void main() /*递归分析*/
{
int f,j=0;
printf("请输入字符串(长度<50,以#号结束)\n");
do{
scanf("%c",&ch);
a[j]=ch;
j++;
}while(ch!='#');
n1=j;
ch=b[0]=a[0];
f=E();
if (f==0) return;
if (ch=='#') printf("accept\n");
else printf("error\n");
}

int E() // E→TE'
{ int f,t;
f=T();
if (f==0) return(0);
t=E1();
if (t==0) return(0);
else return(1);
}

int T() // T→FT'
{ int f,t;
f=F();
if (f==0) return(0);
t=T1();
if (t==0) return(0);
else return(1);
}

int E1()/*E’*/ // E'→+TE'
{ int f;
if(ch=='+') {
b[i1]=ch;
ch=a[++i1];
f=T();
if (f==0) return(0);
E1();
return(1);
}
return(1);
}

int T1()/*T’*/ // T'→*FT'
{
int f,t;
if(ch=='*') {
b[i1]=ch;
ch=a[++i1];
f=F();
if (f==0) return(0);
t=T1();
if (t==0) return(0);
else return(1);}
a[i1]=ch;
return(1);
}

int F() // F→(E)
{ int f;
if(ch=='(') {
b[i1]=ch;
ch=a[++i1];
f=E();
if (f==0) return(0);
if(ch==')') {
b[i1]=ch;
ch=a[++i1];
}
else {
printf("error\n");
return(0);
}
}
else if(ch=='i') {
b[i1]=ch;
ch=a[++i1];
}
else {printf("error\n");return(0);}
return(1);
}

‘柒’ c关于switch问题,这是什么原理

当case语句大于等于4的时候,且每两个case之间产生的间隔之和不超过6时,就按线性结构查找。即,如下图的汇编里面的jmp dword ptr [edx*4+11B1428h]该指令里面的11B1428h地址里面,其存放着各个case语句的首地址。由于内存中下标是从0开始的,因此,通过对其进行减一操作,在判断其是否大于11B1428h地址的数组长度,如果大于直接跳出,否则通过计算直接定位到该数组上的地址进行跳转。

‘捌’ 急求!!!用C语言编写一个编译原理实验的简单优先分析法程序

编译原理IF条件语句的翻译程序设计—简单优先法、输出四元式通过设计、编制、调试一个条件语句的语法及语义分析程序,加深对语法及语义分析原理的理解,并实现词法分析程序对单词序列的词法检查和分析。具体做到以下几点:①对输入语句进行词法分析。将输入的字符串进行扫描和分解,识别出一个个合法的单词。单词种类包括:关键字,标识符,运算符,常数和界限符②进行语法分析。编写条件语句的相应文法,按照语法分析方法中的简单优先分析法为文法设计简单优先表,对词法分析得到的单词序列进行语法分析,以判别输入的语句是否属于该文法的条件语句。③语法制导翻译。设计中间代码(四元式)序列的结构及属性文法,运用语法制导翻译,在进行语法分析的同时,执行相应的语义规则描述的动作,从而实现语义处理,生成中间代码以四元式的形式输出。④错误提示。对不同的错误给出简略描述,并终止程序的继续执行。下载地址如下,有你要的东西!pile.rar

‘玖’ 编译原理编程

1)0*10*10*

2)0*(10+)*(1|0)

3)(0*10*10*)*

第一题跟第三题是差不多的

这时候可以发现,只要用一个count来做对错的识别就能解决,并不是没有用到state状态,而是该状态变为隐性了,如下

/**

*@fnintcheck_data(char*d_line,intn)

*@brief检查资列串是否符合给定的正则表达式

*@return0不符;1符合

*/

intcheck_data(char*d_line,intn){

inti,count;

for(count=0,i=0;i<n;i++){//只要算出1的个数即可

if(d_line[i]=='1')count++;

}

return(1-(count&1));//当count奇数表示失败;当count偶数成功

}

第二题的话,就会用到state来纪录状态,

而最后离开状态S4还是被隐含在执行判断的过程中

#defineS10

#defineS21

#defineS32

#defineS43

intcheck_data(char*d_line,intn){

inti,state;

state=S1;

for(i=0;i<n;i++){

switch(state){

caseS1:

if(d_line[i]=='1')state=S2;break;

caseS2:

if(d_line[i]=='1')return0;//失败了

/*d_line[i]为'0'*/state=S3;break;

caseS3:

if(d_line[i]=='1')state=S2;break;

caseS4:break;

}

}

return1;

}

基本上上述程式对照自动机就可以比较清楚了

‘拾’ 编译原理词法分析程序

(一)Block子程序分析

procere enter(k: object1); //填写符号表
begin {enter object into table}
tx := tx + 1; //下标加1,tx的初始值为零,零下标不地址不填写标志符,用于查找失败使用
with table[tx] do //填入内容,保存标志符名和类型
begin name := id; kind := k;
case k of //根据类型判断是否正确
constant: begin if num > amax then //如果是常量,判断是否大于最大值,若是则报30号错
begin error(30); num :=0 end;
val := num //否则保存数值
end;
varible: begin level := lev; adr := dx; dx := dx + 1; //如果是变量,填写变量内部表示,LEVEl是变量的层次,adr为地址
end;
proc: level := lev //如果是过程,保存过程的层次
end
end
end {enter};

//查找符号表的位置
function position(id: alfa): integer;
var i: integer;
begin {find indentifier id in table} //从后向前查找
table[0].name := id; i := tx; //找到保存类型
while table[i].name <> id do i := i-1;
position := i //返回标志符在符号表中的位置
end {position};

procere block(lev,tx: integer; fsys: symset);
var dx: integer; {data allocation index} //数据分配索引
tx0: integer; {initial table index} //初始符号表索引
cx0: integer; {initial code index} //初始代码索引
procere enter(k: object1); //填写符号表,下次分析
begin {enter object into table}
tx := tx + 1;
with table[tx] do
begin name := id; kind := k;
case k of
constant: begin if num > amax then
begin error(30); num :=0 end;
val := num
end;
varible: begin level := lev; adr := dx; dx := dx + 1;
end;
proc: level := lev
end
end
end {enter};

function position(id: alfa): integer; //查找符号表,下次分析
var i: integer;
begin {find indentifier id in table}
table[0].name := id; i := tx;
while table[i].name <> id do i := i-1;
position := i
end {position};

procere constdeclaration; //常量声明
begin if sym = ident then //如果是标志符,读入一个TOKEN
begin getsym;
if sym in [eql, becomes] then //读入的是等号或符值号继续判断
begin if sym = becomes then error(1); //如果是“=”报1号错
getsym; //读入下一个TOKEN
if sym = number then //读入的是数字,填写符号表
begin enter(constant); getsym
end
else error(2) //如果不是数字,报2号错
end else error(3) //不是等号或符值号,报3号错
end else error(4) //如果不是标志符,报4号错
end {constdeclaration};

procere vardeclaration; //变量声明
begin if sym = ident then //读入的是标志符,填写符号表
begin enter(varible); getsym
end else error(4) //不是标志符,报4号错
end {vardeclaration};

procere listcode;
var i: integer;
begin {list code generated for this block}
for i := cx0 to cx-1 do
with code[i] do
writeln(i:5, mnemonic[f]:5, 1:3, a:5)
end {listcode};

procere statement(fsys: symset);
var i, cx1, cx2: integer;
procere expression(fsys: symset); //表达式分析
var addop: symbol;
procere term(fsys: symset); //项分析
var mulop: symbol;
procere factor(fsys: symset); //因子分析
var i: integer;
begin test(facbegsys, fsys, 24); //读入的是“(”,标志符或数字
while sym in facbegsys do
begin
if sym = ident then //是标志符,查表
begin i:= position(id);
if i = 0 then error(11) else //未找到,报11号错
with table[i] do //找到,读入标志符类型
case kind of
constant: gen(lit, 0, val); //写常量命令
varible: gen(lod, lev-level, adr);//写变量命令
proc: error(21) //过程名,报21号错
end;
getsym //读入下一个TOKEN
end else
if sym = number then //读入的是数字
begin if num > amax then //如果数字大于最大数,报30号错误
begin error(30); num := 0
end;
gen(lit, 0, num); getsym //调用数字命令,读入下一个TOKEN
end else
if sym = lparen then //读入的是“(”
begin getsym; expression([rparen]+fsys); //调用表达式分析函数
if sym = rparen then getsym else error(22) //如果“(”后无“)”,报22号错
end;
test(fsys, [lparen], 23)
end
end {factor};//因子分析结束

//项分析
begin {term} factor(fsys+[times, slash]); //调用因子分析程序
while sym in [times, slash] do //取得是乘、除号循环
begin mulop:=sym;getsym;factor(fsys+[times,slash]); //记录符号,调用因子分析
if mulop=times then gen(opr,0,4) else gen(opr,0,5) //写乘除指令
end
end {term};
begin {expression}
if sym in [plus, minus] then //如果是加减号
begin addop := sym; getsym; term(fsys+[plus,minus]); //记录符号,调用项分析程序
if addop = minus then gen(opr, 0,1) //写加减指令
end else term(fsys+[plus, minus]);
while sym in [plus, minus] do //如果是加减号循环
begin addop := sym; getsym; term(fsys+[plus,minus]);
if addop=plus then gen(opr,0,2) else gen(opr,0,3)
end
end {expression};

//条件过程
procere condition(fsys: symset);
var relop: symbol;
begin
if sym = oddsym then //如果是判奇符
begin getsym; expression(fsys); gen(opr, 0, 6) //取下一个TOKEN,调用expression,填指令
end else
begin expression([eql, neq, lss, gtr, leq, geq]+fsys);
if not(sym in [eql, neq, lss, leq, gtr, geq]) then //如果不是取到逻辑判断符号,出错.20
error(20) else
begin relop := sym; getsym; expression(fsys);
case relop of
eql: gen(opr, 0, 8); // =,相等
neq: gen(opr, 0, 9); // #,不相等
lss: gen(opr, 0, 10); // <,小于
geq: gen(opr, 0, 11); // ],大于等于
gtr: gen(opr, 0, 12); // >,大于
leq: gen(opr, 0, 13); // [,小于等于
end
end
end
end {condition};

begin {statement}
if sym = ident then //如果是标识符
begin i := position(id); //查找符号表
if i = 0 then error(11) else //未找到,标识符未定义,报11号错
if table[i].kind <> varible then //如果标识符不是变量,报12号错
begin {assignment to non-varible} error(12); i := 0
end;
getsym; if sym = becomes then getsym else error(13); //如果是变量读入下一个TOKEN,不是赋值号,报13好错;是则读入一个TOKEN
expression(fsys); //调用表达是过程
if i <> 0 then //写指令
with table[i] do gen(sto, lev-level, adr)
end else
if sym = callsym then //如果是过程调用保留字,读入下一个TOKEN
begin getsym;
if sym <> ident then error(14) else //不是标识符报14号错
begin i := position(id);
if i = 0 then error(11) else //是标识符,未定义,报13号错
with table[i] do // 已定义的标识符读入类型
if kind=proc then gen(cal, lev-level, adr) //是过程名写指令
else error(15); //不是过程名,报15号错
getsym
end
end else
if sym = ifsym then //如果是IF
begin getsym; condition([thensym, dosym]+fsys); //读入一个TOKEN,调用条件判断过程
if sym = thensym then getsym else error(16); //如果是THEN,读入一个TOKEN,不是,报16号错
cx1 := cx; gen(jpc, 0, 0); //写指令
statement(fsys); code[cx1].a := cx
end else
if sym = beginsym then //如果是BEGIN
begin getsym; statement([semicolon, endsym]+fsys); //读入一个TOKEN
while sym in [semicolon]+statbegsys do
begin
if sym = semicolon then getsym else error(10); //如果读入的是分号
statement([semicolon, endsym]+fsys)
end;
if sym = endsym then getsym else error(17) //如果是END 读入一个TOKEN,不是,报17号错
end else
if sym = whilesym then //如果是WHILE
begin cx1 := cx; getsym; condition([dosym]+fsys); //调用条件过程
cx2 := cx; gen(jpc, 0, 0); //写指令
if sym = dosym then getsym else error(18); //如果是DO读入下一个TOKEN,不是报18号错
statement(fsys); gen(jmp, 0, cx1); code[cx2].a := cx
end;
test(fsys, [], 19)
end {statement};

begin {block}
dx:=3;
tx0:=tx;
table[tx].adr:=cx;
gen(jmp,0,0);
if lev > levmax then error(32);
repeat
if sym = constsym then //如果是CONST
begin getsym; //读入TOKEN
repeat constdeclaration; //常量声明
while sym = comma do
begin getsym; constdeclaration
end;
if sym = semicolon then getsym else error(5) //如果是分号读入下一个TOKEN,不是报5号错
until sym <> ident //不是标志符常量声明结束
end;
if sym = varsym then 如果是VAR
begin getsym; 读入下一个TOKEN
repeat vardeclaration; //变量声明
while sym = comma do
begin getsym; vardeclaration
end;
if sym = semicolon then getsym else error(5) //如果是分号读入下一个TOKEN,不是报5号错
until sym <> ident; //不是标志符常量声明结束
end;
while sym = procsym do //过程声明
begin getsym;
if sym = ident then
begin enter(proc); getsym
end
else error(4); //不是标志符报4号错
if sym = semicolon then getsym else error(5); //如果是分号读入下一个TOKEN,不是报5号错
block(lev+1, tx, [semicolon]+fsys);
if sym = semicolon then //如果是分号,取下一个TOKEN,不是报5号错
begin getsym;test(statbegsys+[ident,procsym],fsys,6)
end
else error(5)
end;
test(statbegsys+[ident], declbegsys, 7)
until not(sym in declbegsys); //取到的不是const var proc结束
code[table[tx0].adr].a := cx;
with table[tx0] do
begin adr := cx; {start adr of code}
end;
cx0 := 0{cx}; gen(int, 0, dx);
statement([semicolon, endsym]+fsys);
gen(opr, 0, 0); {return}
test(fsys, [], 8);
listcode;
end {block};

热点内容
密码锁锁住了怎么办 发布:2025-03-16 17:25:51 浏览:294
中国移动数据库 发布:2025-03-16 17:18:14 浏览:603
php二维数组函数 发布:2025-03-16 17:16:11 浏览:374
安卓系统在哪里换鸿蒙界面 发布:2025-03-16 17:15:38 浏览:864
重庆智慧存储柜厂家 发布:2025-03-16 17:10:30 浏览:588
企业的服务器满了如何备份 发布:2025-03-16 17:04:00 浏览:901
促销算法模型 发布:2025-03-16 16:56:55 浏览:93
线程异步java 发布:2025-03-16 16:51:52 浏览:260
软件编程有哪些 发布:2025-03-16 16:46:07 浏览:481
最近上传91 发布:2025-03-16 16:46:03 浏览:706