📄 analyzer.java
字号:
/*
* 吕渊 200532580144
* 使用工具:eclipse
* Java SE 6
*/
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.*;
public class Analyzer extends JApplet {
//图标
ImageIcon openIcon = new ImageIcon("Icon/Open.png"),
saveIcon = new ImageIcon("Icon/Save.png"),
undoIcon = new ImageIcon("Icon/Undo.png"),
redoIcon = new ImageIcon("Icon/Redo.png"),
colorIcon = new ImageIcon("Icon/Color.png"),
deleteAllIcon = new ImageIcon("Icon/Delete.png"),
lexicalIcon = new ImageIcon("Icon/Lexical.png"),
syntaxIcon = new ImageIcon("Icon/Syntax.png");
//菜单项
private JMenuItem jmiOpen = new JMenuItem("打开文件", openIcon);
private JMenuItem jmiSaveInput = new JMenuItem("输入内容另存为...", saveIcon);
private JMenuItem jmiSaveResult = new JMenuItem("分析结果另存为...", saveIcon);
private JMenuItem jmiExit = new JMenuItem("退出");
private JMenuItem jmiUndo = new JMenuItem("撤消", undoIcon);
private JMenuItem jmiRedo = new JMenuItem("重复", redoIcon);
private JMenuItem jmiForeground = new JMenuItem("前景色", colorIcon);
private JMenuItem jmiBackground = new JMenuItem("背景色", colorIcon);
protected JMenuItem lexicalAnalyzer = new JMenuItem("词法分析", lexicalIcon);
protected JMenuItem syntaxAnalyzer= new JMenuItem("语法分析", syntaxIcon);
protected JMenuItem jMenuClean = new JMenuItem("清空", deleteAllIcon);
protected JMenu jMenuExe = new JMenu("运行(D)");//菜单项
protected JMenuBar jMenuBar = new JMenuBar();//菜单
private JLabel jlblStatus = new JLabel();//信息栏
private JFileChooser jFileChooser = new JFileChooser(new File("."));//文件对话框
private JTextArea lineNoArea = new JTextArea();//显示行号
protected JTextArea jta = new JTextArea();//输入区域
protected DefaultListModel listModel = new DefaultListModel();
protected JList jlst = new JList(listModel);//输出区域
JSplitPane center = new JSplitPane();//中央区域
public ArrayList<Integer> tokenStart = new ArrayList<Integer>();//对应输出位置
public ArrayList<Integer> tokenEnd = new ArrayList<Integer>();//对应输出位置
boolean change = true;//输入文本改变
int clickCount = 1;//双击JList次数
LinkedList<String> buffer = new LinkedList<String>();//输入内容缓冲
final int maxSize = 100;//缓冲存储上限
int index = 0;//当前显示内容在缓冲中的索引
boolean flag = false;//是否使用快捷键控制索引显示
public Analyzer() {
buffer.add("");
//菜单
JMenu jMenuFile = new JMenu("文件(F)");
jMenuFile.setMnemonic('F');
jMenuFile.add(jmiOpen);
jMenuFile.addSeparator();
jMenuFile.add(jmiSaveInput);
jMenuFile.add(jmiSaveResult);
jMenuFile.addSeparator();
jMenuFile.add(jmiExit);
JMenu jMenuEdit = new JMenu("编辑(E)");
jMenuEdit.setMnemonic('E');
jMenuEdit.add(jmiUndo);
jMenuEdit.add(jmiRedo);
JMenu jMenuShow = new JMenu("显示(S)");
jMenuShow.setMnemonic('S');
jMenuShow.add(jmiForeground);
jMenuShow.add(jmiBackground);
jMenuExe.setMnemonic('D');
jMenuExe.add(lexicalAnalyzer);
jMenuExe.addSeparator();
jMenuExe.add(syntaxAnalyzer);
jMenuExe.addSeparator();
jMenuExe.add(jMenuClean);
jMenuBar.add(jMenuFile);
jMenuBar.add(jMenuEdit);
jMenuBar.add(jMenuShow);
jMenuBar.add(jMenuExe);
setJMenuBar(jMenuBar);
//输入文本区及行号显示区域属性及滚动
jta.setEditable(true);
jta.setFont(new Font(Font.SERIF, Font.PLAIN, 15));
jta.setForeground(Color.BLUE);
jta.setTabSize(1);
lineNoArea.setFont(new Font(Font.SERIF, Font.PLAIN, 15));
lineNoArea.setEditable(false);
lineNoArea.setText("1");
lineNoArea.setBackground(Color.LIGHT_GRAY);
JPanel jplInput = new JPanel(new BorderLayout());
jplInput.add(lineNoArea, BorderLayout.WEST);
jplInput.add(jta, BorderLayout.CENTER);
JScrollPane inputScrollPane = new JScrollPane(jplInput);
inputScrollPane.setBorder(new TitledBorder(" 请输入 "));
//JList输出区域及滚动
jlst.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
jlst.setFocusable(false);
JScrollPane outputScrollPane = new JScrollPane(jlst);
outputScrollPane.setBorder(new TitledBorder(" 分析结果 "));
JPanel jplRight = new JPanel(new GridLayout(2,1));
jplRight.add(inputScrollPane);
jplRight.add(outputScrollPane);
center = new JSplitPane(1,
new JScrollPane(new JTree(new DefaultMutableTreeNode("Syntax Tree"))), jplRight);
center.setContinuousLayout(true);
center.setOneTouchExpandable(true);
//添加信息栏及中央区域
getContentPane().add(jlblStatus, BorderLayout.SOUTH);
getContentPane().add(center, BorderLayout.CENTER);
//操作快捷键
lexicalAnalyzer.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, ActionEvent.ALT_MASK));
jmiOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
jMenuClean.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.CTRL_MASK));
syntaxAnalyzer.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, ActionEvent.CTRL_MASK));
jmiUndo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
jmiRedo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, ActionEvent.CTRL_MASK));
//以下为监听器注册及实现
/** 输入文本区内容变化响应事件*/
jta.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {}
/** 删除操作*/
public void removeUpdate(DocumentEvent e) {
clickCount = 0;
change = true;
showLineNo();//显示行号
if (flag == false) {
if (index < buffer.size()-1)
buffer = new LinkedList<String>(buffer.subList(0, index+1));
buffer.add(jta.getText());
if (buffer.size() > maxSize) buffer.removeFirst();
else index++;
}
}
/** 输入操作*/
public void insertUpdate(DocumentEvent e) {
clickCount = 0;
change = true;
showLineNo();//显示行号
if (flag == false) {
if (index < buffer.size()-1)
buffer = new LinkedList<String>(buffer.subList(0, index+1));
buffer.add(jta.getText());
if (buffer.size() > maxSize) buffer.removeFirst();
else index++;
}
}
});
/** 对JList进行双击的响应事件*/
jlst.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (!change) {
try {
int select = jlst.getSelectedIndex();
int start = tokenStart.get(select);
int end = tokenEnd.get(select);
if (start >=0 ) jta.select(start, end);
else if (start == -2) {
int endT = tokenStart.size();
for (int i = select+1; i < endT; i++)
if (tokenStart.get(i) == -2) {
endT = i;
break;
}
clickCount++;
if (clickCount == endT - select) clickCount = 1;
start = tokenStart.get(select + clickCount);
end = tokenEnd.get(select + clickCount);
if (start != -3) jta.select(start, end);
}
}
catch (Exception ex) {}
}
}
});
/** JList改变选中的响应事件*/
jlst.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent lse) {
clickCount =0;
}
});
/** 读入文件*/
jmiOpen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
open();
showLineNo();
}
});
/** 保存输入*/
jmiSaveInput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
save(1);
}
});
/** 保存结果*/
jmiSaveResult.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
save(2);
}
});
/** 结束程序*/
jmiExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.exit(0);
}
});
/** 撤消输入*/
jmiUndo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (index > 0) {
flag = true;
index--;
jta.setText(buffer.get(index));
flag = false;
}
}
});
/** 重复输入*/
jmiRedo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (index < buffer.size()-1) {
flag = true;
index++;
jta.setText(buffer.get(index));
flag = false;
}
}
});
/** 设置前景色*/
jmiForeground.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Color selectedColor =
JColorChooser.showDialog(null, "选择前景色",
jta.getForeground());
if (selectedColor != null)
jta.setForeground(selectedColor);
}
});
/** 设置背景色*/
jmiBackground.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Color selectedColor =
JColorChooser.showDialog(null, "选择背景色",
jta.getForeground());
if (selectedColor != null)
jta.setBackground(selectedColor);
}
});
/** 词法分析*/
lexicalAnalyzer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
center.setLeftComponent(new JScrollPane(
new JTree(new DefaultMutableTreeNode("Syntax Tree"))));
LexicalAnalyze lexical = new LexicalAnalyze(jta.getText());
if (lexical.toArrayList().isEmpty())
JOptionPane.showMessageDialog (null, "请输入!",
"Notice", JOptionPane.INFORMATION_MESSAGE);
else {
tokenStart = lexical.tokenStart;
tokenEnd = lexical.tokenEnd;
listModel.clear();
for(String value: lexical.toArrayList())
listModel.addElement(value);
change = false;
}
}
});
/** 语法分析*/
syntaxAnalyzer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (jta.getText().trim().equals("")){
JOptionPane.showMessageDialog (null, "请输入!",
"Notice", JOptionPane.INFORMATION_MESSAGE);
}
else {
SyntaxAnalyze syntax = new SyntaxAnalyze(jta.getText());
listModel.clear();
center.setLeftComponent(new JScrollPane(
new JTree(new DefaultMutableTreeNode("Syntax Tree"))));
for(String value: syntax.toArrayList())
listModel.addElement(value);
change = false;
if (syntax.lexicalError == true) {
JOptionPane.showMessageDialog (null, "词法分析发现错误!",
"Notice", JOptionPane.INFORMATION_MESSAGE);
tokenStart = syntax.tokenStart;
tokenEnd = syntax.tokenEnd;
}
else if (syntax.syntaxError == true) {
JOptionPane.showMessageDialog (null, "含有语法错误!",
"Notice", JOptionPane.INFORMATION_MESSAGE);
tokenStart = syntax.tokenErrorStart;
tokenEnd = syntax.tokenErrorEnd;
}
else {
center.setLeftComponent(new JScrollPane(
new JTree(new DefaultTreeModel(syntax.syntaxTree))));
tokenStart = syntax.tokenRightStart;
tokenEnd = syntax.tokenRightEnd;
}
}
}
});
/** 清空*/
jMenuClean.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
change = true;
lineNoArea.setText("1");
jta.setText(null);
center.setLeftComponent(new JScrollPane(
new JTree(new DefaultMutableTreeNode("Syntax Tree"))));
}
});
}
/** 显示行号*/
private void showLineNo() {
String lineNo = "";
for (int i = 1; i <= jta.getLineCount(); i++)
if (i == 1)lineNo += "" + 1;
else lineNo += "\n" + i;
lineNoArea.setText(lineNo);
}
/** 打开文件*/
private void open() {
if (jFileChooser.showOpenDialog(this) ==
JFileChooser.APPROVE_OPTION)
open(jFileChooser.getSelectedFile());
}
private void open(File file) {
try {
jta.setText(null);
BufferedReader input = new BufferedReader(
new FileReader(file));
String line;
while ((line = input.readLine()) != null) {
jta.append(line + "\n");
}
jta.setText(jta.getText().trim());
input.close();
jlblStatus.setText(file.getName() + " 已打开");
}
catch (IOException ex) {
jlblStatus.setText(file.getName() + " 打开失败!");
}
}
/** 保存*/
private void save(int x) {
if (jFileChooser.showSaveDialog(this) ==
JFileChooser.APPROVE_OPTION) {
save(jFileChooser.getSelectedFile(), x);
}
}
private void save(File file, int x) {
try {
BufferedWriter output =
new BufferedWriter(new FileWriter(file));
if (x == 1) output.write(jta.getText());
else {
String result = "";
for(int i = 0; i < jlst.getModel().getSize(); i++)
result += jlst.getModel().getElementAt(i) + "\n";
output.write(result);
}
output.close();
jlblStatus.setText(file.getName() + " 已保存 ");
}
catch (IOException ex) {
jlblStatus.setText(file.getName() + " 保存失败! ");
}
}
public static void main(String[] args) {
Analyzer applet = new Analyzer();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(3);
frame.setTitle("CMM Analyzer Beta4");
frame.getContentPane().add(applet, BorderLayout.CENTER);
applet.init();
applet.start();
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setSize(d.width*4/5,d.height*4/5);
frame.setLocation(d.width / 10, d.height / 10);
frame.setVisible(true);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -