编译原理__词法分析器

本文详细介绍了词法分析器的工作原理,包括其任务、与语法分析器的交互以及输出形式。重点讲解了如何构造词法分析器的状态图,并提供了Java实现词法分析器的代码示例,涵盖了关键字、标识符、常数、运算符和分隔符的识别过程。通过这段代码,读者可以理解词法分析器如何从源代码中提取出有意义的单词符号。

1. 词法分析器的任务:
输入源程序,输出单词符号。即从组成源程序的符号串中识别出一个个单词符号。

2. 词法分析器与语法分析器的交互:
这里写图片描述

3. 词法分析器的输出形式
词法分析器输出一个个的单词符号,通常表示成二元组(单词类别,单词符号的属性值)。单词类别是指单词的种类的整数编码,而单词符号的属性是指单词符号的特征或特性。属性值则是反应特征或特性的值。这个二元组是后面语法分析、语义分析及转换的输入。

4. 单词的种类
- 关键字
- 标识符
- 常数
- 运算符(操作符)
- 分隔符

5. 构造词法分析器的状态图
那么怎么写自己的词法分析器呢?我们将源程序看成是一个很大的字符串,我们的任务是从这个大的字符串中把关键字、标识符等等识别出来,分解成一个个的字符串。那怎么识别呢?请看下面的状态转换图

这里写图片描述

6. 下面是词法分析器的代码

`packagepackage com.java.zhenghui;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.PushbackReader;
import java.util.*;
import javax.swing.JOptionPane;

class Data { //二元组
//变量
private int kind; //单词类型
private String value = null; //属性值
//方法
public Data(int _kind, String _value) {
kind = _kind;
value = _value;
}
public Data(int _kind) {… }
public int getFirst() {… }
public String getSecond() {… }
}
//词法分析的类
public class Cifa {
//首先我们需要一个函数,判断读入的字符的类型:数字、字母、下划线。。。
public static int panDuan(char c) {
Character ch = Character.valueOf(c);
if (Character.isDigit(c) == true)
return 0;// 数字返回
if (Character.isLetter(c) == true||c==’_’)
return 1;// 字母或下划线返回1
if (Character.isWhitespace(c) == true)
return 2;// 空格返回2
if (ch.equals(‘+’) || ch.equals(‘-‘) || ch.equals(‘*’)
|| ch.equals(‘/’) || ch.equals(‘%’) || ch.equals(‘<’)
|| ch.equals(‘>’) || ch.equals(‘=’) || ch.equals(‘!’)
|| ch.equals(‘&’) || ch.equals(‘|’) || ch.equals(‘^’)
|| ch.equals(‘~’))
return 3; // 操作符返回3
if (ch.equals(‘(‘) || ch.equals(‘)’) || ch.equals(‘[‘)
|| ch.equals(‘]’) || ch.equals(‘{‘) || ch.equals(‘}’)
|| ch.equals(‘?’) || ch.equals(‘:’) || ch.equals(‘#’)
|| ch.equals(‘,’)|| ch.equals(‘;’) || ch.equals(‘”’)
|| ch.equals(‘\”)|| ch.equals(‘.’))
return 4; // 分隔符返回4
return 5;// 其他不认识的字符
}
//datas用来装所有的单词
private ArrayList datas=new ArrayList();
public void doSomething() {//对着上面的状态转换图看下面的代码…
int rowcount=1;//开始为第一行
//定义单词类别,用int型表示
final int NUMBER = 0; // 数字及小数点
final int ALPHA = 1; // 字母
final int SPACE = 2; // 空格
final int OPERATOR = 3; // 操作符
final int APART = 4; // 分隔符
final int INTCONSTANCE=100;
final int DOUBLECONSTANCE=101;
final int IDENT=102;
final int BREAK=103;
final int CASE=104;
final int CHAR=105;
final int CONTINUE=106;
final int DEFAULT=107;
final int DO=108;
final int DOUBLE=109;
final int ELSE=110;
final int FLOAT=111;
final int FOR=112;
final int IF=113;
final int INCLUDE=114;
final int INT=115;
final int LONG=116;
final int MAIN=117;
final int RETURN=118;
final int SHORT=119;
final int SIGNED=120;
final int SIZEOF=121;
final int STATIC=122;
final int SWITCH=123;
final int UNSIGNED=124;
final int VOID=125;
final int WHILE=126;
final int JIA=200;
final int JIAN=201;
final int CHENG=202;
final int CHU=203;
final int JIADENG=204;
final int JIANDENG=205;
final int CHENGDENG=206;
final int CHUDENG=207;
final int JIAJIA=208;
final int JIANJIAN=209;
final int MO=210;
final int MODENG=211;
final int LEFTYIDENG=212; // <<=
final int RIGHTYIDENG=213; // >>=
final int XIAOXIAO=214; // <<
final int DADA=215; // >>
final int XIAO=216; // <
final int DA=217; // >
final int DENG=218; // =
final int DENGDENG=219; // ==
final int BUDENG=220; //!=
final int BU=221; //!
final int DADENG=222; // >=
final int XIAODENG=223; // <=
final int YU=224; // &&
final int HUO=225; // ||
final int WEIYU=226; // &
final int WEIHUO=227; // |
final int WEIYUDENG=228; // &=
final int WEIHUODENG=229; // |=
final int WEIFAN=230; // ~
final int WEIFANDENG=231; // ~=
final int WEIYIHUO=232; // ^
final int WEIYIHUODENG=233; // ^=
final int LEFTXIAOKUOHAO=300;
final int RIGHTXIAOKUOHAO=301;
final int LEFTZHONGKUOHAO=302;
final int RIGHTZHONGKUOHAO=303;
final int LEFTDAKUOHAO=304;
final int RIGHTDAKUOHAO=305;
final int WENHAO=306;
final int MAOHAO=307;
final int JINHAO=308;
final int DOUHAO=309;
final int FENHAO=310;
final int DANYINHAO=311;
final int DANYINHAOZY=312;
final int SHUANGYINHAO=313;
final int JUHAO=314;
final int ERROR=400;
try {
System.out.println(“第”+rowcount+”行”);
String dir;
String filename= JOptionPane.showInputDialog(“please input the filename:(比如:data.txt)”);
dir = System.getProperty(“user.dir”);// 得到用户当前目录
PushbackReader file = new PushbackReader(new FileReader(dir+ “\src\”+filename), 3);
char ch;
int n, m;
while ((n = file.read()) != -1)// 每次读一个字符
{
ch = (char) (n);// 当前处理的字符放在ch中
String value = null; // 当前取出的单词放在value中
// System.out.print(ch);
m = Cifa.panDuan(ch);
switch (m) {
/********************************************/
case NUMBER:// 数字 弄出整型常量或浮点型常量
int point=0;
value = “” + ch;
while ((n = file.read()) != -1
&& ((char) n == ‘.’ || Character.isDigit((char) n)))
{ // 是数字或小数点
if( (char) n == ‘.’ && point==0 )
++point;
else if((char) n == ‘.’ && point!=0)
break;//不是第一个小数点了,跳出
value += (char) n;
}
if ((char) n == ‘e’)// 如1.2e……
{
if ((n = file.read()) != -1
&& Character.isDigit((char) n))// 如1.2e3dea
{
value = value + ‘e’ + (char) n;
while ((n = file.read()) != -1
&& Character.isDigit((char) n))
value += (char) n;
if (n != -1)
file.unread(n); //退回d
} else if ((char) n == ‘-‘) {// 如1.2e-……
if ((n = file.read()) != -1
&& Character.isDigit((char) n))// 如1.2e-3daq
{
value = value + ‘e’ + ‘-’ + (char) n;
while ((n = file.read()) != -1
&& Character.isDigit((char) n))
value += (char) n;
if (n != -1)
file.unread(n); //退回d
} else if (n != -1) {// 如1.2e-adsf
file.unread(n); //退回a
file.unread(‘-‘); //退回-
file.unread(‘e’); //退回e
}
}else{ //如1.2ea
if(n!=-1)
file.unread(n); //退回a
file.unread(‘e’); //退回e
}
}else {//如1.2dfk 退回d
if (n != -1)
file.unread(n);
}
System.out.println(“”+rowcount+” NUMBER: “+value); //#########
if(value.contains(“.”)||value.contains(“e”))//串包含小数点或e则当作double类型 
{
datas.add(new Data(DOUBLECONSTANCE,value));
}
else
{
datas.add(new Data(INTCONSTANCE,value));
}//###########
break;
/**************************************************/
case ALPHA:// 字母 弄出标识符或关键字
value=”“+ch;
while ((n = file.read()) != -1&&( Character.isLetter((char)n)||(char)n==’_’||Character.isDigit((char)n) ) )// 每次读一个字符
{
value+=(char)n;
}
if(n!=-1)
file.unread(n);
if(value.equals(“break”))//######## 关键字
datas.add(new Data(BREAK,value));
else if(value.equals(“case”))
datas.add(new Data(CASE,value));
else if(value.equals(“char”))
datas.add(new Data(CHAR,value));
else if(value.equals(“continue”))
datas.add(new Data(CONTINUE,value));
else if(value.equals(“default”))
datas.add(new Data(DEFAULT,value));
else if(value.equals(“do”))
datas.add(new Data(DO,value));
else if(value.equals(“double”))
datas.add(new Data(DOUBLE,value));
else if(value.equals(“else”))
datas.add(new Data(ELSE,value));
else if(value.equals(“float”))
datas.add(new Data(FLOAT,value));
else if(value.equals(“for”))
datas.add(new Data(FOR,value));
else if(value.equals(“if”))
datas.add(new Data(IF,value));
else if(value.equals(“include”))
datas.add(new Data(INCLUDE,value));
else if(value.equals(“int”))
datas.add(new Data(INT,value));
else if(value.equals(“long”))
datas.add(new Data(LONG,value));
else if(value.equals(“main”))
datas.add(new Data(MAIN,value));
else if(value.equals(“return”))
datas.add(new Data(RETURN,value));
else if(value.equals(“short”))
datas.add(new Data(SHORT,value));
else if(value.equals(“signed”))
datas.add(new Data(SIGNED,value));
else if(value.equals(“sizeof”))
datas.add(new Data(SIZEOF,value));
else if(value.equals(“static”))
datas.add(new Data(STATIC,value));
else if(value.equals(“switch”))
datas.add(new Data(SWITCH,value));
else if(value.equals(“unsigned”))
datas.add(new Data(UNSIGNED,value));
else if(value.equals(“void”))
datas.add(new Data(VOID,value));
else if(value.equals(“while”))
datas.add(new Data(WHILE,value));
else//标识符
datas.add(new Data(IDENT,value));
System.out.println(“”+rowcount+” IDENT: “+value);
break;
/**************************************************/
case SPACE:// 空格 跳过不管
if(n==13){
++rowcount;
System.out.println(“第”+rowcount+”行”);
}
break; /**************************************************/
case OPERATOR:// 操作符 if(ch==’+’||ch==’-‘||ch==’=’||ch==’&’||ch==’|’)
{
if( (n=file.read())!=-1)
{
char temp=(char)n;
if(temp==’=’){
value=”“+ch+temp; //如+= == &=
if(ch==’+’)
datas.add(new Data(JIADENG,value));
if(ch==’-‘)
datas.add(new Data(JIANDENG,value));
if(ch==’=’)
datas.add(new Data(DENGDENG,value));
if(ch==’&’)
datas.add(new Data(WEIYUDENG,value));
if(ch==’|’)
datas.add(new Data(WEIHUODENG,value));
}else if(temp==ch){ //如++ – 但==不在其中
value=”“+ch+temp;
if(ch==’+’)
datas.add(new Data(JIAJIA,value));
if(ch==’-‘)
datas.add(new Data(JIANJIAN,value));
if(ch==’&’)
datas.add(new Data(YU,value));
if(ch==’|’)
datas.add(new Data(HUO,value));
}
else{
value=”“+ch; //如 + - =
if(ch==’+’)
datas.add(new Data(JIA,value));
if(ch==’-‘)
datas.add(new Data(JIAN,value));
if(ch==’=’)
datas.add(new Data(DENG,value));
if(ch==’&’)
datas.add(new Data(WEIYU,value));
if(ch==’|’)
datas.add(new Data(WEIHUO,value));
file.unread(temp);
}
}else{
value=”“+ch;
if(ch==’+’)
datas.add(new Data(JIA,value));
if(ch==’-‘)
datas.add(new Data(JIAN,value));
if(ch==’=’)
datas.add(new Data(DENG,value));
if(ch==’&’)
datas.add(new Data(WEIYU,value));
if(ch==’|’)
datas.add(new Data(WEIHUO,value));
}
}
if(ch==’>’||ch==’<’)
{
if( (n=file.read())!=-1)
{
char temp1=(char)n;
if( (n=file.read())!=-1)
{
char temp2=(char)n;
if(temp1==ch&&temp2==’=’){ //如 <<=3
value=”“+ch+temp1+temp2;
if(ch==’<’) //<<=
datas.add(new Data(LEFTYIDENG,value));
if(ch==’>’) //>>=
datas.add(new Data(RIGHTYIDENG,value));
}
else if(temp1==ch){ //如 <

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值