简单实现词法分析器

说明#

  • 开发语言: java
  • 界面设计:采用eclipse的插件windowbuilder
  • 功能描述:统计行数和列数用于错误单词的定位,如果发现错误则报告出错。删除空格类字符,包括回车、制表符空格,按拼写单词(关键字、标识符、常数、运算符、关系运算符、分界符号),并用(内码,属性)二元式表示。

主程序流程#


源程序存储在文件中,用一个字符串word存储识别的字符,通过read()函数读入文件中一个字符。
如果识别到空格,制表符等,直接通过read()读取下一个字符。
如果识别到字母,进入状态1的判断分支,然后读取下一个字符进行判断,如果为数字和字母则连接到word后,再读取下一个。直到结束后判断其是否为关键字或标识符。
如果识别到运算符或分割符,通过switch语句进行相应的判断,其余基本操作与上图和描述相似。

代码#

Copy
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; } }

在文本框中选择源程序文件的绝对路径,点击选择按钮后运行结果。如果程序中有错误,进行报错。

测试源程序文件中的程序段如下:

Copy
int main(void) {int a(=1; if(a>=1){ count<<a+2;%%} else{ count<<a+3;}}
posted @   启林O_o  阅读(243)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示
CONTENTS