词法分析器实现过程(java和c++实现)

词法分析器是编译原理的一个实验,本文将会详细给出实现的具体步骤,利用java进行示例讲解,源码(包含java和c++两种实现方式)可在 https://download.csdn.net/download/qq_40121502/10926516 下载。

一、 实验目的

设计、编写一个词法分析程序,加深对词法分析原理的理解。

二、 实验原理

词法分析是从左向右一个字符、一个字符地读入源程序,扫描每行源程序的符号,依据词法规则,识别单词。执行词法分析的程序称为词法分析器,将给定的程序通过词法分析器,识别出一个个单词符号。单词符号常采用统一的二元式表示:(单词种别码,单词符号自身的值),单词种别码是语法分析所需要的信息,而单词符号自身属性值是编译其他阶段需要的信息。

三、 实验内容

(1)程序利用C++或Java或其他编程语言,给出其词法的产生式(词法部分也可以用regular expression),包含数学运算表达式,赋值,函数调用,控制流语句(分支或循环),类型声明等基本元素。
(2)词法实验部分要求写出该语言的词法分析程序。要求识别出词法分析单元,给出词法单元的分类,按照不同类别填入相应的表中,表中给出词法单元在源程序中的位置。

四、 实验方法

(1)词法的产生式(或regular expression)转换成NFA
(2)NFA确定化为DFA
(3)DFA最小化
(4)根据最小化后的DFA写出词法分析程序。
(5)使用选定的编程语言写几个测试用例文件作为输入,测试词法分析程序是否正确。

五、 实验设计

(1)关键字:
“char”,“int”,“float”,“double”,“final”,“if”,“else”,“while”,“do”,“for”,“break”,“continue”,”void”,”return”
(2)运算符:=、==、>、<、>=、<=、+、-、*、/
(3)界限符:( ) [ ]{ } , : ;
(4)标识符(ID):用字母、数字、下划线的连接用来表示变量名、过程名等的单词称为标识符(不能以数字开头、不与关键字重名、不包含$、#等无法识别的字符)
(5)常量(NUM):整数、小数、浮点数。
(6)词法分析阶段通常忽略空格、制表符和换行符等。
根据以上的分类与分析,设置该语言中的单词符号及种别编码如下表:
在这里插入图片描述

六、状态图分析

1.关键字

本次设计中关键字有17个,分别包括:
“char”,“short”,“int”,“long”,“float”,“double”,“final”,“static”,“if”,“else”,“while”,
“do”,“for”,“break”,“continue”,“void”, “return”。
关键字都是由小写字母组成,在程序中,将17个关键字保存在一个String类型的数组中,然后做一次循环,将字符串逐个与17个关键字对比,相同则取出对应的种别码,存入ArrayList中。
关键字的正规表达式为:
key->letter( letter )*
letter->[a-z]
按照RE—>NFA—>DFA—>最小化DFA的顺序,过程如图所示:
在这里插入图片描述

2.运算符

本实验设计了十个运算符,分别为:=、==、>、<、>=、<=、+、-、、/
运算符表达式为:
operation -> ( = | == | > | < | >= | <= | + | - | * | / )

按照RE—>NFA—>DFA—>最小化DFA的顺序,过程如图所示:在这里插入图片描述

3.界限符

本实验设计的界限符有:( ) [ ]{ } , : ;
界限符表达式为:
delimiter -> ( ( | ) | [ | ] | { | } | , | : | ; )*
从RE—>NFA—>DFA—>最小化DFA的顺序,过程如图所示:
在这里插入图片描述

4.标识符

用字母、数字、下划线的连接用来表示变量名、过程名等的单词称为标识符(不能以数字开头、不与关键字重名、不包含$、#等无法识别的字符)。
标识符的正规表达式为:
ID ->( letter | _ ) ( letter | digit | _ )*
letter->[a-zA-Z]
digit->[0-9]
按照RE—>NFA—>DFA—>最小化DFA的顺序,过程如图所示:
在这里插入图片描述

5.常量

将整数,浮点数归并后分为无符号数和有符号数。
因为有符号数,除了开始有符号外,之后的判断与无符号数是一致的。所以在这里只针对无符号数的正规表达式构造NFA和DFA。
无符号数正规表达式:
NUM -> digits op_fra op_exp
其中:
digits -> d(d)*
d -> [0-9]
op_fra-> .digits | ε
op_exp -> ( E (+|-| ε) digits) | ε
将上述表达式整合得无符号数NUM的正规表达式为:
NUM->d(d)|d(d).d(d)|d(d)(E(+|-|ε)d(d))|d(d).d(d)E(+|-|ε)d(d)
d -> [0-9]
按照RE—>NFA—>DFA—>最小化DFA的顺序,过程如图所示:
在这里插入图片描述在这里插入图片描述

七、数据结构

(1)使用ArrayList<String>来存放从文件内读取进来的每个单词(符号)。
(2)自定义类Pair,相当于键值对,用于存放单词种别码和对应的单词,包含一个Integer类型的key和一个String类型的value。
(3)使用ArrayList<Pair>来存放词法分析的结果。

八、实现代码

1.定义关键字

首先定义了一系列关键字及其对应的种别码,用于表示词法分析的结果。

// 单词种别码, 1-17为关键字种别码
public static final int CHAR = 1;
public static final int SHORT = 2;
public static final int INT = 3;
public static final int LONG = 4;
public static final int FLOAT = 5;
public static final int DOUBLE = 6;
public static final int FINAL = 7;
public static final int STATIC = 8;
public static final int IF = 9;
public static final int ELSE = 10;
public static final int WHILE = 11;
public static final int DO = 12;
public static final int FOR = 13;
public static final int BREAK = 14;
public static final int CONTINUE = 15;
public static final int VOID = 16;
public static final int RETURN = 17;

// 20为标识符种别码
public static final int ID = 20;

// 30为常量种别码
public static final int NUM = 30;

// 31-40为运算符种别码
public static final int AS = 31; // =
public static final int EQ = 32; // ==
public static final int GT = 33; // >
public static final int LT = 34; // <
public static final int GE = 35; // >=
public static final int LE = 36; // <=
public static final int ADD = 37; // +
public static final int SUB = 38; // -
public static final int MUL = 39; // *
public static final int DIV = 40; // /

// 41-49为界限符种别码
public static final int LP = 41; // (
public static final int RP = 42; // )
public static final int LBT = 43; // [
public static final int RBT = 44; // ]
public static final int LBS = 45; // {
   
public static final int RBS = 46; // }
public static final int COM = 47; // ,
public static final int COL = 48; // :
public static final int SEM = 49; // ;

// -1为无法识别的字符标志码
public static final int ERROR = -1;
public static int errorNum = 0; // 记录词法分析错误的个数
2.单词分割

对于输入的代码段,进行单词的分割,需要识别判断出分割的位置,最后将拆分好的单词序列放入ArrayList<String>中保存,用于后续的词法分析。

测试文件读入内存
final String blank = " ";
final String newLine = "\n";
Scanner scanner = new Scanner(System.in);
System.out.print("请输入测试文件的路径:");
String filepath = scanner.next();
StringBuffer sb = new StringBuffer();
String fileStr = "";
try {
   
    InputStream is = 
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值