源码在最下面

内容:设计并实现一个词法分析器,实现对自己输入的类C语言源程序中的所有单词进行分类,指出其所属类型,实现简单的词法分析操作。

一.运行环境: win10         Microsoft Visual Studio 2010

二.原理:

大多数程序语言的单词符号可以用正规文法来描述,由正规文法可以构造出相应的状态转换图,由此状态转换图就可以方便地识别单词符号,因此由状态转换图就不难构造出相应单词词法分析程序。

依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结束。

三.词法分析程序的输出:

PL/0语言的单词符号分类:

保留字、标识符、无符号整数、运算符、界符

构造状态转换图

对于上述基本符号用以下正规文法规则进行描述

 ::= |

 ::= ··字母|数字|字母

 ::=  +|-|*|/|=

 ::=  ,|;|{|}|(|)

从中可以看出,以上每一条规则所构成文法是一个左线性文法,由此可以画出各自的状态转换图。

java词法分析一行代码 java词法分析程序_词法分析

因为词法分析程序是一个子程序,用来识别和分析各类单词符号,并且在识别出一个单词之后,将返回调用程序。故可以将各自状态转换图合并成一张状态转换图。

词法分析程序的构造

有了状态转换图很容易写出词法分析程序,我们可以把词法分析程序作为一个子程序来构造,当语法分析程序需要一个单词符号时就调用这个子程序。每一次调用,词法分析程序就从输入串中识别出一个单词符号。

定义单词种类与词法规则

①标识符:首字符为字母或下划线,其后由字母、数字或下划线组成 注:标识符长度不能超过20个字符。

②无符号整数:由十进制数字组成的一个序列。首位数字不能为0; 注:无符号整数不带正负号。

③ 保留字:procedure、call、begin、end、and、or、if、else、int、float、const、for、new、public、while、long、static、do、read、char、return、using、void、break、include、switch、continue、try、private、var、odd、then、write 注:保留字不区分大小写。

④ 运算符:+、-、 *、 /、 =、 、   <=、  >=、  !=、<>、  ==、#

⑤ 界符:      (   )    , ;{  }

四.将词法分析工作分离的考虑:

1.使整个编译程序的结构更简洁、清晰和条理化。

2.编译程序的效率会改进。

3.增强编译程序的可移植性。

词法分析程序的主要功能是从字符流的源程序中识别单词,它要从左至右逐个字符地扫描源程序,因此它还可完成其他一些任务。比如,滤掉源程序中的注释和空白(由空格、制表符或回车换行字符引起的空白);又如,为了使编译程序能将发现的错误信息与源程序的出错位置联系起来,词法分析程序负责记录新读入的字符行的行号,以便行号与出错信息相关联;再如,在支持宏处理功能的源语言中,可以由词法分析程序完成其预处理等。

例如下面为一段C语言源程序:

#include 
void main()
{
int sum,n;
sum=0;
n=1
while(n<=100)
{
sum=sum+n;
n++;
}
printf("sum=",sum);
}

输入上述源程序后以“@”结束。运行输出:

java词法分析一行代码 java词法分析程序_词法分析_02

五.说明:

1.程序运行后可以自己输入C语言源程序,以@符号结束

2. 程序运行过程中,会依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结束。

3.cout是iostream类的一个对象,它重载了<

六.程序源码(用Microsoft Visual Studio 2010测试,真实有效,能正常运行)

#include 
#include 
#include 
#include 
#include 
using namespace std;
//看是否为数字
bool NUMBER(char A)
{
if (A >= '0'&&A <= '9')
return true;
return false;
}
//看是否为字母
bool LETTER(char A)
{
if ((A >= 'A'&&A <= 'Z') || A >= 'a'&&A <= 'z')
return true;
return false;
}
bool RESERVEDWORD(char *a)
{
if (strcmp(a, "if") == 0||strcmp(a, "main") == 0||strcmp(a, "else") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "int") == 0||strcmp(a, "float") == 0||strcmp(a, "const") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "for") == 0||strcmp(a, "new") == 0||strcmp(a, "public") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "while") == 0||strcmp(a, "long") == 0||strcmp(a, "static") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "do") == 0||strcmp(a, "read") == 0||strcmp(a, "char") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "return") == 0||strcmp(a, "using") == 0||strcmp(a, "void") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "break") == 0||strcmp(a, "include") == 0||strcmp(a, "switch") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "continue") == 0||strcmp(a, "try") == 0||strcmp(a, "private") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "procedure") == 0||strcmp(a, "call") == 0||strcmp(a, "begin") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "end") == 0||strcmp(a, "and") == 0||strcmp(a, "or") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "var") == 0||strcmp(a, "odd") == 0||strcmp(a, "then") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
if (strcmp(a, "write") == 0)
{
cout << "保留字, '" << a << "'" << endl;
return true;
}
return false;
}
int main()
{
//保留字;标识符;无符号整数;运算符;界符。
char a;
FILE *f;
char CHAR;
char TOKEN\[120\];
f = fopen("write.txt", "w");   //创建文本文件code,保存输入的程序代码
if (f == NULL)
{
cout << "con't create file" << endl;
exit(0);
}
cout << "\\n请输入源程序  以“@”结束" << endl;
while ((a = getchar()) != '@')   //getchar() 是从控制台接收字符,注意只会接收一个字符
fputc(a, f);
fclose(f);
cout << "over\\n" << endl;
f = fopen("write.txt", "r");
while ((CHAR = fgetc(f)) != EOF)
{
while (CHAR != ' ')
{
if (LETTER(CHAR)) //如果以字母开头
{
int k = 0;
do {
TOKEN\[k\] = CHAR;
k++;
}
while ((CHAR = fgetc(f)) != EOF && CHAR != ' '&&LETTER(CHAR));
if (NUMBER(CHAR))//如果以数字开头
{
do {
TOKEN\[k\] = CHAR;
k++;
}
while ((CHAR = fgetc(f)) != EOF && CHAR != ' '&&NUMBER(CHAR));
}
TOKEN\[k\] = '\\0';
if (!(RESERVEDWORD(TOKEN)))        //判断标识符是否为保留字
cout << "标识符, '" << TOKEN << "'" << endl;
}
if (NUMBER(CHAR))              //整数情况
{
int i = 0;
do {
TOKEN\[i\] = CHAR;
i++;
}
while ((CHAR = fgetc(f)) != EOF && CHAR != ' '&&NUMBER(CHAR));
TOKEN\[i\] = '\\0';
if (!RESERVEDWORD(TOKEN))
cout << "无符号整数, '" << TOKEN << "'" << endl;
}
if (CHAR == '+' || CHAR == '-' || CHAR == '*' || CHAR == '/' || CHAR == '>' || CHAR == '=' || CHAR == '<=' || CHAR == '!='|| CHAR == '==')  //运算符情况
{
cout << "运算符, '" << CHAR << "'" << endl;
}
if (CHAR == ',' || CHAR == ';' || CHAR == '(' || CHAR == ')' || CHAR == '{' || CHAR == '}')   //界符情况
{
printf("界符: %c\\n",CHAR);
}
break;
}
}
fclose(f);
printf("按任意键退出...");
getch();
return 0;
}