编译原理实验一 -无符号数的词法分析程序
一、实验目的和要求:
1.掌握词法分析的基本思想,并用高级语言编写无符号数的词法分析程序。
2.要求从键盘上输入一串字符(包括字母、数字等),最后以“;”结束,编
写程序识别出其中的无符号数
二、实验平台:
Java语言
三、主要实验内容及结果:
实验内容:
词法分析的主要任务是:扫描源程序,识别单词,生成属性字。单词的种类一般分为四种:关键字、标识符、常数、特殊符号,无符号数是常数中的一种,无符号数的词法分析难点在于带指数的无符号数的识别。
无符号数文法规则可定义如下:
<无符号数>→<无符号实数>│<无符号整数>
<无符号实数>→<无符号整数>.<数字串>[E<比例因子>]│
<无符号整数>E<比例因子>
<比例因子>→<有符号整数>
<有符号整数>→[+│-]<无符号整数>
<无符号整数>→<数字串>
<数字串>→<数字>{<数字>}
<数字>→0 │1 │2 │3...... │9
程序代码:
import java.util.ArrayList;
import java.util.Scanner;
public class Unsigned {
private ArrayList<Word> wordList;
public static void main(String[] args) {
Unsigned unsigned = new Unsigned();
// 读入单词列表
unsigned.inputWordList();
// 识别单词列表
for (Word word : unsigned.wordList) {
// 识别单词
unsigned.whichType(word);
String temp = word.getCJ2();
if (temp != null) {
int index = temp.lastIndexOf(".0");
if (index == temp.length() - 2)
word.setCJ2(temp.substring(0, index));
}
}
// 输出单词列表
unsigned.printWordList();
}
// 识别单词
private void whichType(Word word) {
int w = 0;
int p = 0;
int j = 0;
int e = 1;
int d = 0;
String chars[] = word.getStr().split("");
// 从第一个字符开始
int i = 0;
String current_char = chars[i];
// 数字否?
if (!isNum(current_char)) {
word.setCJ1("出错");
return;
} else {
while (true) {
d = Integer.parseInt(current_char);
w = w * 10 + d;
current_char = chars[++i];
// 数字否?
if (isNum(current_char))
{
continue;
} else {
// 是'.'否?
if (current_char.equals(".")) {
current_char = chars[++i];
// 数字否?
if (!isNum(current_char))
{
word.setCJ1("出错");
return;
} else {
while (true) {
d = Integer.parseInt(current_char);
w = w * 10 + d;
j = j + 1;
current_char = chars[++i];
// 数字否?
if (isNum(current_char)) {
continue;
} else {
// 是'E'否?
if (current_char.equals("E")) {
isE(current_char, chars, i, word, w, p, j, e, d);
return;
} else {
// 退一字符
word.setCJ1("实型");
word.setCJ2((w * Math.pow(10, e * p - j)) + "");
return;
}
}
}
}
} else {
// 是'E'否?
if (current_char.equals("E")) {
isE(current_char, chars, i, word, w, p, j, e, d);
return;
} else {
// 退一字符
word.setCJ1("整型");
word.setCJ2((w * Math.pow(10, e * p - j)) + "");
return;
}
}
}
}
}
}
private void isE(String current_char, String[] chars, int i, Word word, int w, int p, int j, int e, int d) {
current_char = chars[++i];
// 是'-'否?
if (current_char.equals("-")) {
e = -1;
current_char = chars[++i];
// 数字否?
if (isNum(current_char)) {
while (true) {
d = Integer.parseInt(current_char);
p = p * 10 + d;
current_char =
chars[++i];
if (isNum(current_char))
{
continue;
} else {
// 退一字符
word.setCJ1("实型");
word.setCJ2((w * Math.pow(10, e * p - j)) + "");
return;
}
}
} else {
word.setCJ1("出错");
return;
}
} else {
// 是'+'否?
if (current_char.equals("+")) {
current_char =
chars[++i];
// 数字否?
if (isNum(current_char))
{
while (true) {
d = Integer.parseInt(current_char);
p = p * 10 + d;
current_char =
chars[++i];
if (isNum(current_char))
{
continue;
} else {
// 退一字符
word.setCJ1("实型");
word.setCJ2((w * Math.pow(10, e * p - j)) + "");
return;
}
}
} else {
word.setCJ1("出错");
return;
}
} else {
// 数字否?
if (isNum(current_char))
{
while (true) {
d = Integer.parseInt(current_char);
p = p * 10 + d;
current_char =
chars[++i];
if (isNum(current_char))
{
continue;
} else {
// 退一字符
word.setCJ1("实型");
word.setCJ2((w * Math.pow(10, e * p - j)) + "");
return;
}
}
} else {
word.setCJ1("出错");
return;
}
}
}
}
// 是否为数字
private boolean isNum(String string) {
return "0123456789".contains(string);
}
// 读入单词列表
private void inputWordList() {
System.out.println("12996 0269 0E Es265 ;要求从键盘上输入一串字符(包括字母、数字等),最后以“;”结束");
Scanner scanner = new Scanner(System.in);
String temp = scanner.nextLine().replace(";", "");
scanner.close();
String[] strs = temp.split(" ");
wordList = new ArrayList<Word>();
for (String str : strs) {
Word word = new Word();
word.setStr(str + "#");
wordList.add(word);
}
}
// 输出单词列表
private void printWordList() {
for (Word word : wordList) {
System.out.println(word.getStr() + "\t" + word.getCJ2() + "\t" + word.getCJ1());
}
}
// 单词类
private class Word {
// str记原始单词
private String str;
// CJ1记类型
private String CJ1;
// CJ1记数值
private String CJ2;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String getCJ1() {
return CJ1;
}
public void setCJ1(String cJ1) {
CJ1 = cJ1;
}
public String getCJ2() {
return CJ2;
}
public void setCJ2(String cJ2) {
CJ2 = cJ2;
}
}
}
运行结果:
四、心得体会
词法分析阶段是编译过程的第一个阶段,是编译的基础。这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。