
词法分析器编制一个读单词的程序,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符和分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示)。
扩展资料
词法分析器的作用:
1、与符号表进行交互,存储和读取符号表中的标识符的信息。
2、读入源程序的输入字符,将他们组成词素,生成并输出一个词法单元序列,每个词法单元序列对应一个于一个词素。
3、过滤掉程序中的注释和空白。
4、将编译器生成的错误消息与源程序的位置联系起。
参考资料来源:
百度百科-词法分析器
C语言词法分析器#include<iostream>
#include<stdio.h>
#include<string>
using namespace std
FILE *f //定义一个文件变量
static int line = 1 //表示光标所在的行数
struct ID{ char *nameint count}id[100]//用于存放ID号码
static int I = 0//用于记录ID存放的数量
int Number[100]//用于存放数字
static int P = 0//用于记录存放数字的个数
int error[100] = {0} //用于记录错误所在的行数
static int K = 0//记录错误次数
void Error() //记录错误
void loginID(char *) //注册ID号
void loginNumber(int &)//记录数字
void noteLine(char &)//记录光标所在的行数
void print() //输出分析结果
int same(char *chr) //判断单词是否已经存在
void Error()
{ error[K++] = line}
void loginID(char *chr) //注册ID号
{
int k = 0
int h = 0
for(int i = 0i <Ii++)
{
if(!strcmp(chr,id.name)) //如果单词已经存在
{
id.count++
k = 1
}
}
if(k == 0) //该单词不存在
{
h = I + 1
//I = h
id[h].count++
id[h].name = chr
//strcpy(id[h].name ,chr)
}
}
void loginNumber(int &nu)
{ Number[P++] = nu}
void noteLine(char &ch)
{
if ( ch == ' ' )
++line
}
void print()//输出部分
{
//cout <<"关键字以及变量:" <<endl
//for(int i = 0i <100i++)
//cout <<i <<" " <<id.name <<" " <<id.count <<endl
cout <<"数字:" <<endl
for(int i = 1i <= Pi++)
cout <<i <<": " <<Number[i-1] <<endl
if(error[0] != 0)
{
cout <<"出现的错误!" <<endl
for(int i = 1i <= Ki++)
cout <<"第" <<i <<"个错误: " <<"第" <<error[i-1] <<"行" <<endl
}
else cout <<"没有错误!" <<endl
}
//文件处理部分
void noblank( char &ch) //跳过空格,回车
{
noteLine(ch)
while(ch == ' ' || ch == ' ')
ch = fgetc(f)
}
void identifier(char name[],char &ch)//字母变量
{
int i
for(i = 0i <20i++)
name = ''
i = 0
while (('0'<= ch &&ch <= '9')||('a'<= ch&&ch <= 'z')||('A'<= ch&&ch <='Z'))
{
name = ch
i++
ch = fgetc(f)
}
loginID(name)
//for(int j = 0j <ij++)
//{cout <<name[j]}
// cout <<' '
}
int number(char &ch)//数字
{
int num=0
while('0'<= ch &&ch <= '9')
{
num = num* 10 + (ch-'0')
ch = fgetc(f)
}
if( ('a'<= ch&&ch <= 'z')||('A'<= ch&&ch <='Z'))
{
Error()
}
else if( ch == '.')
{}
loginNumber(num) //记录数字
return num
}
void test(char &ch)//符号
{
char str[2]={'0/'}
if(ch == '*')
{ str[0] = chch = fgetc(f)}
if(ch == '.')
{ str[0] = chch = fgetc(f)}
if(ch == ',')
{ str[0] = chch = fgetc(f)}
if(ch == '"')
{ str[0] = chch = fgetc(f)}
if(ch == '/')
{ str[0] = chch = fgetc(f)}
if(ch == '%')
{ str[0] = chch = fgetc(f)}
if(ch == '^')
{ str[0] = chch = fgetc(f)}
if(ch == '-')
{ str[0] = chch = fgetc(f)}
if(ch == '{')
{ str[0] = chch = fgetc(f)}
if(ch == '}')
{ str[0] = chch = fgetc(f)}
if(ch == '[')
{ str[0] = chch = fgetc(f)}
if(ch == ']')
{ str[0] = chch = fgetc(f)}
if(ch == '')
{str[0] = chch = fgetc(f)}
if(ch == ':')
{ str[0] = chch = fgetc(f)}
if(ch == '?')
{ str[0] = chch = fgetc(f)}
if(ch == '(')
{ str[0] = chch = fgetc(f)}
if(ch == ')')
{str[0] = chch = fgetc(f)}
if(ch =='+')
{
str[0] = ch
if((ch = fgetc(f)) == '+' )
{
str[1] = ch
ch = fgetc(f)
//cout <<str[0] <<str[1] <<endl
}
//cout <<str[0]<<endl
}
if(ch == '-')
{
str[0] = ch
if((ch = fgetc(f)) == '-' )
{
str[1] = ch
ch = fgetc(f)
//cout <<str[0] <<str[1] <<endl
}
//cout <<str[0]<<endl
}
if(ch == '&')
{
str[0] = ch
if((ch = fgetc(f)) == '&' )
{
str[1] = ch
ch = fgetc(f)
//cout <<str[0] <<str[1] <<endl
}
//cout <<str[0]<<endl
}
if(ch == '|')
{
str[0] = ch
if((ch = fgetc(f)) == '|' )
{
str[1] = ch
ch = fgetc(f)
//cout <<str[0] <<str[1] <<endl
}
//cout <<str[0]<<endl
}
if(ch == '!')
{
str[0] = ch
if((ch = fgetc(f)) == '=' )
{
str[1] = ch
ch = fgetc(f)
//cout <<str[0] <<str[1] <<endl
}
//cout <<str[0]<<endl
}
if(ch == '=')
{
str[0] = ch
if((ch = fgetc(f)) == '=' )
{
str[1] = ch
ch = fgetc(f)
//cout <<str[0] <<str[1] <<endl
}
}
if(ch == '>')
{
str[0] = ch
if((ch = fgetc(f)) == '=' )
{
str[1] = ch
ch = fgetc(f)
//cout <<str[0] <<str[1] <<endl
}
else
if(ch == '>' )
{
str[1] = ch
ch = fgetc(f)
//cout <<str[0] <<str[1] <<endl
}
}
if(ch == '<')
{
str[0] = ch
if((ch = fgetc(f)) == '=' )
{
str[1] = ch
ch = fgetc(f)
}
else
if(ch == '<' )
{
str[1] = ch
ch = fgetc(f)
}
}
}
int main()
{
char ch
char name[30]
for(int i = 0i <30i++)
name = '/0'
f = fopen("c.txt","r") //打开指定输入文件
if (f == NULL)
cout<<"文件不存在!"<<endl
ch = fgetc(f)
while(!feof(f))
{
noblank( ch )//跳过回车,空格
if( ( ch >= 'a' &&ch <= 'z' )||( ch >= 'A' &&ch <= 'Z' ))
{ identifier(name,ch)} //处理字母
else if( ch >= '0'&&ch <= '9')
{ number(ch)} //处理数字
else
{ test(ch)} //处理符号
}
print() //打印词法分析结果
fclose(f) //关闭文件
system("pause")
return 0
}
分成词法分析,语法分析(LL算法,递归下降算法,LR算法),语义分析,运行时环境,中间代码,代码生成,代码优化这些部分。其实现在很多编译原理的教材都是按照85,86出版的那本龙书来安排教学内容的,所以那本龙书的内容格式几乎成了现在编译原理教材的定式,包括国内的教材也是如此。一般来说,大学里面的本科教学是不可能把上面的所有部分都认真讲完的,而是比较偏重于前面几个部分。像代码优化那部分东西,就像个无底洞一样,如果要认真讲,就是单独开一个学期的课也不可能讲得清楚。所以,一般对于本科生,对词法分析和语法分析掌握要求就相对要高一点了。
词法分析相对来说比较简单。可能是词法分析程序本身实现起来很简单吧,很多没有学过编译原理的人也同样可以写出各种各样的词法分析程序。不过编译原理在讲解词法分析的时候,重点把正则表达式和自动机原理加了进来,然后以一种十分标准的方式来讲解词法分析程序的产生。这样的做法道理很明显,就是要让词法分析从程序上升到理论的地步。
语法分析部分就比较麻烦一点了。现在一般有两种语法分析算法,LL自顶向下算法和LR自底向上算法。LL算法还好说,到了LR算法的时候,困难就来了。很多自学编译原理的都是遇到LR算法的理解成问题后就放弃了自学。其实这些东西都是只要大家理解就可以了,又不是像词法分析那样非得自己写出来才算真正的会。像LR算法的语法分析器,一般都是用工具Yacc来生成,实践中完全没有比较自己来实现。对于LL算法中特殊的递归下降算法,因为其实践十分简单,那么就应该要求每个学生都能自己写。当然,现在也有不少好的LL算法的语法分析器,不过要是换在非C平台,比如Java,Delphi,你不能运用YACC工具了,那么你就只有自己来写语法分析器。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)