词法分析(英语:lexical analysis)是计算机科学中将字符序列转换为单词(Token)序列的过程。进行词法分析的程序或者函数叫作词法分析器(Lexical analyzer,简称Lexer),也叫扫描器(Scanner)。词法分析器一般以函数的形式存在,供语法分析器调用。 完成词法分析任务的程序称为词法分析程序或词法分析器或扫描器。
实验目的
通过本实验使学生进一步熟悉和掌握程序设计语言的词法分析程序的设计原理及相关的设计技术,如何针对确定的有限状态自动机进行编程序;熟悉和掌握程序设计语言的语法分析程序的设计原理、熟悉和掌握算符优先分析方法。
实验要求
本实验要求:①要求能熟练使用程序设计语言编程;②在上机之前要有详细的设计报告(预习报告);③要编写出完成相应任务的程序并在计算机上准确地运行;④实验结束后要写出上机实验报告。
实验题目
针对下面文法G(S): S→ v = E E→E+E│E-E│E*E│E/E│(E)│ v │ i 其中,v为标识符,i为整型或实型数。要求完成 ① 使用自动机技术实现一个词法分析程序; ② 使用算符优先分析方法实现其语法分析程序,在语法分析过程中同时完成常量表达式的计算。
构建DFA
java代码
结合注释和DFA的图看就好了
package lab1;
import java.util.*;
/*
编号规定:
001:加法运算符
002:减法运算符
003:乘法运算符
004:除法运算符
005:左括号
013:右括号
008.标识符
010.整数
011.等号运算符
012.浮点数
014:错误字段
*/
public class lexicalAnalysis {
private static char[] Code;//转化为字符数组
public static ArrayList tokens=new ArrayList<>();//用于之后的语法分析传值使用
public static void main(String[] args) {
// String s = "abc2@e=num2+12.3.23)*123-12.#";//输入符号串
String s = "A1=1.2+3*(4-6/3)#";//表达式为A1=1.2+3*(4-6/3)
StartLexicalAnalysis(s);
}
public static void StartLexicalAnalysis(String s) {//开始进行语法分析
if (IsCode(s)) {//判断
System.out.println("当前输入符号为:" + s.substring(0,s.length()-1));
System.out.println("词法分析结果如下:");
StartState(0, 0);
}
}
private static boolean IsCode(String s){//判断源代码是否为空,为空则不能进行词法分析
if (s.isEmpty()||s.toCharArray()[0]=='#') {
System.out.println("源代码为空,无法进行词法分析!");
return false;
}
else {
Code = s.toCharArray();
return true;
}
}
private static void StartState(int basicPointer, int currentPointer)//状态0,初始状态
{
if (Code[currentPointer] == '#') {
System.out.println("词法分析结束");
}
else if (IsEqual(Code[currentPointer]))//如果当前字符是等于号进入EqualState
{
EqualState(currentPointer);
}
else if (IsAdd(Code[currentPointer]))//如果当前字符是加号进入AddState
{
AddState(currentPointer);
}
else if (IsSub(Code[currentPointer]))//如果当前字符是减号进入SubState
{
SubState(currentPointer);
}
else if (IsMul(Code[currentPointer]))//如果当前字符是乘号进入MulState
{
MulState(currentPointer);
}
else if (IsDiv(Code[currentPointer]))//如果当前字符是除号进入DivState
{
DivState(currentPointer);
}
else if (IsLParent(Code[currentPointer]))//如果当前字符是左括号进入LParentState
{
LParentState(currentPointer);
}
else if (IsRParent(Code[currentPointer]))//如果当前字符是右括号进入RParentState
{
RParentState(currentPointer);
}
else if (IsAlpha(Code[currentPointer]))//如果当前字符是字母号进入IdentState
{
IdentState(basicPointer, currentPointer + 1);//是字母就进入状态6
}
else if (IsDigit(Code[currentPointer]))//如果当前字符是数字进入IntState
{
IntState(basicPointer, currentPointer + 1);//是数字就进入状态7
}
else {
System.out.println("(014,错误," + Code[currentPointer] + ")");
String tempSt="014,"+Code[currentPointer];
tokens.add(tempSt);
StartState(basicPointer + 1, currentPointer + 1);
}
}
private static void EqualState(int j)//表示字符为等号运算符
{
System.out.println("(011,等于号," + Code[j] + ")");
String tempSt="011,"+Code[j];
tokens.add(tempSt);
StartState(j + 1, j + 1);
}
private static void AddState(int j)//表示字符为加法运算符
{
System.out.println("(001,加号," + Code[j] + ")");
String tempSt="001,"+Code[j];
tokens.add(tempSt);
StartState(j + 1, j + 1);
}
private static void SubState(int j)//表示字符为减法运算符
{
System.out.println("(002,减号," + Code[j] + ")");
String tempSt="002,"+Code[j];
tokens.add(tempSt);
StartState(j + 1, j + 1);
}
private static void MulState(int j)//表示字符为乘法运算符
{
System.out.println("(003,乘号," + Code[j] + ")");
String tempSt="003,"+Code[j];
tokens.add(tempSt);
StartState(j + 1, j + 1);
}
private static void DivState(int j)//表示字符为除法运算符
{
System.out.println("(004,除号," + Code[j] + ")");
String tempSt="004,"+Code[j];
tokens.add(tempSt);
StartState(j + 1, j + 1);
}
private static void LParentState(int j)//字符为左括号
{
System.out.println("(005,左括号," + Code[j] + ")");
String tempSt="005,"+Code[j];
tokens.add(tempSt);
StartState(j + 1, j + 1);
}
private static void RParentState(int j)//字符为右括号
{
System.out.println("(0013,右括号," + Code[j] + ")");
String tempSt="013,"+Code[j];
tokens.add(tempSt);
StartState(j + 1, j + 1);
}
private static void IdentState(int i, int j)//标识符
{
//Code[i]为准标识符的第一个字符,是个字母 ,而Code[j-1]是字母或数字
if (IsDigit(Code[j]) || IsAlpha(Code[j]))
//如果当前字符仍然为字母或数字则再次进入IdentState
{
IdentState(i, j + 1);
} else//如果当前字符为非数字及字母字符,则表明Code[i]~Code[j-1]这一段是标识符
{
System.out.print("(008,标识符,");
String tempSt="008,";
printA(i, j, tempSt);
}
}
private static void IntState(int i, int j)//状态7,准实数
{
//Code[i]为准实数的第一个字符,是个字母 ,而Code[j-1]是数字或小数点
if (IsDigit(Code[j]))//如果当前字符仍然是数字,则再次进入IntState
{
IntState(i, j + 1);
}
if (Code[j] == '.')//如果当前字符是小数点,进入PointState
{
PointState(i, j + 1);
}
if ((Code[j] != '.') && !IsDigit(Code[j]))
//如果当前字符既不为小数点也不是数字 ,则表明Code[i]~Code[j-1]这一段是个实数
{
System.out.print("(010,整数,");
String tempSt="010,";
printA(i, j, tempSt);
}
}
private static void PointState(int i, int j)//整数后接个小数点的中间态
{
//Code[i]~Code[j-1]之中含有小数点
if (!IsDigit(Code[j])) {//小数点后还是小数点或者不是数字时报错
System.out.print("(014,错误,");
String tempSt="014,";
int q = i;//从Code[i]开始算起
while ((IsDigit(Code[q])) || (Code[q]) == '.')
//直接相连的数字或小数点都属于这个无效字段的一部分
{
tempSt=tempSt+Code[q];
System.out.print(Code[q]);
q++;
}
System.out.println(")");
tokens.add(tempSt);
//Code[q]此时为无效字段的下一个字符
StartState(q, q);
}
if (IsDigit(Code[j]))//如果当前字符是数字,则进入FloatState
{
FloatState(i, j + 1);
}
}
private static void FloatState(int i,int j){
if (IsDigit(Code[j]))//如果当前字符是数字,则再次进入FloatState
{
FloatState(i, j + 1);
}
if (!IsDigit(Code[j]))
//如果当前字符是非数字字符,说明Code[i]~Code[j-1]这一段是浮点数
{
System.out.print("(012,浮点数,");
String tempSt="012,";
printA(i, j, tempSt);
}
}
private static void printA(int i, int j, String tempSt) {//用于输出非单一字符
for (int k = i; k < j; k++) {
tempSt = tempSt + Code[k];
System.out.print(Code[k]);
}
System.out.println(")");
tokens.add(tempSt);
StartState(j, j);
}
private static boolean IsEqual(char ch) {//判断是否是字符'='
return ch == '=';
}
private static boolean IsAdd(char ch)//判断是否是字符'+'
{
return ch == '+';
}
private static boolean IsSub(char ch)//判断是否是字符'-'
{
return ch == '-';
}
private static boolean IsMul(char ch)//判断是否是字符'*'
{
return ch == '*';
}
private static boolean IsDiv(char ch)//判断是否是字符'/'
{
return ch == '/';
}
private static boolean IsLParent(char ch)//判断是否左括号
{
return ch == '(';
}
private static boolean IsRParent(char ch)//判断是否是有括号
{
return ch == ')';
}
private static boolean IsDigit(char ch) {//判断是否是数字
return Character.isDigit(ch);
}
private static boolean IsAlpha(char ch) {//判断是否是字母
return Character.isLetter(ch);
}
}
复制代码