当前位置:首页 » 编程软件 » 编译原理词法分析实验报告

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

发布时间: 2025-02-21 00:57:50

A. 词法分析和语法分析区别

词法分析和语法分析是编译原理中的两个重要概念,它们在编译过程中扮演不同的角色。
1. 词法分析(Lexical Analysis):词法分析是编译器的第一阶段,也称为扫描(Scanning)或词法扫描(Tokenization)。它的主要任务是将源代码转化为一个个的词法单元(Token)。词法单元是具有独立含义的字符序列,比如关键字、标识符、数字常量、运算符等。词法分析器根据事先定义好的词法规则(正则表达式或有限状态自动机)对源代码进行扫描和识别,生成词法单元流作为后续语法分析的输入。
2. 语法分析(Syntax Analysis):语法分析是编译器的第二阶段,也称为解析(Parsing)。它的主要任务是根据语法规则分析词法单元流,确定语法结构,并构建对应的语法树(Parse Tree)或抽象语法树(Abstract Syntax Tree)。语法规则通常使用上下文无关文法的巴科斯-诺尔范式(BNF)。语法分析器通过递归下降、LR分析等算法,从词法单元流中识别语法结构,并进行相应的语法规约和移进操作,最终得到语法树或者抽象语法树。
总结而言,词法分析关注于单词的识别和分类,将源代码切分为有意义的词法单元;而语法分析则关注于将词法单元通过语法规则组织起来,构建出语法结构。两者相互配合,是编译过程中的重要组成部分,并且是后续语义分析和代码生成的基础。

B. 编译原理词法分析实验中, 文件写入顺序的问题(fputs)

1)fopen在代码中出现2次,没有必要

2)你的程序不对 你搞混和S这个字符和TOKEN。

你的第一个WHILE读入的是字符S,而TOKEN是由若干字符S构成的。而你的SWITCH(S)里面按理应该是组成TOKEN的规则,而你直接就输出了。这样如果你要结果,我给你改了下,你看下:

int main()
{
char token[20] = {''};
char s;
char strings[10] = "(34,_)";
struct _iobuf* fp_cifa;
int i = 0, j;
strings[6] = ' '
strings[7] = ''
//fp_cifa = fopen(“D:\cifa.txt "a+");

while((size_t)i != strlen(file))
{
for(j = 0; j < 20; j++)
{
token[j] = ''
}
s = file[i++];
while(s == ' ' || s == ' ')
{
s = file[i++];
}
switch(s)
{
caseƇ':
token[0]=s;
token[1]=''
digitprint(token, value_num, num_list);
break;
case'=':
token[0]=s;
token[1]=''
digitprint(token, value_num, num_list);
//fputs(strings, fp_cifa);
break;
default:
cout<<"error"<<endl;
}
}
//fclose(fp_cifa);
return 0;
}

  • void digitprint(char* a, int& value_num_, char num_list[100][20])//a是需要评定的字符串//num在符号表中的位置,需要转化为字符串然后输入到文件中
    {
    FILE* fp_cifa;
    char c[20] = "(34,01)";
    fp_cifa = fopen("D:\cifa.txt ", "a+");
    //fputs(c, fp_cifa);
    fputs(a,fp_cifa);//这里要显示 a 而不是c 你可以把a 拼到 c然后,再显示c
    fclose(fp_cifa);
    }

C. 急(高悬赏 帮个忙) 求编译原理课程设计---c语言实现c-的语法分析,在线等

新建一个文本文档在你工程目录下,名字起为"输入.txt",里面的内容可以为
begin a:=1+7*(6+3);b:=1end#

输出是在"输出.txt"中查看,以下为输出情况:

词法分析结果如下:
(1, begin)
(10, a)
(18, :=)
(11, 1)
(13, +)
(11, 7)
(15, *)
(27, ()
(11, 6)
(13, +)
(11, 3)
(28, ))
(26, ;)
(10, b)
(18, :=)
(11, 1)
(6, end)
(0, #)
语法分析结果如下:(以四元式形式输出)
( +, 6, 3, t1)

( *, 7, t1, t2)

( +, 1, t2, t3)

( =, t3, __, a)

( =, 1, __, b)

//提供一个编译原理的语义分析程序 你可以直接复制 用TC进行调试
#include "stdio.h"
#include "string.h"
#include <malloc.h>
#include <conio.h>
#include "stdlib.h"

char prog[100],token[8],ch;
char *rwtab[6]={"begin","if","then","while","do","end"};
int syn,p,m,n,sum,q;
int kk;
//四元式表的结构如下:
struct
{
char result1[8];
char ag11[8];
char op1[8];
char ag21[8];
}quad[20];

char *factor();
char *expression();
int yucu();
char *term();
int statement();
int lrparser();
char *newtemp();
void scaner();
void emit(char *result,char *ag1,char *op,char *ag2);

void main()
{
FILE *fp1,*fp2;

if((fp1=fopen("输入.txt","rt"))==NULL)
{
printf("Cannot open 输入.txt\n");
getch();
exit(1);
}
if((fp2=fopen("输出.txt","wt+"))==NULL)
{
printf("Cannot create 输出.txt FILE.strike any key exit");
getch();
exit(1);
}

int j;
q=p=kk=0;
p=0;
//printf("Please Input a String(end with '#'):\n");
while(ch!='#')
{
ch = fgetc(fp1);
if(ch == EOF)
{
printf("文件为空,请检查后再尝试!");
return ;
}

prog[p++]=ch;
}
if(prog[p]=='#')
{
printf("输入的待分析的串不是以'#'结尾,请修改之后再尝试!\n");
return;
}
p=0;
char buffer1[200] = {0};
sprintf(buffer1,"词法分析结果如下:\n");
fputs(buffer1,fp2);
//printf("词法分析结果如下:\n");
do
{
scaner();
switch(syn)
{
case 11:
//printf("(%d,%d)\n",syn,sum);
sprintf(buffer1,"(%d, %d) \n",syn,sum);
fputs(buffer1,fp2);
break;
default:
//printf("(%d,%s)\n",syn,token);
sprintf(buffer1,"(%d, %s)\n",syn,token);
fputs(buffer1,fp2);
break;
}
}while(syn!=0);
printf("\n");

p=0;
char buffer[200]={0};
sprintf(buffer,"语法分析结果如下:(以四元式形式输出)\n");
fputs(buffer,fp2);
//printf("语法分析结果如下:(以四元式形式输出)\n");
scaner();//扫描函数
lrparser();
if(q>19)
printf(" to long sentense!\n");
else
{

for (j=0;j<q;j++)
{
//printf("( %s, %s, %s, %s) \n\n",quad[j].op1,quad[j].ag11,quad[j].ag21,quad[j].result1);
sprintf(buffer,"( %s, %s, %s, %s) \n\n",quad[j].op1,quad[j].ag11,quad[j].ag21,quad[j].result1);
fputs(buffer,fp2);
}
}
printf("已把相应的词法和语法的结果保存到相应的文件中,请查阅!\n");
fclose(fp1);
fclose(fp2);
}
int lrparser()
{
int schain=0;
kk=0;
if (syn==1) //得到begin
{
scaner();//扫描下个字符
schain=yucu();
if(syn==6)//得到end
{
scaner();//扫描下个字符
if((syn==0)&&(kk==0)) //得到#
printf("Success!\n");
}
else
{
if(kk!=1)
printf("short of 'end' !\n");
kk=1;
getch();
exit(0);
}
}
else
{
printf("short of 'begin' !\n");
kk=1;
getch();
exit(0);
}
return (schain);
}
int yucu()
{
int schain=0;
schain=statement();
while(syn==26)
{
scaner();
schain=statement();
}
return (schain);
}
int statement()
{
char tt[8],eplace[8];
int schain=0;
if (syn==10)
{
strcpy(tt,token); //tt中保存的是第一个字符
scaner();
if(syn==18) //检测到=号
{
scaner();
strcpy(eplace,expression());
emit(tt,eplace,"=","__");
schain=0;
}
else
{
printf("short of sign ':=' !\n");
kk=1;
getch();
exit(0);
}
return (schain);
}
}
char *expression()
{
char *tp,*ep2,*eplace,*tt;
tp=(char *)malloc(12);
ep2=(char *)malloc(12);
eplace=(char *)malloc(12);
tt=(char *)malloc(12);

strcpy(eplace,term());

while((syn==13)||(syn==14))
{
if (syn==13)
strcpy(tt,"+");
else
strcpy(tt,"-");

scaner();
strcpy(ep2,term());
strcpy(tp,newtemp());
emit(tp,eplace,tt,ep2);
strcpy(eplace,tp);
}
return (eplace);
}
char *term()
{
char *tp,*ep2,*eplace,*tt;
tp=(char *)malloc(12);
ep2=(char *)malloc(12);
eplace=(char *)malloc(12);
tt=(char *)malloc(12);

strcpy(eplace,factor());

while((syn==15)||(syn==16))
{
if (syn==15)
strcpy(tt,"*");
else
strcpy(tt,"/");
scaner();
strcpy(ep2,factor());
strcpy(tp,newtemp());
emit(tp,eplace,tt,ep2);
strcpy(eplace,tp);
}
return (eplace);
}
char *factor()
{
char *fplace;
fplace=(char *)malloc(12);
strcpy(fplace,"");

if(syn==10) //得到字符
{
strcpy(fplace,token);
scaner();
}
else if(syn==11) //得到数字
{
itoa(sum,fplace,10);
scaner();
}
else if(syn==27) //得到)
{
scaner();
fplace=expression();
if(syn==28) //得到(
scaner();
else
{
printf("error on ')' !\n");
kk=1;
getch();
exit(0);
}
}
else
{
printf("error on '(' !\n");
kk=1;
getch();
exit(0);
}
return (fplace);
}
//该函数回送一个新的临时变量名,临时变量名产生的顺序为T1,T2...
char *newtemp()
{
char *p;
char m[8];
p=(char *)malloc(8);

kk++;
itoa(kk,m,10);
strcpy(p+1,m);
p[0]='t';
return(p); //设置中间变量名放在一个字符数组中,字符数组的第一个字符为t第二个字符为m表示的数值
}
void scaner()
{
sum=0;
///for(m=0;m<8;m++)
//token[m++]=NULL;
memset(token,0,8);
m=0;
ch=prog[p++];
while(ch==' ')
ch=prog[p++];
if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))
{
while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))
{
token[m++]=ch;
ch=prog[p++];
}
p--;
syn=10;
token[m++]='\0';
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
else if((ch>='0')&&(ch<='9'))
{
while((ch>='0')&&(ch<='9'))
{
sum=sum*10+ch-'0';
ch=prog[p++];
}
p--;
syn=11;
}
else switch(ch)
{
case '<':m=0;
ch=prog[p++];
if(ch=='>')
{
syn=21;
}
else if(ch=='=')
{
syn=22;
}
else
{
syn=20;
p--;
}
break;
case '>':m=0;
ch=prog[p++];
if(ch=='=')
{
syn=24;
}
else
{
syn=23;
p--;
}
break;
case ':':m=0;
token[m++] = ch;
ch=prog[p++];
if(ch=='=')
{
syn=18;
token[m++] = ch;
}
else
{
syn=17;
p--;
}
break;

case '+': syn=13;token[0] = ch; break;
case '-': syn=14;token[0] = ch; break;
case '*': syn=15;token[0] = ch;break;
case '/': syn=16;token[0] = ch;break;
case '(': syn=27;token[0] = ch;break;
case ')': syn=28;token[0] = ch;break;
case '=': syn=25;token[0] = ch;break;
case ';': syn=26;token[0] = ch;break;
case '#': syn=0;token[0] = ch;break;
default: syn=-1;break;
}
}
//该函数是生成一个三地址语句送到四元式表中
void emit(char *result,char *ag1,char *op,char *ag2)
{
strcpy(quad[q].result1,result);
strcpy(quad[q].ag11,ag1);
strcpy(quad[q].op1,op);
strcpy(quad[q].ag21,ag2);
q++; //统计有多少个四元式
}

D. 编译原理中词法分析和语法分析的任务分别是什么

词法分析的主要任务是将源代码转换为一系列有意义的词汇单位,这个过程可以分解字符序列形成单词组合,我们称之为词法单元或记号。在词法分析中,分析器识别关键字、标识符、常量和运算符等元素,形成一个词法单元序列。

语法分析的任务是根据预设的语法规则,分析词法单元序列的结构。这一步骤旨在判断序列是否遵循既定的语法规则。语法分析器通过构建语法树或语法分析树,展示源代码的结构。在此过程中,语法分析器还会检测语法错误,并生成相应的错误信息。

词法分析与语法分析是编译原理中的两个关键环节,它们共同协作完成源代码的分析和转换。词法分析将源代码转换为词法单元序列,为后续的语法分析提供数据输入。而语法分析则依据语法规则对词法单元序列进行深入分析,判断其是否符合语法规则。经过这两个步骤,编译器能够对源代码进行更深层次的语义分析、优化,并最终生成目标代码。

E. 编译原理中的词法分析需要进行错误报告吗

词法分析中需要进行处理和报告的错误为:源程序中出现的不符合文法的字符,标识符等等。
这些一定要在词法分析中完成,搁到后面会很麻烦。
其余错误,如类型不匹配,返回值出错,语句语法错误等,在语法分析过程中进行。

F. 编译原理简单吗

编译原理主要是讲了编译器的实现。
那什么是编译器呢?
编译器就是将 源程序→编译器 →目标机器代码的程序
本文将用一段最简单的代码进行说明

1 + 2 + 3

第一步. 词法分析
当代码从文件中被读入到编辑器时,将会进行词法分析
示例中的代码最终会转换为(下面为伪代码)

1 ADD 2 ADD 3

第二步. 语法分析
这一步编译器将会把词法分析的结果转换成AST(abstract syntax tree, 抽象语法树)
所有的操作数将会作为子节点,所有的操作符将会作为父节点。(不知道的同学可以看一下树的生成)

1 + 2 + 3 对应的树
3. 生成目标代码
对上面的树进行后序遍历,将会得到下面的伪代码

((1 2 +) 3 +)

生成的汇编伪代码为

START:

MOV VALUE, 0//初始化结果为0

ADD VALUE, 1

ADD VALUE, 2//(1 2 +)的汇编伪代码

ADD VALUE, 3

RET VALUE

END

最终汇编代码会被编译成机器代码,在计算机上执行。
下面为一般情况下的编译流程
1. 词法分析(生成代码对应的token序列,使用正则表达式)
2. 语法分析(生成AST)
3. 语义分析(对代码的语法进行检查)
4. 代码生成(生成可执行的代码)

热点内容
邻区脚本 发布:2025-02-22 07:01:04 浏览:961
安卓手机怎么校正soc 发布:2025-02-22 06:36:58 浏览:508
商城总控源码 发布:2025-02-22 06:36:14 浏览:505
ipad怎么玩安卓区游戏 发布:2025-02-22 06:35:29 浏览:347
程序注释和编译功能 发布:2025-02-22 06:34:08 浏览:813
云电脑的密码是什么意思 发布:2025-02-22 06:27:43 浏览:241
安卓系统如何转为ios系统 发布:2025-02-22 05:57:54 浏览:238
安卓手机指纹解锁如何变面容 发布:2025-02-22 05:31:57 浏览:535
压缩燃烧 发布:2025-02-22 05:28:49 浏览:760
数据库的连接查询 发布:2025-02-22 05:24:31 浏览:921