Java 實現《編譯原理》簡單詞法分析功能
Java 實現《編譯原理》簡單詞法分析功能
簡易詞法分析功能
要求及功能
(1)讀取一個 txt 程式檔案(最後的 # 作為結束標誌,不可省去)
{
int a, b;
a = 10;
if(a>=1){
b = a + 20;
}
}
(2)詞法識別分析表
單詞類別|單詞自身值|內部編碼
-|-|-
關鍵字| int、for、while、do、return、break、continue| 1
識別符號| 除關鍵字外的以字母開頭,後跟字母、數字的字元序列| 2
常數| 無符號整型數| 3
運算子| +、-、*、/、>、<、=、>=、<=、!=| 4
換行符|\n| 6
(3)輸出結果:
(5,{)
(6,\n)
(1,int)
(2,a)
(5,,)
(2,b)
(5,;)
(6,\n)
(2,a)
(4,=)
(3,10)
(5,;)
(6,\n)
(2,if)
(5,()
(2,a)
(4,>=)
(3,1)
(5,))
(5,{)
(6,\n)
(2,b)
(4,=)
(2,a)
(4,+)
(3,20)
(5,;)
(6,\n)
(5,})
(6,\n)
(5,})
(6,\n)
(0,#)
並儲存成新的 txt 檔案
程式設計實現
(1)程式檔案目錄:
(2)Word.java 檔案:
package com.java997.analyzer.lexical; /** * <p> * 表示識別後的詞實體類 * * @author XiaoPengwei * @since 2019-06-13 */ public class Word { /** * 種別碼 */ private int typeNum; /** * 掃描得到的詞 */ private String word; public int getTypeNum() { return typeNum; } public void setTypeNum(int typeNum) { this.typeNum = typeNum; } public String getWord() { return word; } public void setWord(String word) { this.word = word; } }
(3)CodeScanner.java 檔案:
package com.java997.analyzer.lexical;
/**
* <p>
* 字元掃描
*
* @author XiaoPengwei
* @since 2019-06-13
*/
public class CodeScanner {
private static String _KEY_WORD_END = "end string of string";
private int charNum = 0;
private Word word;
private char[] input = new char[255];
private char[] token = new char[255];
private int p_input = 0;
private int p_token = 0;
private char ch;
/**
* 關鍵字陣列
*/
private String[] rwtab = {"int", "if", "while", "do", "return", "break", "continue", _KEY_WORD_END};
/**
* 邏輯運算陣列
*/
private String[] logicTab = {"==",">=","<=","!=", _KEY_WORD_END};
public CodeScanner(char[] input) {
this.input = input;
}
/**
* 取下一個字元
*
* @return
*/
public char m_getch() {
if (p_input < input.length) {
ch = input[p_input];
p_input++;
}
return ch;
}
/**
* 如果是識別符號或者空白符就取下一個字元
*/
public void getbc() {
while ((ch == ' ' || ch == '\t') && p_input < input.length) {
ch = input[p_input];
p_input++;
}
}
/**
* 把當前字元和原有字串連線
*/
public void concat() {
token[p_token] = ch;
p_token++;
token[p_token] = '\0';
}
/**
* 回退一個字元
*/
public void retract() {
p_input--;
}
/**
* 判斷是否為字母
*
* @return boolean
* @author XiaoPengwei
*/
public boolean isLetter() {
return ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z';
}
/**
* 判斷是否為數字
*
* @return boolean
* @author XiaoPengwei
*/
public boolean isDigit() {
return ch >= '0' && ch <= '9';
}
/**
* 檢視 token 中的字串是否是關鍵字,是的話返回關鍵字種別編碼,否則返回 2
*
* @return
*/
public int isKey() {
int i = 0;
while (rwtab[i].compareTo(_KEY_WORD_END) != 0) {
if (rwtab[i].compareTo(new String(token).trim()) == 0) {
return i + 1;
}
i++;
}
return 2;
}
/**
* 可能是邏輯預算字元
*
* @return
*/
public Boolean isLogicChar() {
return ch == '>' || ch == '<'|| ch == '='|| ch == '!';
}
/**
* 檢視 token 中的字串是否是邏輯運算子,是的話返回關鍵字種別編碼,否則返回 2
*
* @return
*/
public int isLogicTab() {
int i = 0;
while (logicTab[i].compareTo(_KEY_WORD_END) != 0) {
if (logicTab[i].compareTo(new String(token).trim()) == 0) {
return i + 1;
}
i++;
}
return 4;
}
/**
* 能夠識別換行,單行註釋和多行註釋的
* 換行的種別碼設定成30
* 多行註釋的種別碼設定成31
*
* @return
*/
public Word scan() {
token = new char[255];
Word myWord = new Word();
myWord.setTypeNum(10);
myWord.setWord("");
p_token = 0;
m_getch();
getbc();
if (isLetter()) {
while (isLetter() || isDigit()) {
concat();
m_getch();
}
retract();
myWord.setTypeNum(isKey());
myWord.setWord(new String(token).trim());
return myWord;
} else if (isLogicChar()) {
while (isLogicChar()) {
concat();
m_getch();
}
retract();
myWord.setTypeNum(4);
myWord.setWord(new String(token).trim());
return myWord;
} else if (isDigit()) {
while (isDigit()) {
concat();
m_getch();
}
retract();
myWord.setTypeNum(3);
myWord.setWord(new String(token).trim());
return myWord;
} else {
switch (ch) {
//5
case ',':
myWord.setTypeNum(5);
myWord.setWord(",");
return myWord;
case ';':
myWord.setTypeNum(5);
myWord.setWord(";");
return myWord;
case '{':
myWord.setTypeNum(5);
myWord.setWord("{");
return myWord;
case '}':
myWord.setTypeNum(5);
myWord.setWord("}");
return myWord;
case '(':
myWord.setTypeNum(5);
myWord.setWord("(");
return myWord;
case ')':
myWord.setTypeNum(5);
myWord.setWord(")");
return myWord;
//4
case '=':
myWord.setTypeNum(4);
myWord.setWord("=");
return myWord;
case '+':
myWord.setTypeNum(4);
myWord.setWord("+");
return myWord;
case '-':
myWord.setTypeNum(4);
myWord.setWord("-");
return myWord;
case '*':
myWord.setTypeNum(4);
myWord.setWord("*");
return myWord;
case '/':
myWord.setTypeNum(4);
myWord.setWord("/");
return myWord;
case '\n':
myWord.setTypeNum(6);
myWord.setWord("\\n");
return myWord;
case '#':
myWord.setTypeNum(0);
myWord.setWord("#");
return myWord;
default:
concat();
myWord.setTypeNum(-1);
myWord.setWord("ERROR INFO: WORD = \"" + new String(token).trim() + "\"");
return myWord;
}
}
}
}
(4)MainAnalyzer.java 檔案:
package com.java997.analyzer.lexical;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Scanner;
/**
* <p>
* 執行主程式
*
* @author XiaoPengwei
* @since 2019-06-13
*/
public class MainAnalyzer {
private File inputFile;
private File outputFile;
private String fileContent;
private ArrayList<Word> list = new ArrayList<>();
/**
* 構造方法
*
* @param input
* @param output
* @author XiaoPengwei
*/
public MainAnalyzer(String input, String output) {
//例項化輸入檔案
inputFile = new File(input);
//例項化輸出檔案
outputFile = new File(output);
}
/**
* 從指定的 txt 檔案中讀取源程式檔案內容
*
* @return java.lang.String
*/
public String getContent() {
StringBuilder stringBuilder = new StringBuilder();
try (Scanner reader = new Scanner(inputFile)) {
while (reader.hasNextLine()) {
String line = reader.nextLine();
stringBuilder.append(line + "\n");
System.out.println(line);
}
System.out.println("Successful reading of files:" + inputFile.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return fileContent = stringBuilder.toString();
}
/**
* 然後掃描程式,在程式結束前將掃描到的詞新增到 list 中
* 最後把掃描結果儲存到指定的檔案中
*
* @param fileContent
* @return void
*/
public void analyze(String fileContent) {
int over = 1;
Word word = new Word();
//呼叫掃描程式
CodeScanner scanner = new CodeScanner(fileContent.toCharArray());
System.out.println("The result:");
while (over != 0) {
word = scanner.scan();
System.out.println("(" + word.getTypeNum() + "," + word.getWord() + ")");
list.add(word);
over = word.getTypeNum();
}
saveResult();
}
/**
* 將結果寫入到到指定檔案中
* 如果檔案不存在,則建立一個新的檔案
* 用一個 foreach 迴圈將 list 中的項變成字串寫入到檔案中
*/
public void saveResult() {
//建立檔案
if (!outputFile.exists()) {
try {
outputFile.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
}
//寫入檔案
try (Writer writer = new FileWriter(outputFile)) {
for (Word word : list) {
writer.write("(" + word.getTypeNum() + " ," + word.getWord() + ")\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//注意輸入檔案路徑/名稱必須對, 輸出檔案可以由程式建立
MainAnalyzer analyzer = new MainAnalyzer("D:\\analyzer\\src\\main\\java\\com\\java997\\analyzer\\lexical\\input.txt", "D:\\analyzer\\src\\main\\java\\com\\java997\\analyzer\\lexical\\output.txt");
analyzer.analyze(analyzer.getContent());
}
}
(5)input.txt 檔案:
{
int a, b;
a = 10;
if(a>=1){
b = a + 20;
}
}
#
執行測試
相關推薦
Java 實現《編譯原理》簡單詞法分析功能
Java 實現《編譯原理》簡單詞法分析功能 簡易詞法分析功能 要求及功能 (1)讀取一個 txt 程式檔案(最後的 # 作為結束標誌,不可省去) { int a, b; a = 10; if(a>=1){ b = a + 20; } } (2)詞法識別分析表 單詞類別|單詞自身值
編譯原理實驗---詞法分析
轉自 一、實驗概述 1.1、實驗要求 選擇計算機高階語言之一-----C語言,運用恰當的此法分析技術線路,設計和實現其對應的詞法分析器。 建議:程式語言,選擇《計算機程式設計》課程所採用的語言。 提示:技術線路選擇如下兩種之一: 正則式→NFA→DFA→
編譯原理-1-詞法分析
在上一篇文章中,大致介紹了下編譯過程。從這篇文章開始,我們就開始逐步慢慢深入的學習編譯過程中的步驟。今天我們就來具體看看詞法分析到底是怎麼回事。 ========================華麗麗的分割線=================================
編譯原理之詞法分析、語法分析、語義分析
詞法分析(Lexical analysis或Scanning)和詞法分析程式(Lexical analyzer或Scanner) 詞法分析階段是編譯過程的第一個階段。這個階段的任務是從左到右一個字元一個字元地讀入源程式,即對構成源程式的字元流進行掃描然後根據構詞規則識別單詞(也稱單詞符號或符號)。詞法
編譯原理實驗:實驗一 簡單詞法分析程序設計(必修)(Python實現)
it is 括號 ali 鍵盤輸入 優化 沒有 mce constant 是否 一、實驗目的 了解詞法分析程序的基本構造原理,掌握詞法分析程序的手工構造方法。 二、實驗內容 1、了解編譯程序的詞法分析過程。 2、根據PASCAL語言的說明語句形式,用手工方法構造一個對說明語
編譯原理實驗 簡單詞法分析程式的設計
一、實驗目的 瞭解詞法分析程式的基本構造原理,掌握簡單詞法分析程式的構造方法。 二、實驗內容 根據PASCAL語言的說明語句結構,設計一個對PASCAL語言常量說明語句進行詞法分析的簡單程式,並用C、C++或Java語言程式設計實現。要求程式能夠對從鍵盤輸入或從檔案讀入
編譯原理簡單的LALR(1)分析表的構造
閒著無聊,,,,寫了一個簡單的LALR(1)分析表的構造,就當是複習了 #include <cstdio> #include <cstring> #include <map> #include <vector> #includ
java實現一個最簡單的tomcat服務
連接數 accep print tex soc ins udp web服務 reply 1.如何啟動? main方法是程序的入口,tomcat也不例外,查看tomcat源碼,發現main是在Bootstrap 類中的; 2.如何建立連接? 要通訊,必須要建議so
編譯原理實驗 —— 詞法分析器
// Lexical_Analysis.cpp : 定義控制檯應用程式的入口點。 // #include "stdio.h" #include "stdlib.h" #include "string.h" #include "iostream" using namespace std; //詞法分析程式
【原始碼分享】java實現對接簡訊驗證碼應用功能
今天公司提出一個需求,要在現有專案上收集註冊使用者的真實手機號,由於之前沒有接觸過這一塊,只能尋求度孃的幫助,經過一天的努力,終於完成了,現整理記錄下已備查閱。 1 解決方案:在註冊時要求使用者進行手機驗證。2 尋找簡訊供應商:由於對這一塊不是太懂,大學同學推薦一家他們公司在用的給我。3 程式碼實現 首先到
【資料結構與演算法-java實現】二 複雜度分析(下):最好、最壞、平均、均攤時間複雜度的概念
上一篇文章學習了:如何分析、統計演算法的執行效率和資源消耗? 點選連結檢視上一篇文章:複雜度分析上 今天的文章學習以下內容: 最好情況時間複雜度 最壞情況時間複雜度 平均情況時間複雜度 均攤時間複雜度 1、最好與最壞情況時間複雜度 我們首先
編譯原理:語法分析1-遞迴下降
要求: 使用的文法如下: E →TE’ E → + TE’ | ε T → FT’ T →* FT’ | ε F → (E) | id 對於任意給定的輸入串(詞法記號流)進行語法分析,遞迴下降方法實現。 要有一定的錯誤處理功能。即對錯誤能提示,並且
堆排序的JAVA實現及時間複雜度分析
堆排序是一個比較常用的排序方式,下面是其JAVA的實現: 1. 建堆 // 對輸入的陣列進行建堆的操作 private static void buildMaxHeap(int[] array, int length) { // 遍歷所有
java實現word、pdf檔案下載功能
在SpringMVC的開發過程中,有時需要實現文件的下載功能。文件的下載功能涉及到了java IO流操作的基礎知識,下面本文詳細介紹java如何實現後臺文件下載功能。 首先根據文件在專案中的儲存路徑建立File物件,並獲取文件的名稱和字尾。判斷瀏覽器型別,防止
Java實現生成二維碼圖片功能
import cn.api.commons.commons.util.MatrixToImageWriter; import java.io.File; import java.io.FileOutputStream; import java.io.InputStr
java實現棧的簡單操作
public class stract { public static void main(String[] args) { MyStack stack = new MyStack(20); stack.push(10);
java實現RSA的簡單加密解密
RSAUtil package com.zhuyun.rsa; import java.io.IOException; import java.security.KeyFactory; import java.security.KeyPair; import java
java實現AES的簡單加密解密
AESUtil package com.zhuyun.aes; import java.io.IOException; import javax.crypto.Cipher; import ja
Java-JVM-編譯原理
Java-JVM-編譯原理 轉載宣告: 本文大量內容系轉載自以下文章,並參考其他文件資料加入了一些內容: JVM系列第4講:從原始碼到機器碼,發生了什麼? 作者:陳樹義 來源:部落格園 深入分析Java的編譯原理 來源:Hollis 轉載僅為方便學習檢視,一切權
二叉排序樹,java實現(知識簡單的實現,持續完善更新)
定義: 二叉排序樹就是左子樹都比節點小,右子樹都比節點大。簡單的排序二叉樹實現。 程式碼: package com.wzq.data_structure; public class Bina