?? 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 + -