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语言词法分析器的更多相关文章

  1. java编写词法分析器

    词法分析器就是通过扫描一段程序判断是否是关键字.标识符.常数.分界符.运算符.一般分为一符一种和经典五中: 这里我用的是经典五中,此词法分析器是用java编写的: /* 保留字|关键字:1 操作符|运 ...

  2. 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

    作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...

  3. java安全沙箱(三)之内置于Java虚拟机(及语言)的安全特性

    java是一种类型安全的语言,它有四类称为安全沙箱机制的安全机制来保证语言的安全性,这四类安全沙箱分别是: 类加载体系 .class文件检验器 内置于Java虚拟机(及语言)的安全特性 安全管理器及J ...

  4. 网页动物园2.0发布,经过几个月的努力,采用JAVA编写!

    网页动物园2.0发布,经过几个月的努力,采用JAVA编写! 网页动物园2.0 正式发布!游戏发布 游戏名称: 网页动物园插件 游戏来源: 原创插件 适用版本: Discuz! X1.5 - X3.5 ...

  5. [转]深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

    以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-l ...

  6. Java的native关键字---JAVA下调用其他语言的关键词

    今天研究Java基础类库,Object类的时候,发现了一个关键字:native 咦?这是个什么东东?它认识我,我可不认识它! 嘿嘿,没关系,baidu一下. java native关键字 一. 什么是 ...

  7. 实战WEB 服务器(JAVA编写WEB服务器)

    实战WEB 服务器(JAVA编写WEB服务器) 标签: web服务服务器javawebsockethttp服务器 2010-04-21 17:09 11631人阅读 评论(24) 收藏 举报  分类: ...

  8. Java学习笔记--脚本语言支持API

    Java语言的动态性之脚本语言支持API 随着Java平台的流行,很多的脚本语言(scripting language)都可以运行在Java虚拟机啊上,其中比较流行的有JavaScript.JRuby ...

  9. Java编写高质量代码改善程序的151个建议

    第一章  Java开发中通用的方法和准则 建议1:不要在常量和变量中出现易混淆的字母: (i.l.1:o.0等). 建议2:莫让常量蜕变成变量: (代码运行工程中不要改变常量值). 建议3:三元操作符 ...

随机推荐

  1. iOS xcodebuild 打包app

    1.传统的app打包(没有使用cocopods) 在打包之前,先把证书和配置文件选好. step1:打开终端,cd 进入到工程目录中 step2:xcodebuild clean(如果buid文件存在 ...

  2. 为静态Checkbox动态地添加checked属性

    1.ASP.NET HTML Code: 嵌套在repeater中 " ? "checked" : "" %> /> *** 关键代码: ...

  3. zoj 3757 Alice and Bob and Cue Sports 模拟

    题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3757 #include<cstdio> #incl ...

  4. lab 1实验报告

    练习1:理解通过make生成执行文件的过程. 1.操作系统镜像文件ucore.img是如何一步一步生成的? 生成 bin/kern 部分 生成 init.o 生成 readline.o 生成 stdi ...

  5. Java异常处理的误区和经验总结

    本文着重介绍了 Java 异常选择和使用中的一些误区,希望各位读者能够熟练掌握异常处理的一些注意点和原则,注意总结和归纳.只有处理好了异常,才能提升开发人员的基本素养,提高系统的健壮性,提升用户体验, ...

  6. MSSQLSERVER数据库- 判断全局临时表是否存在

    写一下今天遇到的一个问题. 今天因为一些作用域的问题,我使用了全局临时表,然后我在存储过程里使用了这么一段语句,想判断全局临时表是否存在,如果不存在,则将他DROP掉. 可是这段语句没用. if ex ...

  7. 树莓派通过 HDMI - VGA 转接后分辨率始终为640*480无法修改的问题

    一开始装的Raspbian,感觉系统不错,就是分辨率调不了,网上找了很多解决方法,捣鼓了差不多一天,仍然没有解决. 期间尝试换了好几个系统,比如说 raspbmc .XBian等,最后试了下Pidor ...

  8. Shell 命令--文件创建、搜索命令--总结自《Linux Shell 脚本攻略》

    (一)文件创建命令 1.touch命令 比如:touch abc命令在本地文件夹中创建了一个名为abc的空文件 2.cp命令 cp命令同意我们把一个文件的内容拷贝到同名或不同名的文件里,复制得到的文件 ...

  9. dubbo与spring mvc

    安装 一.本地服务     1.定义服务接口: (该接口需单独打包,在服务提供方和消费方共享) public interface CustomerService { public String get ...

  10. css 行内元素和块级元素

    1. 块级元素默认在新行开始,如常见的div和p标签,行内元素默认在同行开始显示,如a,span标签 2.块级元素一般用于做容器,可容纳行内和块级元素,可设置width和height,行内元素只能容纳 ...