標籤:
Java編寫的C語言詞法分析器
這是java編寫的C語言詞法分析器,我也是參考很多代碼,然後核心代碼整理起來,放在QQ空間和部落格上,目的是互相學習借鑒,希望可以得到高手改進。這個詞法分析器實現的功能有開啟檔案、儲存檔案、開啟協助文檔、文本域內容的剪下和複製和黏貼、進行詞法分析
程式的項目結構,Word類和Unidentifiable類是兩個JavaBean類,存放的參數有兩個row(整型)、word(String),row用於擷取行數,word用於擷取標識符,LexerFrame是詞法分析器的介面類,Analyze封裝了進行詞法分析的核心代碼 ,doc檔案夾放一個協助文檔,當使用者點擊協助按鈕時可以彈出來以協助使用者使用。
//核心程式:
package com.lexer;import java.util.ArrayList;
/**
*1~20號為關鍵字,用下標表示,i+1就是其機器碼;21~40號為操作符,用下標表示,i+21就是其機器碼;41~60號為分界符,
* 用下標表示,i+41就是其機器碼;使用者自訂的標識符,其機器碼為51;常數的機器碼為52;不可以識別的標識符,其機器碼為0
*/
public class Analyze { //關鍵字
private String keyword[]={"int","long","char","if","else","for","while","return","break","continue",
"switch","case","default","float","double","void","struct","static","do","short"};
//運算子
private String operator[]={"+","-","*","/","%","=",">","<","!","==","!=",">=","<=","++","--","&","&&","||","[","]"};
//分界符
private String delimiter[]={",",";","(",")","{","}","\‘","\"",":","#"};
public Analyze() {
}
/**
* 判斷是否是數字
*/
public boolean isDigit(char ch){
if(ch>=‘0‘&&ch<=‘9‘){
return true;
}else{
return false;
}
}
/**
* 判斷是否是字母的函數
*/
public boolean isLetter(char ch){
if((ch>=‘a‘&&ch<=‘z‘)||(ch>=‘A‘&&ch<=‘Z‘)){
return true;
}else{
return false;
}
}
/**
* 判斷是否由兩個運算子組成
*/
public boolean isTwoOperator(String str,char ch){
char lc;
int flag=0;
if(str.length()>1||str.length()==0){//字元數大於2和無字元的情況
return false;
}else{//字元數等於2的情況
lc=str.charAt(str.length()-1);
if(ch==‘=‘&&(lc==‘>‘||lc==‘<‘||lc==‘=‘||lc==‘!‘)){
}else if(ch==‘+‘&&lc==‘+‘){
}else if(ch==‘-‘&&lc==‘-‘){
}else if(ch==‘|‘&&lc==‘|‘){
}else if(ch==‘&‘&&lc==‘&‘){
}else{
return false;//否就返回false
}
return true;//其它符號的情況都返回true
}
}
/**
* 擷取關鍵字的機器碼
*/
public int getKeywordOpcodes(String str){
int i;
for(i=0;i<keyword.length;i++){
if(str.equals(keyword[i]))
break;
}
if(i<keyword.length){
return i+1;//返回關鍵字的機器碼
}else{
return 0;
}
}
/**
* 擷取操作符的機器碼
*/
public int getOperatorOpcodes(String str){
int i;
for(i=0;i<operator.length;i++){
if(str.equals(operator[i]))
break;
}
if(i<operator.length)
return i+21;//返回操作符的機器碼
else
return 0;
}
/**
* 擷取分界符的機器碼
*/
public int getDelimiterOpcodes(String str){
int i;
for(i=0;i<delimiter.length;i++){
if(str.equals(delimiter[i]))
break;
}
if(i<delimiter.length)
return i+41;//返回分界符的機器碼
else
return 0;
}
/**
* 判斷字元是否可以識別
*/
public boolean isIdent(String str){
char ch;
int i;
for(i=0;i<str.length();i++){
ch=str.charAt(i);
//非數字串的情況和非由英文字母組成的字串
if((i==0&&!isLetter(ch))||(!isDigit(ch)&&!isLetter(ch))){
break;
}
}
if(i<str.length()){
return false;
}else{
return true;
}
}
/**
*
* 預先處理函數
*/
public String preFunction(String str){
String ts="";
int i;
char ch,nc;
//這裡的i<str.length()-1
for(i=0;i<str.length()-1;i++){
ch=str.charAt(i);
nc=str.charAt(i+1);
if(ch==‘\n‘){//如果字元是分行符號,將\n換成$
ch=‘$‘;
ts=ts+ch;
}else if(ch==‘ ‘||ch==‘\r‘||ch==‘\t‘){
if(nc==‘ ‘||nc==‘\r‘||ch==‘\t‘){
continue;//連續‘ ‘或者‘\t‘或者‘\r‘的情況,直接跳過
}else{
ch=‘ ‘;//一個‘ ‘或者‘\t‘或者‘\r‘的情況,將這些字元換成‘ ‘
ts=ts+ch;
}
}else{
ts=ts+ch;//將字元連起來
}
}
ch=str.charAt(str.length()-1);
if(ch!=‘ ‘&&ch!=‘\r‘&&ch!=‘\t‘&&ch!=‘\n‘){
ts=ts+ch;
}
return ts;
}
/**
* 將字串分成一個個單詞,存放在數組列表
*/
public ArrayList<Word> divide(String str){
ArrayList<Word> list=new ArrayList<Word>();
String s="";
char ch;
int i;
int row=1;
for(i=0;i<str.length();i++){
ch=str.charAt(i);
if(i==0&&ch==‘ ‘)//字串的第一個字元
continue;
if(ch==‘ ‘){//‘ ‘或者‘\t‘或者‘\r‘的情況
if(s!=""){
list.add(new Word(row, s));
s="";//置空
}else{
continue;
}
}else if(isDigit(ch)||isLetter(ch)){
if(s==""||isDigit(s.charAt(s.length()-1))||isLetter(s.charAt(s.length()-1))){
s = s + ch;
}else{
list.add(new Word(row, s));
s = "";
s=s + ch;
}
}else{
if(isTwoOperator(s, ch)){//兩個運算子的情況
s = s + ch;
}else{
if(s==""&&ch!=‘$‘){
s = s + ch;
}else if(s==""&&ch==‘$‘){//若檢測到$符號,就換行
row++;//行數加一
}else{
list.add(new Word(row, s));
s = "";
if(ch!=‘$‘){
s=s + ch;
}else{
row++;
}
}
}
}
}
if(s!=""){
list.add(new Word(row, s));
}
return list;
}
/**
* 判斷字串是數字串,單個字元,還是一個字串
*/
public int check(String str){
char ch;
ch=str.charAt(0);
if(ch>=‘0‘&&ch<=‘9‘){
return 1;//數字串
}
if(str.length()==1)
return 2;//單個字元
else
return 3;//一個字串
}
/**
*
* 檢查字串是否為數字串,返回其機器碼
*/
public int checkDigit(String str){
int i;
char ch;
for(i=0;i<str.length();i++){
ch=str.charAt(i);
if(ch>‘9‘||ch<‘0‘)
break;
}
if(i<str.length()){
return 0;//不可識別的情況
}else{
return 52;//常數
}
}
/**
*
* 檢查字串是否為單個字元,返回其機器碼
*/
public int checkChar(String str){
if(getOperatorOpcodes(str)!=0){//操作符
return getOperatorOpcodes(str);
}else if(getDelimiterOpcodes(str)!=0){//分界符
return getDelimiterOpcodes(str);
}else if(isIdent(str)){
return 51;//使用者自訂標識符的機器碼
}else{
return 0;//不可以被識別的標識符,機器碼為0
}
}
/**
*
* 檢查字串是否為字串,返回其機器碼
*/
public int checkString(String str){
if(getOperatorOpcodes(str)!=0){//操作符
return getOperatorOpcodes(str);
}else if(getKeywordOpcodes(str)!=0){//關鍵字
return getKeywordOpcodes(str);
}else if(isIdent(str)){
return 51;//使用者自訂標識符的機器碼
}else{
return 0;//不可以被識別的標識符,機器碼為0
}
}
}
//********************************************************************************************************************
在介面類寫這個方法來調用方法
/**
* 詞法分析
*/
public void doTokenizing(){
consoleTextArea.setText(null);
ArrayList<Word> wlist=new ArrayList<Word>();
ArrayList<Unidentifiable> ulist=new ArrayList<Unidentifiable>();
String s,ts,str;
Word word;
int i;
int opcodes=-1;
int errorNum=0;
int count=0;
s=fileContentTextArea.getText();
if(s.length()>1){
ts=analyze.preFunction(s);
wlist=analyze.divide(ts);
values=new String[wlist.size()][3];
while(wlist.size()>0){
word=(Word)wlist.remove(0);
str=word.getWord();
i=analyze.check(str);
switch (i) {
case 1:
opcodes=analyze.checkDigit(str);
break;
case 2:
opcodes=analyze.checkChar(str);
break;
case 3:
opcodes=analyze.checkString(str);
break;
}
if(opcodes==0){
Unidentifiable u=new Unidentifiable(word.getRow(), str);
ulist.add(u);
errorNum++;
}
values[count][0]=String.valueOf(word.getRow());
values[count][1]=str;
values[count][2]=String.valueOf(opcodes);
count++;
}
//更新表格內容
DefaultTableModel model=(DefaultTableModel)table.getModel();
while(model.getRowCount()>0){
model.removeRow(model.getRowCount()-1);
}
model.setDataVector(values,title);
table=new JTable(model);
consoleTextArea.append("共有"+errorNum+"處錯誤!"+"\n");
while (ulist.size()>0) {
int r;
String string;
Unidentifiable uni=ulist.remove(0);
r=uni.getRow();
string=uni.getWord();
consoleTextArea.append("第"+r+"行:"+"錯誤,"+string+"\n");
}
}else{
int j;
j=JOptionPane.showConfirmDialog(this, "請輸入程式!");
if(j!=JOptionPane.YES_OPTION){
return;
}
}
}
Java編寫的C語言詞法分析器