简单实现词法分析器
说明
- 开发语言: java
- 界面设计:采用eclipse的插件windowbuilder
- 功能描述:统计行数和列数用于错误单词的定位,如果发现错误则报告出错。删除空格类字符,包括回车、制表符空格,按拼写单词(关键字、标识符、常数、运算符、关系运算符、分界符号),并用(内码,属性)二元式表示。
主程序流程
源程序存储在文件中,用一个字符串word存储识别的字符,通过read()函数读入文件中一个字符。
如果识别到空格,制表符等,直接通过read()读取下一个字符。
如果识别到字母,进入状态1的判断分支,然后读取下一个字符进行判断,如果为数字和字母则连接到word后,再读取下一个。直到结束后判断其是否为关键字或标识符。
如果识别到运算符或分割符,通过switch语句进行相应的判断,其余基本操作与上图和描述相似。
代码
package lexical;
import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.event.ActionListener;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.awt.event.ActionEvent;
import java.awt.TextField;
import java.awt.TextArea;
import java.awt.Button;
import java.awt.Font;
public class Lexical_gui {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Lexical_gui window = new Lexical_gui();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Lexical_gui() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setTitle("\u8BCD\u6CD5\u5206\u6790\u5668");
frame.setFont(new Font("Dialog", Font.PLAIN, 20));
frame.setResizable(false);
frame.setBounds(100, 100, 769, 454);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
TextArea textArea = new TextArea();
textArea.setFont(new Font("Dialog", Font.PLAIN, 20));
textArea.setBounds(38, 87, 696, 307);
frame.getContentPane().add(textArea);
TextField textField = new TextField();
textField.setFont(new Font("Dialog", Font.PLAIN, 20));
textField.setBounds(38, 28, 579, 38);
frame.getContentPane().add(textField);
Button button_1 = new Button("选择");
button_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
int[] row_line = { 1, 0 };
String word = "";
int c;
try {
String filename = textField.getText();
Reader r = new FileReader(filename);
c = r.read();
while (c != -1) {
word = "";
while (c == 32 || c == 9 || c == 10 || c == 13) {
if (c == 10) {
row_line[0] = row_line[0] + 1;
row_line[1] = 0;
}
c = r.read();
}
if (isLetter(c)) {
word = word + (char) c;
row_line[1] = row_line[1] + 1;
c = r.read();
while (isLetter(c) || isNumber(c)) {
word = word + (char) c;
row_line[1] = row_line[1] + 1;
c = r.read();
}
if (find_key(word)) {
textArea.append(
word + "\t1\t" + word + "\t关键字\t\t" + row_line[0] + "," + row_line[1] + '\n');
} else {
textArea.append(
word + "\t6\t" + word + "\t标识符\t\t" + row_line[0] + "," + row_line[1] + '\n');
}
} else if (isNumber(c)) {
word = word + (char) c;
row_line[1] = row_line[1] + 1;
c = r.read();
while (isNumber(c)) {
word = word + (char) c;
row_line[1] = row_line[1] + 1;
c = r.read();
}
textArea.append(
word + "\t5\t" + word + "\t无符号数\t\t" + row_line[0] + "," + row_line[1] + '\n');
} else if (c == 60 || c == 62) {
word = word + (char) c;
row_line[1] = row_line[1] + 1;
c = r.read();
if (c == 60 || c == 61 || c == 62) {
word = word + (char) c;
row_line[1] = row_line[1] + 1;
c = r.read();
}
textArea.append(
word + "\t4\t" + word + "\t关系运算符\t\t" + row_line[0] + "," + row_line[1] + '\n');
} else {
word = word + (char) c;
row_line[1] = row_line[1] + 1;
switch (word) {
case "=":
textArea.append(
word + "\t3\t" + word + "\t算术运算符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case "+":
textArea.append(
word + "\t3\t" + word + "\t算术运算符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case "-":
textArea.append(
word + "\t3\t" + word + "\t算术运算符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case "*":
textArea.append(
word + "\t3\t" + word + "\t算术运算符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case "/":
textArea.append(
word + "\t3\t" + word + "\t算术运算符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case "(":
textArea.append(
word + "\t2\t" + word + "\t分界符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case ")":
textArea.append(
word + "\t2\t" + word + "\t分界符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case "[":
textArea.append(
word + "\t2\t" + word + "\t分界符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case "]":
textArea.append(
word + "\t2\t" + word + "\t分界符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case "{":
textArea.append(
word + "\t2\t" + word + "\t分界符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case "}":
textArea.append(
word + "\t2\t" + word + "\t分界符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case ",":
textArea.append(
word + "\t2\t" + word + "\t分界符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
case ";":
textArea.append(
word + "\t2\t" + word + "\t分界符\t\t" + row_line[0] + "," + row_line[1] + '\n');
break;
default:
textArea.append(word + "\terror\t" + "-" + "\terror\t\t\t" + row_line[0] + ","
+ row_line[1] + '\n');
}
c = r.read();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
button_1.setBounds(627, 28, 107, 38);
frame.getContentPane().add(button_1);
}
static boolean find_key(String x) {
String[] k_table = { "int", "void", "main", "if", "else", "count" };
boolean flag = false;
for (int i = 0; i < k_table.length; i++) {
if (k_table[i].equals(x))
flag = true;
}
return flag;
}
static boolean isLetter(int x) {
if ((x >= 97 && x <= 122) || (x >= 81 && x <= 106))
return true;
else
return false;
}
static boolean isNumber(int x) {
if (x >= 48 && x <= 57)
return true;
else
return false;
}
}
在文本框中选择源程序文件的绝对路径,点击选择按钮后运行结果。如果程序中有错误,进行报错。
测试源程序文件中的程序段如下:
int main(void)
{int a(=1;
if(a>=1){
count<<a+2;%%}
else{
count<<a+3;}}