📄 cffx.java
字号:
package edu.psl.by.cffx;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;
import java.util.Vector;
public class Cffx {
String sourceCode = "";
ArrayList<String> keyWords = new ArrayList<String>();// 关键词集合
ArrayList<String> limitWords = new ArrayList<String>();// 限界符集合
ArrayList<String> contents = new ArrayList<String>();// 源代码单词分解
Map<String, Integer> key;// 源代码找出的关键词,以及所在行数
ArrayList<Glorb> glorb = new ArrayList<Glorb>();// 源代码中的全局变量,以及所在行数
ArrayList<Local> local = new ArrayList<Local>();// 源代码中的局部变量,以及所在
ArrayList<String> ConstList = new ArrayList<String>();// 常量表
ArrayList<String> IdentifierList = new ArrayList<String>();// 标识符表
ArrayList<String> OutputList = new ArrayList<String>();// 输出表
ArrayList<String> lines = new ArrayList<String>();// 每行的字符
int big = 0;
int line = 1;
String functionName = null;
/**
* 初始化关键词表和限界符运算符表
*/
public Cffx() {
String keys[] = { "auto", "double", "int", "struct", "break", "else",
"long", "switch", "case", "enum", "register", "typedef",
"char", "extern", "return", "union", "const", "float", "short",
"unsigned", "continue", "for", "signed", "void", "default",
"goto", "sizeof", "volatile", "do", "while", "static", "if" };
for (int i = 0; i != keys.length; i++) {
keyWords.add(keys[i]);
}
/* 运算、限界符 */
String[] limit = new String[] { " ", "(", ")", "[", "]", "->", ".",
"!", "++", "--", "&", "~", "*", "/", "%", "+", "-", "<<", ">>",
"<", "<=", ">", ">=", "==", "!=", "&&", "||", "=", "+=", "-=",
"*=", "/=", ",", ";", "{", "}", "#", "_", "'" };
for (int i = 0; i != limit.length; i++) {
limitWords.add(limit[i]);
}
}
/***************************************************************************
* 十进制转二进制函数
**************************************************************************/
private String dtb(String buf) {
int[] temp = new int[20];
String binary = "";
int val = 0, i = 0;
/* 先将字符转化为十进制数 */
val = Integer.parseInt(buf);
if (val == 0) {
return (Integer.toString(val));
}
i = 0;
while (val != 0) {
temp[i++] = val % 2;
val /= 2;
}
binary = "";
for (int j = 0; j <= i - 1; j++)
binary += (char) (temp[i - j - 1] + 48);
return (binary);
}
/***************************************************************************
* 根据不同命令查表或造表函数
**************************************************************************/
private int find(String buf, int type, int command) {
int number = 0;
String temp;
Iterator ie = null;
ArrayList<String> al = null;
switch (type) {
case 1:// 关键字表
ie = keyWords.iterator();
break;
case 2:// 标识符表
ie = this.IdentifierList.iterator();
break;
case 3:// 常数表
ie = this.ConstList.iterator();
break;
case 4:// 运算、限界符表
ie = limitWords.iterator();
break;
}
if (ie != null)
while (ie.hasNext()) {
temp = ie.next().toString();
if (temp.equalsIgnoreCase(buf)) {
return number;
}
number++;
}
if (command == 1) {
/* 找不到,当只需查表,返回0,否则还需造表 */
return 0;
}
switch (type) {
case 1:
al = this.keyWords;
break;
case 2:
al = this.IdentifierList;
break;
case 3:
al = this.ConstList;
break;
case 4:
al = this.limitWords;
break;
}
if (al != null)
al.add(buf);
return number + 1;
}
/***************************************************************************
* 数字串处理函数
**************************************************************************/
private void cs_manage(String buffer) {
String binary = dtb(buffer);
int result = find(binary, 3, 2);
this.OutputList.add(String.format("%1$s\t\t\t数字\t\t\t%2$s", buffer,
result));
}
private String getFunctionName(int lineno) {
String buffer = lines.get(lineno - 2);
Site t = new Site();
char ch;
char[] array = new char[100];
while (t.getLoc() < buffer.length() - 1) {
int i = 0;
ch = getchc(t);
String word;
if (((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z'))
|| (ch == '_')) {
while (((ch >= 'A') && (ch <= 'Z'))
|| ((ch >= 'a') && (ch <= 'z')) || (ch == '_')
|| ((ch >= '0') && (ch <= '9'))) {
array[i++] = ch;
ch = getchc(t);
}
array[i++] = '\0';
word = joinString(array, array.length);
int result = find(word, 1, 1);
if (result != 0) {
} else {
return word;
}
if (t.getLoc() < buffer.length())
t.dec();
} else if ((ch == ' ') || (ch == '\t') || (ch == '\r'))
/* 消除空格符和水平制表符 */
;
}
return null;
}
/***************************************************************************
* 字符串处理函数
**************************************************************************/
private void ch_manage(String buffer) {
int result = find(buffer, 1, 1);
if (result != 0) {
this.OutputList.add(String.format("%1$s\t\t\t关键字\t\t\t%2$s",
buffer, result));
} else {
result = find(buffer, 2, 2);
this.OutputList.add(String.format("%1$s\t\t\t标识符\t\t\t%2$s",
buffer, result));
if (big == 1) {
Glorb temp = new Glorb(buffer, line);
glorb.add(temp);
} else if (big > 1 && functionName != null) {
Local l = new Local();
l.setFuncionName(functionName);
l.setLine(line);
l.setName(buffer);
local.add(l);
}
}
}
/***************************************************************************
* 出错处理函数
**************************************************************************/
private void er_manage(String error, int lineno) {
this.OutputList.add(String.format("错误标识符: %1$s,所在行: %2$s", error,
lineno));
}
/***************************************************************************
* 转换Char数组为string
**************************************************************************/
private String joinString(char[] array, int Length) {
String s = "";
if (array.length > 0)
for (int i = 0; i < Length; i++) {
if (array[i] != '\0') {
s += array[i];
} else {
break;
}
}
return s;
}
private char getchc(Site n) {
char[] c = sourceCode.toCharArray();
if (n.getLoc() < c.length) {
char r = c[n.getLoc()];
n.inc();
return r;
}
return sourceCode.charAt(sourceCode.length() - 1);
}
/***************************************************************************
* 扫描程序
*
* @throws FileNotFoundException
**************************************************************************/
public void Parse(String fileName) throws FileNotFoundException {
FileInputStream fis = new FileInputStream(fileName);
byte[] buff = new byte[500];
int len;
try {
len = fis.read(buff);
sourceCode = new String(buff, 0, len);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
char[] lineContent = new char[100];
int k = 0;
char ch;
int i = 0;
int count, result, errorno = 0;
char[] array = new char[30];
String word = "";
/* 按字符依次扫描源程序,直至结束 */
Site n = new Site();
while (n.getLoc() < sourceCode.length() - 1) {
i = 0;
ch = getchc(n);
lineContent[k++] = ch;
/* 以字母开头 */
if (((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z'))
|| (ch == '_')) {
while (((ch >= 'A') && (ch <= 'Z'))
|| ((ch >= 'a') && (ch <= 'z')) || (ch == '_')
|| ((ch >= '0') && (ch <= '9'))) {
array[i++] = ch;
ch = getchc(n);
}
array[i++] = '\0';
word = joinString(array, array.length);
ch_manage(word);
if (n.getLoc() < sourceCode.length())
n.dec();
} else if (ch >= '0' && ch <= '9') {
/* 以数字开头 */
while (ch >= '0' && ch <= '9') {
array[i++] = ch;
ch = getchc(n);
if (((ch >= 'A') && (ch <= 'Z'))
|| ((ch >= 'a') && (ch <= 'z')) || (ch == '_')) {
while (((ch >= 'A') && (ch <= 'Z'))
|| ((ch >= 'a') && (ch <= 'z')) || (ch == '_')
|| ((ch >= '0') && (ch <= '9'))) {
array[i++] = ch;
ch = getchc(n);
word = joinString(array, array.length);
er_manage(word, line);
errorno++;
}
} else {
while (ch >= '0' && ch <= '9') {
array[i++] = ch;
ch = getchc(n);
}
array[i++] = '\0';
word = joinString(array, array.length);
cs_manage(word);
}
if (n.getLoc() < sourceCode.length())
n.dec();
}
} else if ((ch == ' ') || (ch == '\t') || (ch == '\r'))
/* 消除空格符和水平制表符 */
;
else if (ch == '\n') {
/* 消除回车并记录行数 */
String temp;
lineContent[k++] = '\0';
temp = joinString(array, array.length);
line++;
lines.add(temp);
k = 0;
lineContent = new char[100];
} else if (ch == '/') {
/* 消除注释 */
ch = getchc(n);
if (ch == '=') {
/* 判断是否为‘/=’符号 */
this.OutputList.add(String
.format("/=\t\t\t运算符或界限符\t\t\t32"));
} else if (ch != '*') {
/* 若为除号,写入输出 */
this.OutputList
.add(String.format("/\t\t\t运算符或界限符\t\t\t13"));
n.dec();
} else if (ch == '*') {
/* 若为注释的开始,消除包含在里面的所有字符 */
count = 0;
ch = getchc(n);
while (count != 2) {
/* 当扫描到‘*’且紧接着下一个字符为‘/’才是注释的结束 */
count = 0;
while (ch != '*')
ch = getchc(n);
count++;
ch = getchc(n);
if (ch == '/')
count++;
else
ch = getchc(n);
}
}
} else if (ch == '"') {
/* 消除包含在双引号中的字符串常量 */
this.OutputList.add(String.format("%1$s\t\t\t运算符或界限符\t\t\t37",
ch));
while (ch != '"')
ch = getchc(n);
this.OutputList.add(String.format("%1$s\t\t\t运算符或界限符\t\t\t37",
ch));
} else {
/* 首字符为其它字符,即运算限界符或非法字符 */
array[0] = ch;
/* 再读入下一个字符,判断是否为双字符运算、限界符 */
ch = getchc(n);
/* 若该字符非结束符 */
if (n.getLoc() < sourceCode.length()) {
array[1] = ch;
array[2] = '\0';
word = joinString(array, 2);
result = find(word, 4, 1); /* 先检索是否为双字符运算、限界符 */
if (result == 0) {
/* 若不是 */
array[2] = '\0';
word = joinString(array, 1);
result = find(word, 4, 1);
/* 检索是否为单字符运算、限界符 */
if (result == 0) {
/* 若还不是,则为非法字符 */
er_manage(word, line);
errorno++;
n.dec();
} else {
/* 若为单字符运算、限界符,写入输出并将扫描指针回退一个字符 */
this.OutputList.add(String.format(
"%1$s\t\t\t运算符或界限符\t\t\t%2$s\t", word,
result));
if (word.equals("{")) {
big++;
if (big > 1) {
functionName = getFunctionName(line);
}
}
if (word.equals("}")) {
big--;
}
n.dec();
}
} else {
/* 若为双字符运算、限界符,写输出 */
this.OutputList.add(String.format(
"%1$s\t\t\t运算符或界限符\t\t\t%2$s", word, result));
}
} else {
/* 若读入的下一个字符为结束符 */
array[2] = '\0';
word = joinString(array, 1);
/* 只考虑是否为单字符运算、限界符 */
result = find(word, 4, 1);
/* 若不是,转出错处理 */
if (result == 0)
er_manage(word, line);
else {
/* 若是,写输出 */
this.OutputList.add(String.format(
"%1$s\t\t\t运算符或界限符\t\t\t%2$s", word, result));
}
}
}
}
/* 报告错误字符个数 */
this.OutputList.add(String.format("\n共有 %1$d个错误.\n", errorno));
for (i = 0; i != OutputList.size(); i++) {
System.out.println(OutputList.get(i));
}
System.out.println("全局变量:");
for (i = 0; i != glorb.size(); i++) {
System.out.println(glorb.get(i).getContent() + " "
+ glorb.get(i).getLine());
}
System.out.println("局部变量:");
for (i = 0; i != local.size(); i++) {
System.out.println(local.get(i).getName() + " "
+ local.get(i).getFuncionName()+" "+local.get(i).getLine());
}
}
/**
* @param args
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String fileName = sc.nextLine();
Cffx cffx = new Cffx();
try {
cffx.Parse(fileName);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -