词法分析器java语言_Java语言的词法分析器的Java实现

该实验旨在实现Java语言的词法分析器,通过DFA转换图将源程序符号转化为内部表示。程序能识别保留字、运算符、常数、界符和标识符,处理注释和空白符,打印源程序的二元形式,识别词法错误并定位。实验内容包括创建词法分析器,删除注释和空白符,以及将字符分类为不同词法成分。
摘要由CSDN通过智能技术生成

一.实验目的

1、 学会针对DFA转换图实现相应的高级语言源程序。

2、 深刻领会状态转换图的含义,逐步理解有限自动机。

3、 掌握手工生成词法分析器的方法,了解词法分析器的内部工作原理。

二.实验内容

Java语言的编译程序的词法分析部分实现。

从左到右扫描每行该语言源程序的符号,拼成单词,换成统一的内部表示送给语法分析程序。

具体的要求如下:

(1)   区分保留字、运算符、常数、界符和标识符

(2)   常数包含整型(正/负)、浮点型(正/负)、字符串和字符。

(3)   空白符是空格、回车符、制表符。

(4)   代码是自由格式。

(5)   注释包含单行注释和多行注释,并且不允许嵌套

程序的记号定义:

表2-1 Java语言记号

保留字

运算符

常数

界符

标识符

abstract

assert

+

整数

字符串

,

以字母开头,

由字母数字

和下划线组成

case

catch

-

浮点数

字符

(

continue

default

*

{

enum

extends

=

[

for

goto

<

;

instanceof

int

>

)

new

package

+=

}

return

strictfp

-=

]

switch

synchronized

*=

transient

try

==

boolean

break

>=

char

class

<=

do

double

final

finally

.

if

implements

:

interface

long

!=

private

protected

short

static

this

throw

void

volatile

byte

native

constant

public

else

super

float

throws

三.实验要求

编译器实现的功能:

(1)   按语法规则将字符识别、分类,并转换成二元式形式打印

(2)   删除注释行(单行、多行)

(3)   删除空白符(空格、回车符、制表符)

(4)   列表打印源程序,按照源程序的行打印,在每行的前面加上行号,并且打印出每行包含的记号的二元形式

(5)   能识别词法错误并定位

Java词法分析进行具体的要求:

(1)      词法分析器每分析出一个完整的词法成分,就将该词法成分的行号和二元式添加到结果字符串info中:。

在所有代码分析完毕后,将info中的内容写入result.txt中;

若分析的过程中出现错误,则将错误信息和错误定位写入result.txt。

(2)      单词符号分种如下:

运算符:运算符分为由单个字符和两个字符组成的运算符。所以对于有可能组成两个运算符的字符,在分析完第一个字符后还要继续分析第二个字符才能分析出完整的运算符。

常量:常量又分为数字、字符串、字符。

a)        数字:分为整数,浮点数,且都有正/负两种情况。其中,“正”用数字开头的“+”标识(可省略),“负”用数字开头的“-”标识;

b)        字符串:字符串中允许有转义字符;

c)        字符:合法的字符有:1.单个字符;2.“\”加“b”、“n”、“r”、“t”、“\”;3.“\”加1到3位数字。

标识符

保留字:标示符和保留字的词法构成相同。识别出字符串后,再根据保留字数组判断该字符串是否为保留字;

界符

(3)      词法分析器的具体功能实现是用函数analyze()。每次都根据当前的状态和当前的字符来判断下一步操作,下一步操作有:

转换系统状态;

读取下一个字符;

将当前字符存入字符串中,待该完成词法成分都在字符串中时再生成对应的二元式,并清空字符串。

根据具体情况,下一步操作可同时执行以上三个动作或只执行其中一个或两个。

DFA:

7dfa310bfe767783625949f7218fdd8f.png

四.代码

package newp2;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

public class Lexical {

private static final String reserveWords[] = { "abstract", "boolean", "break", "byte", "case", "catch", "char",

"class", "continue", "default", "do", "double", "else", "extends", "final", "finally", "float", "for", "if",

"implements", "import", "instanceof", "int", "interface", "long", "native", "new", "package", "private",

"protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw",

"throws", "transient", "try", "void", "volatile", "while", "strictfp", "enum", "goto", "const", "assert" }; // 50

private FileReader fd;

private int state;

private char ch;

private String info; // 结果串

private String temp; // 临时存储

int lineNum;

public Lexical() {

info = "";

temp = "";

lineNum = 1;

getChar();

analyze();

write(info);

}

private void analyze() {

if (ch == (char) -1 && temp.equals(""))

return; // 已经读取到最后一个字符,且没有待处理字符

if (ch == '\n')

lineNum++;

switch (state) {

case 0:

temp = "";

if (ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n') {

toNextCharAndChangeState(0);

} else if (ch == '/') {

toNextCharAndStoreTempAndChangeState(1);

} else if (isDigital(ch)) {

toNextCharAndStoreTempAndChangeState(5);

} else if (isOperator1(ch)) {

toNextCharAndStoreTempAndChangeState(8);

} else if (ch == '!') {

toNextCharAndStoreTempAndChangeState(9);

} else if (isOperator2(ch)) {

writeInfo((ch + ""), "运算符");

getChar();

} else if (isBoundary(ch)) {

writeInfo((ch + ""), "界符");

getChar();

} else if (ch == '"') {

toNextCharAndStoreTempAndChangeState(10);

} else if (isLetter(ch)) {

toNextCharAndStoreTempAndChangeState(11);

} else if (ch == '\'') {

toNextCharAndStoreTempAndChangeState(14);

} else if (ch == '-' || ch == '+') {

toNextCharAndStoreTempAndChangeState(16);

} else if (ch == '|') {

toNextCharAndStoreTempAndChangeState(17);

} else if (ch == '&') {

toNextCharAndStoreTempAndChangeState(18);

} else if (ch == (char) -1) {

// 程序应该结束

} else { // 非法字符

error(1);

return;

}

break;

case 1:

if (ch == '/') {

toNextCharAndChangeState(2);

} else if (ch == '*') {

toNextCharAndChangeState(3);

} else {

state = 8;

}

break;

case 2: // 处理注释

if (ch == '\n') {

state = 0;

getChar();

} else {

getChar();

}

break;

case 3: // 处理注释

if (ch == '*') {

toNextCharAndChangeState(4);

} else {

getChar();

}

break;

case 4: // 处理注释

if (ch == '/') {

toNextCharAndChangeState(0);

} else {

toNextCharAndChangeState(3);

}

break;

case 5:

if (isDigital(ch)) {

temp += ch;

getChar();

} else {

state = 6;

}

break;

case 6:

if (ch == '.') {

toNextCharAndStoreTempAndChangeState(7);

} else {

writeInfo(temp, "常数");

}

break;

case 7:

if (isDigital(ch)) {

toNextCharAndStoreTempAndChangeState(13);

} else {

error(4);

return;

}

break;

case 8:

if (ch == '=') {

temp += ch;

writeInfo(temp, "运算符");

getChar();

} else {

writeInfo(temp, "运算符");

}

break;

case 9:

if (ch == '=') {

temp += ch;

writeInfo(temp, "运算符");

getChar();

} else {

error(2);

return;

}

break;

case 10:

if (ch == '"') {

temp += ch;

writeInfo(temp, "常量");

getChar();

} else if (ch == '\\') {

for (int i = 0; i < 2; i++) {

temp += ch;

getChar();

}

state = 10;

} else {

toNextCharAndStoreTempAndChangeState(10);

}

break;

case 11:

if (isDigital(ch) || isLetter(ch) || ch == '_') {

toNextCharAndStoreTempAndChangeState(11);

} else {

state = 12;

}

break;

case 12:

if (isReserve(temp)) {

writeInfo(temp, "保留字");

getChar();

} else {

writeInfo(temp, "标识符");

getChar();

}

break;

case 13:

if (isDigital(ch)) {

toNextCharAndStoreTempAndChangeState(13);

} else {

writeInfo(temp, "常数");

}

break;

case 14:

if (ch == '\'') {

temp += ch;

if (isLegalChar(temp)) {

writeInfo(temp, "常量");

} else {

error(9);

return;

}

getChar();

} else if (ch == '\\') {

for (int i = 0; i < 2; i++) {

temp += ch;

getChar();

}

state = 14;

} else {

toNextCharAndStoreTempAndChangeState(14);

}

break;

case 16:

if (isDigital(ch)) {

toNextCharAndStoreTempAndChangeState(5);

} else {

state = 8;

}

break;

case 17:

if (ch == '|') {

temp += ch;

writeInfo(temp, "运算符");

getChar();

} else {

writeInfo(temp, "运算符");

}

break;

case 18:

if (ch == '&') {

temp += ch;

writeInfo(temp, "运算符");

getChar();

} else {

writeInfo(temp, "运算符");

}

break;

default:

error(3);

return;

}

analyze();

}

private boolean isLegalChar(String temp) {

char[] ch = temp.toCharArray();

int length = ch.length;

boolean isLegalChar = false;

/*

* Char a = '';// error char b = ' ';// length = 3; char c = '\n';//length = 4;

* b n r t " ' \ char d = '\122'; // length <= 6;

*/

if (length == 2) { // ''

isLegalChar = false;

} else if (length == 3) {

isLegalChar = true;

} else if (length == 4) {

if ((ch[1] == '\\') && (ch[2] == 'b' || ch[2] == 'n' || ch[2] == 'r' || ch[2] == 't' || ch[2] == '\"'

|| ch[2] == '\'' || ch[2] == '\\' || isDigital(ch[2]))) {

isLegalChar = true;

}

} else if (length <= 6) {

if (ch[1] == '\\') {

for (int i = 2; i < (length - 1); i++) {

if (!isDigital(ch[i])) {

isLegalChar = false;

break;

}

isLegalChar = true;

}

} else {

System.out.println('*');

isLegalChar = false;

}

} else {

isLegalChar = false;

}

return isLegalChar;

}

private void toNextCharAndChangeState(int state) {

this.state = state;

getChar();

}

private void toNextCharAndStoreTempAndChangeState(int state) {

temp += ch;

this.state = state;

getChar();

}

private boolean isReserve(String temp2) {

for (int i = 0; i < 50; i++) {

if (temp.equals(reserveWords[i])) {

return true;

}

}

return false;

}

private void writeInfo(String value, String type) {

info += lineNum + ": < " + type + " , " + value + " >\r\n";

state = 0;

}

private boolean isLetter(char ch) {

if ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122))

return true;

else

return false;

}

private boolean isBoundary(char ch) {

if (ch == ',' || ch == ';' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}')

return true;

return false;

}

private boolean isOperator1(char ch) { // / * = < >

if (ch == '/' || ch == '*' || ch == '=' || ch == '')

return true;

return false;

}

private boolean isOperator2(char ch) { // ? . :

if (ch == '?' || ch == '.' || ch == ':')

return true;

return false;

}

private boolean isDigital(char ch) {

if (ch >= 48 && ch <= 57)

return true;

else

return false;

}

private void error(int i) {

info = "词法分析出错\r\n错误定位:" + i;

}

private void getChar() {

try {

if (fd == null) {

fd = new FileReader("D:/MyEclipse 10 Workspaces/Lexical analyzer/io file/test.txt");

}

ch = (char) fd.read();

if (ch == -1) { // 当从一个文件中读取数据时,在数据最后会返回一个int型-1来表示结束

fd.close();

}

} catch (IOException e) {

}

}

private void write(String info) {

try {

FileWriter fw = new FileWriter("D:/MyEclipse 10 Workspaces/Lexical analyzer/io file/result.txt");

fw.write(info);

fw.flush(); // 刷新数据,将数据写入文件中

fw.close();

} catch (IOException e) {

}

}

public static void main(String[] args) throws IOException {

new Lexical();

}

}

1.根据状态转换图直接编程 编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。在此,词法分析程序作为单独的一遍,如下图所示。 具体任务有: (1)组织源程序的输入 (2)识别单词的类别并记录类别编号和值,形成二元式输出,得到单词流文件 (3)删除注释、空格和无用符号 (4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。将错误信息输出到屏幕上。 (5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。 标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址 注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。 常量表结构:常量名,常量值 单词的构词规则: 字母=[A-Z a-z] 数字=[0-9] 标识符=(字母|_)(字母|数字|_)* 数字=数字(数字)*( .数字+|) 2.S语言表达式和语句说明 1.算术表达式:+、-、*、/、% 2.关系运算符:>、>=、<、<=、==、!= 3.赋值运算符:=,+=、-=、*=、/=、%= 4.变量说明:类型标识符 变量名表; 5.类型标识符:int char float 6.If语句:if 表达式then 语句 [else 语句] 7.For语句:for(表达式1;表达式2;表达式3) 语句 8.While语句:while 表达式 do 语句 9.S语言程序:由函数构成,函数不能嵌套定义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值