词法分析程序(Lexical Analyzer)要求:
- 从左至右扫描构成源程序的字符流
- 识别出有词法意义的单词(Lexemes)
- 返回单词记录(单词类别,单词本身)
- 滤掉空格
- 跳过注释
- 发现词法错误
程序结构:
输入:字符流(什么输入方式,什么数据结构保存)
处理:
–遍历(什么遍历方式)
–词法规则
输出:单词流(什么输出形式)
–二元组
单词类别:
1.标识符(10)
2.无符号数(11)
3.保留字(一词一码)
4.运算符(一词一码)
5.界符(一词一码)
scrollPane_1.setViewportView(textArea_1);
textArea_1.setLineWrap(true); //激活自动换行功能
textArea_1.setWrapStyleWord(true); // 激活断行不断字功能
//分别设置水平和垂直滚动条总是出现
scrollPane_1.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane_1.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
在此过程中也遇到过如何将文本内容显示到文本框里麻烦 解决函数如下:
private String readTxt(String path) {
if (path == null || "".equals(path)) {
return"";
}
StringBuffer sb = new StringBuffer();
File file = new File(path);
InputStreamReader read = null;
BufferedReader reader = null;
try {
read = new InputStreamReader(new FileInputStream(file), "gb2312");
reader = new BufferedReader(read);
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (read != null) {
try {
read.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return sb.toString();
}
执行时掉用该函数将文本框里的内容转化为字符串最后再显示到文本框里
将字符串写入到文件里函数如下:
publicvoid writefile(String path,String content,boolean append)
{
BufferedWriter bw;
File writefile;
boolean addStr = append;
writefile = new File(path);
if(writefile.exists()==false)
{
try {
writefile.createNewFile();
writefile = new File(path);
} catch (IOException e) {
// TODO自动生成的 catch 块
e.printStackTrace();
}
}
else
{
writefile.delete();
try {
writefile.createNewFile();
writefile = new File(path);
} catch (IOException e) {
// TODO自动生成的 catch 块
e.printStackTrace();
}
}
try {
FileWriter fw = new FileWriter(writefile,addStr);
bw = new BufferedWriter(fw);
fw.write(content);
fw.flush();
fw.close();
} catch (IOException e) {
// TODO自动生成的 catch 块
e.printStackTrace();
}
}
写完函数就是简单的调用问题了
最后是词法分析的原理了,由于函数代码较长,就不整理到报告里了!!!
该软件的执行功能及过程如下:
一、打开写有c语言程序或者Pascal程序的文件进行词法分析
过程如下:
点击打开文件按钮,进入选择文件界面如下:
选择cc.txt,确定后如下:
如上图,编辑框里已经显示出文件的内容
点击保存输入可对该词法分析的内容保存到一个自定义的文本里。过程如下
点击保存输出弹出选择输出文件保存路径及自定义文件名文本框
输入文件名后点击确定出现如下分析页面:
输出文本内容如下:
点击全部清空,两个文本框清空
二、对编辑框输入的内容直接进行分析,分析结果显示到分析框中,运行流程如下
在编辑框中输入C语言程序
点击词法分析:
点击全部清空:
完整代码如下:
package bianyi;
import java.awt.EventQueue;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.GroupLayout;
import javax.swing.JOptionPane;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JPanel;
import java.awt.Color;
import javax.swing.JLabel;
import java.awt.Font;
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.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JScrollPane;
import javax.swing.event.AncestorListener;
import javax.swing.event.AncestorEvent;
import javax.swing.JTextArea;
import javax.swing.JButton;
public class Fenci {
private JFrame frame;
public String path;
public String path1;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Fenci window = new Fenci();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Fenci() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setTitle("\u7F16\u8BD1\u539F\u7406\u8BCD\u6CD5\u5206\u6790");
frame.setBounds(100, 100, 802, 679);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
JPanel panel = new JPanel();
panel.setBackground(new Color(224, 255, 255));
GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
groupLayout.setHorizontalGroup(
groupLayout.createParallelGroup(Alignment.LEADING)
.addGroup(groupLayout.createSequentialGroup()
.addComponent(panel, GroupLayout.PREFERRED_SIZE, 781, GroupLayout.PREFERRED_SIZE)
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
groupLayout.setVerticalGroup(
groupLayout.createParallelGroup(Alignment.LEADING)
.addGroup(groupLayout.createSequentialGroup()
.addComponent(panel, GroupLayout.PREFERRED_SIZE, 631, GroupLayout.PREFERRED_SIZE)
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
JLabel label = new JLabel("\u5317\u4FE1\u79D1\u5927\u8BCD\u6CD5\u5206\u6790\u7B80\u6613\u8F6F\u4EF6");
label.setFont(new Font("隶书", Font.BOLD, 36));
JLabel label_1 = new JLabel("\u7F16\u8F91\u6846");
label_1.setFont(new Font("隶书", Font.BOLD, 26));
JLabel label_2 = new JLabel("\u5206\u6790\u6846");
label_2.setFont(new Font("隶书", Font.BOLD, 26));
JScrollPane scrollPane = new JScrollPane();
scrollPane.addAncestorListener(new AncestorListener() {
public void ancestorAdded(AncestorEvent arg0) {
}
public void ancestorMoved(AncestorEvent arg0) {
}
public void ancestorRemoved(AncestorEvent arg0) {
}
});
JScrollPane scrollPane_1 = new JScrollPane();
JButton button = new JButton("\u6253\u5F00\u6587\u4EF6");
button.setFont(new Font("隶书", Font.BOLD, 20));
JButton button_1 = new JButton("\u4FDD\u5B58\u8F93\u51FA");
button_1.setFont(new Font("隶书", Font.BOLD, 20));
JButton button_2 = new JButton("\u8BCD\u6CD5\u5206\u6790");
button_2.setFont(new Font("隶书", Font.BOLD, 20));
JButton button_3 = new JButton("\u5168\u90E8\u6E05\u7A7A");
button_3.setFont(new Font("隶书", Font.BOLD, 20));
GroupLayout gl_panel = new GroupLayout(panel);
gl_panel.setHorizontalGroup(
gl_panel.createParallelGroup(Alignment.TRAILING)
.addGroup(gl_panel.createSequentialGroup()
.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addContainerGap()
.addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, 350, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED, 27, Short.MAX_VALUE)
.addComponent(scrollPane_1, GroupLayout.PREFERRED_SIZE, 376, GroupLayout.PREFERRED_SIZE))
.addGroup(gl_panel.createSequentialGroup()
.addGap(37)
.addComponent(button)
.addGap(66)
.addComponent(button_1)
.addGap(71)
.addComponent(button_2, GroupLayout.PREFERRED_SIZE, 133, GroupLayout.PREFERRED_SIZE)
.addGap(37)
.addComponent(button_3, GroupLayout.PREFERRED_SIZE, 126, GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
.addGroup(gl_panel.createSequentialGroup()
.addGroup(gl_panel.createParallelGroup(Alignment.TRAILING, false)
.addGroup(gl_panel.createSequentialGroup()
.addGap(153)
.addComponent(label))
.addGroup(gl_panel.createSequentialGroup()
.addGap(136)
.addComponent(label_1)
.addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(label_2)))
.addGap(172))
);
gl_panel.setVerticalGroup(
gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addContainerGap()
.addComponent(label)
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
.addComponent(label_2)
.addComponent(label_1))
.addPreferredGap(ComponentPlacement.UNRELATED)
.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
.addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, 453, GroupLayout.PREFERRED_SIZE)
.addComponent(scrollPane_1, GroupLayout.PREFERRED_SIZE, 452, GroupLayout.PREFERRED_SIZE))
.addGap(18)
.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
.addComponent(button, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE)
.addComponent(button_1, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE)
.addComponent(button_2, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE)
.addComponent(button_3, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE))
.addGap(21))
);
final JTextArea textArea_1 = new JTextArea();
textArea_1.setFont(new Font("隶书", Font.BOLD, 20));
textArea_1.setBackground(new Color(245, 222, 179));
scrollPane_1.setViewportView(textArea_1);
textArea_1.setLineWrap(true); //激活自动换行功能
textArea_1.setWrapStyleWord(true); // 激活断行不断字功能
//分别设置水平和垂直滚动条总是出现
scrollPane_1.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane_1.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
final JTextArea textArea = new JTextArea();
textArea.setFont(new Font("隶书", Font.BOLD, 20));
textArea.setBackground(new Color(245, 222, 179));
scrollPane.setViewportView(textArea);
textArea.setLineWrap(true); //激活自动换行功能
textArea.setWrapStyleWord(true); // 激活断行不断字功能
//分别设置水平和垂直滚动条总是出现
scrollPane.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser filechooser = new JFileChooser();
int returnValue = filechooser.showOpenDialog(filechooser);
{
if(returnValue == JFileChooser.APPROVE_OPTION)
{
File file = filechooser.getSelectedFile();
path=file.getAbsolutePath();
String text=readTxt(path);
textArea.setText(text);
}
}
}
});
button_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser filechooser = new JFileChooser();
filechooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);//设置能选择文件和文件夹
filechooser.setMultiSelectionEnabled(false);//禁用多重选择
int returnValue = filechooser.showOpenDialog(filechooser);
{
if(returnValue == JFileChooser.APPROVE_OPTION)
{
File file = filechooser.getSelectedFile();
path1=file.getAbsolutePath();
String rename = JOptionPane.showInputDialog("请输入保存文件名字:");
String name=path1+"\\"+rename;
Suanfa.suanfa1(path, name);
String text=readTxt(name);
textArea_1.setText(text);
}
}
}
});
button_2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String intfile ="in.text";
String outfile="out.text";
String neirong=textArea.getText();
writefile(intfile,neirong,false);
Suanfa.suanfa1(intfile, outfile);
String text=readTxt(outfile);
textArea_1.setText(text);
}
});
button_3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textArea.setText("");
textArea_1.setText("");
}
});
panel.setLayout(gl_panel);
frame.getContentPane().setLayout(groupLayout);
}
private String readTxt(String path) {
if (path == null || "".equals(path)) {
return "";
}
StringBuffer sb = new StringBuffer();
File file = new File(path);
InputStreamReader read = null;
BufferedReader reader = null;
try {
read = new InputStreamReader(new FileInputStream(file), "gb2312");
reader = new BufferedReader(read);
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (read != null) {
try {
read.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return sb.toString();
}
public void writefile(String path,String content,boolean append)
{
BufferedWriter bw;
File writefile;
boolean addStr = append;
writefile = new File(path);
if(writefile.exists()==false)
{
try {
writefile.createNewFile();
writefile = new File(path);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
else
{
writefile.delete();
try {
writefile.createNewFile();
writefile = new File(path);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
try {
FileWriter fw = new FileWriter(writefile,addStr);
bw = new BufferedWriter(fw);
fw.write(content);
fw.flush();
fw.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
package bianyi;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
public class Suanfa {
public static void suanfa1(String infile,String outfile)
{
try {
FileInputStream f = new FileInputStream(infile);
BufferedReader dr = new BufferedReader(new InputStreamReader(f));
BufferedWriter output = new BufferedWriter(new FileWriter(outfile));
String line = "";
int cnt = 0;
while ((line = dr.readLine()) != null) {
cnt++;
if (cnt == 1) {
output.write(String.format("line : %d\r\n", cnt));
} else {
output.write(String.format("\r\n\r\nline : %d\r\n", cnt));
}
if (line.equals("")) {
output.write("空行~\r\n");
} else {
char[] strLine = line.toCharArray();
for (int i = 0; i < strLine.length; i++) {
char ch = strLine[i];
String token = "";
if (isAlpha(ch)) // 判断关键字和标识符
{
do {
token += ch;
i++;
if(i>=strLine.length) break;
ch = strLine[i];
} while (ch != '\0' && (isAlpha(ch) || isDigit(ch)));
--i; // 指针回退
if (isMatchKeyword(token.toString())) // 是关键字
{
output.write(String.format(
"%-10s\t<%s,1 关键字-->\r\n", token, token));
} else // 是标识符
{
if (symbol.isEmpty()
|| (!symbol.isEmpty() && !symbol
.containsKey(token))) {
symbol.put(token, symbol_pos);
output.write(String.format(
"%-10s\t<10 标识符,(%s,入口:%d)>\r\n",
token, token, symbol_pos));
symbol_pos++;
} else {
//%-10s\t<ERROR:标识符重复!>\r\n
output
.write(String
.format(
"%-10s\t<ERROR:标识符重复!>\r\n ",
token));
}
}
token = "";
} else if (isDigit(ch)) // 判断数字常量
{
int s = 1;
Boolean isfloat = false;
while (ch != '\0'
&& (isDigit(ch) || ch == '.' || ch == 'e' || ch == '-')) {
if (ch == '.' || ch == 'e')
isfloat = true;
int k;
for (k = 1; k <= 6; k++) {
char tmpstr[] = digitDFA[s].toCharArray();
if (ch != '#'
&& 1 == in_digitDFA(ch, tmpstr[k])) {
token += ch;
s = k;
break;
}
}
if (k > 6)
break;
i++;if(i>=strLine.length) break;
ch = strLine[i];
}
// if(ch) --i; // 指针回退
Boolean haveMistake = false;
if (s == 2 || s == 4 || s == 5) {
haveMistake = true;
} else // 1,3,6
{
if (!isOp(ch) || ch == '.')
haveMistake = true;
}
if (haveMistake) // 错误处理
{
while (ch != '\0' && ch != ',' && ch != ';'
&& ch != ' ') // 一直到“可分割”的字符结束
{
token += ch;
i++;if(i>=strLine.length) break;
ch = strLine[i];
}
output.write(String.format(
"%-10s\tERROR:请确保实常数输入正确!\r\n", token));
} else {
if (isfloat) {
output.write(String.format(
"%-10s\t<11实型常量,%s>\r\n", token,
token));
} else {
output.write(String.format(
"%-10s\t<11整型常量,%s>\r\n", token,
token));
}
}
--i;
token = "";
} else if (ch == '\'') // 识别字符常量,类似处理字符串常量。
{
int s = 0;
Boolean haveMistake = false;
String token1 = "";
token1 += ch;
while (s != 3) {
i++;if(i>=strLine.length) break;
ch = strLine[i];
if (ch == '\0') {
haveMistake = true;
break;
}
for (int k = 0; k < 4; k++) {
char tmpstr[] = stConDFA[s].toCharArray();
if (in_sinStConDFA(ch, tmpstr[k])) {
token1 += ch; // 为输出
if (k == 2 && s == 1) {
if (isEsSt(ch)) // 是转义字符
token = token + '\\' + ch;
else
token += ch;
} else if (k != 3 && k != 1)
token += ch;
s = k;
break;
}
}
}
if (haveMistake) {
output.write(String.format(
"%s\tERROR:字符常量引号不封闭\r\n", token1));
--i;
} else {
if (token.length() == 1) {
output.write(String.format(
"%-10s\t<字符常量,%s>\r\n", token1,
token));
} else if (token.length() == 2) {
if (isEsSt(token.charAt(1))
&& token.charAt(0) == '\\') {
output.write(String.format(
"%-10s\t<字符常量,%s>\r\n", token1,
token));
}
}
}
token = "";
} else if (ch == '"') // 处理字符串常量的
{
String token1 = "";
token1 += ch;
int s = 0;
Boolean haveMistake = false;
while (s != 3 ) {
i++;
if(i>=strLine.length-1)
{
haveMistake = true;
break;
}
ch = strLine[i];
if (ch == '\0') {
haveMistake = true;
break;
}
for (int k = 0; k < 4; k++) {
char tmpstr[] = stConDFA[s].toCharArray();
if (in_stConDFA(ch, tmpstr[k])) {
token1 += ch;
if (k == 2 && s == 1) {
if (isEsSt(ch)) // 是转义字符
token = token + '\\' + ch;
else
token += ch;
} else if (k != 3 && k != 1)
token += ch;
s = k;
break;
}
}
}
if (haveMistake) {
output.write(String.format(
"%-10s\tERROR:字符串常量引号不封闭\n", token1));
--i;
} else {
output
.write(String.format(
"%-10s\t<字符串常量,%s>\r\n",
token1, token));
}
token = "";
} else if (isOp(ch)) // 运算符,界符
{
token += ch;
if (isPlusEqu(ch)) // 后面可以用一个"="
{
i++;if(i>=strLine.length) break;
ch = strLine[i];
if (ch == '=')
token += ch;
else {
if (isPlusSame(strLine[i - 1])
&& ch == strLine[i - 1])
token += ch; // 后面可以用一个和自己一样的
else {
--i;
}
}
}
output.write(String.format("%-10s\t<%s,符号-->\r\n",
token, token));
token = "";
} else if (ch == '/') // 注释+除号: 注释只要识别出来就好。
{
token += ch;
i++;if(i>=strLine.length) break;
ch = strLine[i];
if (ch != '*' && ch != '/') // 除号处理
{
if (ch == '=')
token += ch; // /=
else {
--i; // 指针回退 // /
}
output.write(String.format("%-10s\t<%s,-->\n",
token, token));
token = "";
} else // 注释可能是‘//’也可能是‘/*’
{
Boolean haveMistake = false;
if (ch == '*') {
token += ch; // ch == '*'
int s = 2;
while (s != 4) {
i++;if(i>=strLine.length) break;
ch = strLine[i]; // 注意判断溢出!
if (ch == '\0') {
haveMistake = true;
break;
}
for (int k = 2; k <= 4; k++) {
char tmpstr[] = noteDFA[s]
.toCharArray();
if (1 == in_noteDFA(ch, tmpstr[k],
s)) {
token += ch;
s = k;
break;
}
}
}
}
else if(ch == '/') //这里就不用状态转移了...
{
int index = line.lastIndexOf("//");
String tmpstr=line.substring(index);
int tmpint = tmpstr.length();
for(int k=0;k<tmpint;k++)
{
i++;
}
token = tmpstr;
}
output.write(String.format("%-10s\t", token));
if (haveMistake) {
output.write("ERROR:注释没有封闭\r\n");
--i;
} else {
output.write(String.format("(注释:%s)\n",
token));
}
token = "";
}
}
else // 一些很奇怪的字符
{
if(ch != ' ' && ch != '\t')
{
output.write(String.format("%-10c ERROR:存在不合法字符\n",ch));
}
}
}
}
}
————————————————
版权声明:本文为CSDN博主「过客璇璇」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_36706878/article/details/79660671
本人能力有限,实现不了实验要求的功能,此代码是网上转载别人的。