一、实验目的
了解词法分析程序的基本构造原理,掌握简单词法分析程序的构造方法。
二、实验内容
根据PASCAL语言的说明语句结构,设计一个对PASCAL语言常量说明语句进行词法分析的简单程序,并用C、C++或Java语言编程实现。要求程序能够对从键盘输入或从文件读入的形如 “const count=10,sum=81.5,char1=’f’,string1=”hj”, max=169;”的字符串进行分析处理,判断该输入串是否是一个有效的PASCAL语言常量说明语句。如果不是,则报错;如果是,则识别出该输入串中所说明的各种常量名、常量类型及常量值,并统计各种类型的常量个数。
三、实验要求
1、输入的常量说明串,要求最后以分号作结束标志;
2、根据输入串或读入的文本文件中第一个单词是否为“const”判断输入串或文本文件是否为常量说明内容;
3、识别输入串或打开的文本文件中的常量名。常量名必须是标识符,定义为字母开头,后跟若干个字母,数字或下划线;
4、根据各常量名紧跟等号“=”后面的内容判断常量的类型。其中:字符型常量定义为放在单引号内的一个字符;字符串常量定义为放在双引号内所有内容;整型常量定义为带或不带+、- 号,不以0开头的若干数字的组合;实型常量定义为带或不带+、- 号,不以0开头的若干数字加上小数点再后跟若干数字的组合;
5、统计并输出串或文件中包含的各种类型的常量个数;
6、以二元组(类型,值)的形式输出各常量的类型和值;
7、根据常量说明串置于高级语言源程序中时可能出现的错误情况,模仿高级语言编译器对不同错误情况做出相应处理。
四、运行结果示例
1、输入如下正确的常量说明串:
const count=10,sum=81.5,char1=‘f’,max=169,str1=“h*54 2..4S!AAsj”, char2=‘@’,str2=“aa!+h”;
输出:
count(integer,10)
sum(float,81.5)
char1(char, ‘f’)
max(integer,169)
str1(string,“h*54 2..4S!AAsj”)
char2(char, ‘@’)
str2(string,“aa!+h”)
int_num=2; char_num=2; string_num=2; float_num=1.
2、输入类似如下的保留字const错误的常量说明串:
Aconstt count=10,sum=81.5,char1=‘f’;
输出类似下面的错误提示信息:
It is not a constant declaration statement!
Please input a string again!
3、输入类似如下含常量名或常量值错误的常量说明串:
const count=10,12sum=81.5,char1=‘ff’,max=0016;
输出类似下面的错误提示信息:
count(integer,10)
12sum(Wrong! It is not a identifier!)
char1(Wrong! There are more than one char in ‘’.)
max(Wrong! The integer can’t be started with ‘0’.)
int_num=1; char_num=0; string_num=0; float_num=0.
4、其他类型的错误处理情况(略)。
五、实验提示
本实验重点有三个:一是作为常量名的标识符的识别;二是如何根据“=”后出现的内容来判断常量类型;三是对各种错误的处理。难点是对整型和实型常量的判断必须综合考虑多种可能情况。
建议:1、用指针或数组与指针相结合来处理输入的常量说明串;2、对整型和实型常量处理时,重点考虑常数中‘0’的位置。
六、分析与讨论
1、若考虑用E或e的科学计数法来表示整数和实数,应该如何实现?
2、若考虑布尔型常量,且规定其值只能为true或false,应该如何实现?
3、如何对手工构造的词法分析程序做进一步的优化,以提高代码质量和运行效率?
个人实验代码(我的判断是依据\"\"来的,如果里面有什么其他符号,请加转义符进行符号插入):
import java.util.*;
public class Main {
static int int_num=0;
static int char_num=0;
static int string_num=0;
static int float_num=0;
static String name;//变量名
static String string;//值
static int namefg = 0;//变量名检验
static int stringfg = 0;//变量值检验
static String type;//类型
static String value;//值
static int kong = 0;
//static int flag = 0;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
boolean result=s.startsWith(\"const \");//检查开头
if(!result){
System.out.println(\"开头校检失败!\");
}else {
CutString(s);//分隔字符串
in.close();
}
}
public static void CutString(String s) {//分割校检
// TODO Auto-generated method stub
char []str = s.toCharArray();//字符串转成字符串数组
int i = 6;
while(i<str.length-1){
i = finds(str,i);
if(kong==0){
System.out.println(\"空格错误!!!\");
continue;
}
i = Check(str,i);
if(namefg==1){
if(stringfg==1){//变量名和变量值均合法
System.out.println(name+\"(\"+type+\",\"+value+\")\");
}else{
//flag = 1;
System.out.println(name+\"(\"+type+\")\"+\"变量值出现不合法情况!值为:\"+string);
}
}else{
System.out.println(name+\"变量名不合法!\");
}
}
/*if(flag == 0){
System.out.println(\"OK\");
System.out.println(\"int_num=\"+int_num+\" float_num=\"+float_num+\" char_num=\"+char_num+\" string_num=\"+string_num);
}else{
System.out.println(\"ERROR4\");
}*/
System.out.println();
System.out.println(\"int_num=\"+int_num+\" float_num=\"+float_num+\" char_num=\"+char_num+\" string_num=\"+string_num);
}
public static int finds(char[] a, int i){
//采集变量名
name = \"\";
for(;i<a.length;i++){
if(a[i]!=\' \'&&a[i]!=\',\'){
kong = 1;
}
if(a[i]==\'=\'){
break;
}
name+=a[i];
}
if(kong==0){
System.out.println(\"ERRORRRRRRRRRR\");//(空格错误,yi解决)
return i;
}
name = name.trim();
if(name.length()!=0){
kong = 1;
}
boolean result1 = name.matches(\"[a-zA-Z_][a-zA-Z0-9_]*\");
if(result1){
namefg = 1;//变量名合法
}else {
namefg = 0;
}
//System.out.println(result1);
i++;
return i;
}
public static int Check(char[] a,int i){
//采集变量值
string=\"\";
for(;i<a.length;i++){
if(a[i]==\'\"\'){//如果发现了左\",那么这是一个字符串,从他后面找到一个\"号,完成\"\"配对
int s = 0;
int e = 0;
for(int j = i+1;j<a.length;j++){//找=和;号
//if(a[j]==\'=\'||a[j]==\';\')
if(a[j]==\'\"\'&&a[j-1]!=\'\\\\\'){
s = j-1;
break;
}
}
string=\"\";
for(;i<=s;i++){//配对引号内容装进
if(a[i]==\'\\\\\')
{
if(a[i+1]==\'\"\')
{
i++;
}
}
string+=a[i];
}
}
if(a[i-1]!=\'\\\\\'&&a[i]==\',\'||a[i]==\';\')break;
string+=a[i];//如果没有遇到\"则正常保存
}
/*while(a[i]!=\',\'&&a[i]!=\';\'){
string+=a[i];
i++;
}*/
string = string.trim();//去除首位多余空格
value = string;
if(namefg == 1){//变量名合法,开始变量值的合法性判断
if(string.startsWith(\"\\\"\")&&string.endsWith(\"\\\"\")){
//字符串
type = \"String\";
stringfg = 1;
string_num++;
}else if(string.startsWith(\"\'\")&&string.endsWith(\"\'\")){
//字符
type = \"char\";
if(string.length()==3){
stringfg = 1;
char_num++;
}else {
stringfg = 0;
}
}else if(string.matches(\"[+|-]?[0-9]*\")){
//整数
stringfg = 1;//变量值合法
type = \"integer\";
int_num++;
}else if(string.matches(\"[+|-]?[0-9]*[.][0-9]*\")){
//浮点
stringfg = 1;
type = \"float\";
float_num++;
}else {
stringfg = 0;
}
}
i++;
return i;
}
}
/*const count=10,sum=81.5,char1=\'f\',max=169,str1=\"h*54 2..4S!AAsj\", char2=\'@\',str2=\"aa!+h\";
count(integer,10)
sum(float,81.5)
char1(char,\'f\')
max(integer,169)
str1(String,\"h*54 2..4S!AAsj\")
char2(char,\'@\')
str2(String,\"aa!+h\")
int_num=2 float_num=1 char_num=2 string_num=2
Aconstt count=10,sum=81.5,char1=\'f\';
开头校检失败!
const count=10,12sum=81.5,char1=\'ff\',max=0016;
count(integer,10)
12sum变量名不合法!
char1(char)变量值出现不合法情况!值为:\'ff\'
max(integer,0016)
int_num=2 float_num=0 char_num=0 string_num=0
*/
继续阅读与本文标签相同的文章
-
将阿里云产品整合成为高校课程实训的训练营产品的实践(二)
2026-05-18栏目: 教程
-
小程序审核常见驳回类型
2026-05-18栏目: 教程
-
Python Threading 学习笔记 | 3、join功能
2026-05-18栏目: 教程
-
Python Threading 学习笔记 | 4、Queue功能
2026-05-18栏目: 教程
-
Python Threading 学习笔记 | 5、不一定有效率GIL
2026-05-18栏目: 教程
