一、实验目的
通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示).
二、实验准备工作
1、词法分析器的功能和输出格式
词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。本实验中,采用的是一类符号一种别码的方式。
2、Java程序语言的单词符号的种别.
识别java的关键字:
boolean,byte,char,double,false,float,int,long,new,null,short,true,void,instanceof,break,case,catch,continue,default,do,else,for,if,return,switch,try,while,finally,throw,this,super,abstract,final,namtive,private,protected,public ,static,synchronized,transient,volatile,class,extends,implements,interface,package,import,throws;单词识别码为1;
标识符:标识符必须是以字母,下划线,美元符号开始,单词识别码为2;
常量:常数为无符号整形数;单词种别码为3;
运算符:+、-、*、/、=、>、<、>=、<=、==、!= 、++、--、%、&&、||、!单词识别码为4;
分隔符:,、;、{、}、(、); 单词种别码为5
4.单元模块
//业务代码:
import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.Vector; public class JavaAnaylsis { private static String[] keyword = { "boolean", "byte", "char", "double", "false", "float", "int", "long", "new", "null", "short", "true", "void", "instanceof", "break", "case", "catch", "continue", "default", "do", "else", "for", "if", "return", "switch", "try", "while", "finally", "throw", "this", "super", "abstract", "final", "namtive", "private", "protected", "public", "static", "synchronized", "transient", "volatile", "class", "extends", "implements", "interface", "package", "import", "throws" }; static String string; static String wordString; static Vector vc; public JavaAnaylsis(String str) throws Exception { File inFile = new File(str); if (inFile.exists()) { System.out.println("文件打开成功!!!"); try { FileReader reader = new FileReader(inFile); BufferedReader br = new BufferedReader(reader); vc = new Vector(); while ((string = br.readLine()) != null) { // 预处理 将一行的字符串连续的空格换成一个空格或将连续的制表符换成一个空格 string = string.trim().replace(" +", " ") .replaceAll("\\t+", " "); // System.out.println(string); judgement(); } br.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { System.out.println("文件打开失败"); } } /* * 判断读入的字符是否为字母 */ public static boolean isLetter(char c) { if ((c >= 'a' && c <= 'z') || (c > +'A' && c <= 'Z')) { return true; } else return false; } /* * 判断读入的字符是否为数字 */ public static boolean isDigit(char c) { if (c >= '0' && c <= '9') { return true; } else return false; } /* * 判断是否为关键字 */ public static boolean isKey(String ss) { int flag = 0; for (int i = 0; i < keyword.length; i++) { if (ss.equals(keyword[i])) { flag = 1; break; } } if (flag == 1) { return true; } return false; } /* * 判断是否为运算符 */ public static boolean isSpilt(char ch) { if (ch == '+' || ch == '-' || ch == '|' || ch == '=' || ch == '&') { return true; } else return false; } /* * 判断输入的字符并输出单词符号 */ public static void judgement() throws Exception { char ch = 0; int m = 0; String str = null; for (int i = 0; i < string.length(); i++) { switch (m) { case 0: ch = string.charAt(i); // 判断是否为运算符使用超前搜索 if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=' || ch == '>' || ch == '<' || ch == '!' || ch == '%' || ch == '|') { str = ""; str += ch; if (ch == '+' || ch == '-' || ch == '>' || ch == '<' || ch == '!' || ch == '|' || ch == '&') { ch = string.charAt(i + 1); // 对下一个字符进行判断是否为运算符 if (isSpilt(ch)) { str += ch; m = 4; } else { ch = string.charAt(i - 1); // 不是运算符则进行回退操作 m = 4; } } } // 判断是否为界符 else if (ch == ',' || ch == ';' || ch == '{' || ch == '}' || ch == '(' || ch == ')') { m = 5; } // 判断是否数字 else if (isDigit((ch = string.charAt(i)))) { str = ""; str += ch; m = 3; } // 判断是否字母 else if (isLetter(ch = string.charAt(i))) { str = ""; str += ch; m = 2; } // 判断是否下划线或美元符号 else if (ch == '_' || ch == '$') { str = ""; str += ch; m = 2; } else { } break; case 4: i--; System.out.println(("( 4 " + "“ " + str + " ” )")); wordString = ("( 4 " + "“ " + str + " ” )"); vc.add(wordString); m = 0; break; case 5: i--; System.out.println(("( 5 " + "“ " + ch + " ” )")); wordString = ("( 5 " + "“ " + ch + " ” )"); vc.add(wordString); m = 0; break; case 2: if (isLetter(ch = string.charAt(i))) { str += ch; } else { if (isKey(str)) { System.out.println("( 1 " + "“ " + str + " ” )"); wordString = ("( 1 " + "“ " + str + " ” )"); vc.add(wordString); } else { System.out.println(("( 2 " + "“ " + str + " ” )")); wordString = ("( 2 " + "“ " + str + " ” )"); vc.add(wordString); } i--; m = 0; } break; case 3: if (isDigit((ch = string.charAt(i)))) { str += ch; } else { System.out.println("( 3 " + "“ " + str + " ” )"); wordString = "( 3 " + "“ " + str + " ” )"; vc.add(wordString); i--; m = 0; } break; } } } public static Vector getVector() { return vc; } }
//界面代码:
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Iterator; import java.util.Vector; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.WindowConstants; public class JavaFrame extends JFrame { private JTextArea textArea, textArea2; private JButton anaylisbButton; static String filename; static Vector vcVector; public JavaFrame() { super(); setTitle("Java词法分析器"); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // 设置"关闭"按钮处理事件 Toolkit tool = Toolkit.getDefaultToolkit(); // 创建工具栏 Dimension screenSize = tool.getScreenSize(); // 获得屏幕大小 setSize(800, 500); // 设置窗体大小 setLocation((screenSize.width - getWidth()) / 2, (screenSize.height - getHeight()) / 2); JPanel scollJPanel = (JPanel) getContentPane(); // 获得内容面板 setResizable(false); // 设置最大化按钮不能用 JMenuBar menuBar = createMenu(); // 设置菜单项 this.setJMenuBar(menuBar); // textArea=new TextArea(); JScrollPane jScrollPane = new JScrollPane(textArea = new JTextArea( "源代码:" + "\n", 1000, 35)); JScrollPane jScrollPane2 = new JScrollPane(textArea2 = new JTextArea( "词法分析后:" + "\n", 1000, 35)); scollJPanel.add(jScrollPane2, BorderLayout.EAST); scollJPanel.add(jScrollPane, BorderLayout.WEST); JPanel buttonJPanel = new JPanel(); anaylisbButton = new JButton("开始词法分析"); anaylisbButton.addActionListener(new start()); buttonJPanel.add(anaylisbButton); scollJPanel.add(buttonJPanel, "South"); setVisible(true); } private JMenuBar createMenu() { // TODO Auto-generated method stub JMenuBar menuBar = new JMenuBar();// 初始化菜单栏 JMenu menu = new JMenu(" 文件 "); JMenu menu2 = new JMenu(" 窗口 "); menu2.setEnabled(false); JMenu menu3 = new JMenu(" 帮助 "); menu3.setEnabled(false); JMenu menu4 = new JMenu(" 格式 "); menu4.setEnabled(false); JMenuItem meun1 = new JMenuItem(" 打开 "); JMenuItem meun2 = new JMenuItem(" 保存 "); JMenuItem meun3 = new JMenuItem(" 另存为 "); JMenuItem meun4 = new JMenuItem(" 退出 "); meun4.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub JavaFrame.this.dispose(); } }); meun1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub // 初始化文件选择框 textArea.setText("源代码:" + "\n"); JFileChooser fDialog = new JFileChooser("d:/"); // 设置文件选择框的标题 fDialog.setDialogTitle("请选择文件"); // 弹出选择框 int returnVal = fDialog.showOpenDialog(null); // 如果是选择了文件 if (JFileChooser.APPROVE_OPTION == returnVal) { // 打印出文件的路径,你可以修改位 把路径值 写到 textField 中 System.out.println(fDialog.getSelectedFile()); filename = fDialog.getSelectedFile().toString(); File inFile = new File(filename); try { FileReader reader = new FileReader(inFile); BufferedReader br = new BufferedReader(reader); String strings; while ((strings = br.readLine()) != null) { textArea.append(strings + "\n"); } br.close(); } catch (Exception e) { // TODO: handle exception } } } }); meun2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub JFileChooser jf = new JFileChooser("d:/"); int value = jf.showSaveDialog(null); if (value == JFileChooser.APPROVE_OPTION) { // 判断窗口是否点的是打开或保存 File getPath = jf.getSelectedFile(); // 取得路径 System.out.println(getPath); try { FileWriter fWriter = new FileWriter(getPath); BufferedWriter out = new BufferedWriter(fWriter); Iterator iterator = vcVector.iterator(); while (iterator.hasNext()) { // textArea2.append(iterator.next().toString()+"\n"); out.write(iterator.next().toString()); out.newLine(); } out.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { // 没有选择,即点了窗口的取消 } } }); menu.add(meun1); menu.add(meun2); menu.add(meun3); menu.addSeparator(); menu.add(meun4); menuBar.add(menu); menuBar.add(menu2); menuBar.add(menu4); menuBar.add(menu3); return menuBar; } private class start implements ActionListener { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub textArea2.setText("词法分析后:" + "\n"); try { new JavaAnaylsis(filename); vcVector = new Vector(); vcVector = JavaAnaylsis.getVector(); Iterator iterator = vcVector.iterator(); while (iterator.hasNext()) { textArea2.append(iterator.next().toString() + "\n"); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { new JavaFrame(); } }
实验总结:我在编程的过程中一共花了一天的时间,而在纸上设计就大概花了半个小时吧,花了半天的时间去上机输入和调试,在这次的实验过程中花了近半天的时间去思考问题,也遇到了编程的过程的问题,主要在逻辑错误问题较多,开始时我以为我的逻辑无错误,还以为是其他的问题,最后静下来理清自己的逻辑,还是发现了出现了较严重的逻辑问题,通过在网上查阅相关的资料来解决问题.到最后还是基本完成了这个java词法分析器的实验.对于我自己的程序我认为还是可以应对基本的词法分析,能编出这个程序我感觉到有那么一点成就感,这次的实验让我进一步地熟悉了java语言,提高了我的编程思维能力,增大了我的兴趣爱好,巩固了我的知识.还有好......