Java编写的C语言词法分析器
这是java编写的C语言词法分析器,我也是参考很多代码,然后核心代码整理起来,放在QQ空间和博客上,目的是互相学习借鉴,希望可以得到高手改进。这个词法分析器实现的功能有打开文件、保存文件、打开帮助文档、文本域内容的剪切和复制和黏贴、进行词法分析
程序的项目结构如图,Word类和Unidentifiable类是两个JavaBean类,存放的参数有两个row(整型)、word(String),row用于获取行数,word用于获取标识符,LexerFrame是词法分析器的界面类,Analyze封装了进行词法分析的核心代码 ,doc文件夹放一个帮助文档,当用户点击帮助按钮时可以弹出来以帮助用户使用。
//核心程序:
package com.lexer;
*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语言词法分析器的更多相关文章
- java编写词法分析器
词法分析器就是通过扫描一段程序判断是否是关键字.标识符.常数.分界符.运算符.一般分为一符一种和经典五中: 这里我用的是经典五中,此词法分析器是用java编写的: /* 保留字|关键字:1 操作符|运 ...
- 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...
- java安全沙箱(三)之内置于Java虚拟机(及语言)的安全特性
java是一种类型安全的语言,它有四类称为安全沙箱机制的安全机制来保证语言的安全性,这四类安全沙箱分别是: 类加载体系 .class文件检验器 内置于Java虚拟机(及语言)的安全特性 安全管理器及J ...
- 网页动物园2.0发布,经过几个月的努力,采用JAVA编写!
网页动物园2.0发布,经过几个月的努力,采用JAVA编写! 网页动物园2.0 正式发布!游戏发布 游戏名称: 网页动物园插件 游戏来源: 原创插件 适用版本: Discuz! X1.5 - X3.5 ...
- [转]深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-l ...
- Java的native关键字---JAVA下调用其他语言的关键词
今天研究Java基础类库,Object类的时候,发现了一个关键字:native 咦?这是个什么东东?它认识我,我可不认识它! 嘿嘿,没关系,baidu一下. java native关键字 一. 什么是 ...
- 实战WEB 服务器(JAVA编写WEB服务器)
实战WEB 服务器(JAVA编写WEB服务器) 标签: web服务服务器javawebsockethttp服务器 2010-04-21 17:09 11631人阅读 评论(24) 收藏 举报 分类: ...
- Java学习笔记--脚本语言支持API
Java语言的动态性之脚本语言支持API 随着Java平台的流行,很多的脚本语言(scripting language)都可以运行在Java虚拟机啊上,其中比较流行的有JavaScript.JRuby ...
- Java编写高质量代码改善程序的151个建议
第一章 Java开发中通用的方法和准则 建议1:不要在常量和变量中出现易混淆的字母: (i.l.1:o.0等). 建议2:莫让常量蜕变成变量: (代码运行工程中不要改变常量值). 建议3:三元操作符 ...
随机推荐
- Oracle10g/11g 在SUSE/RHEL上的安装与配置
在过去对众多项目的支撑过程中,Oracle作为首选数据库,其安装与配置过程成了重复性最多的工作之一.在此,我进行了总结,并分享出来,希望能对大家有所帮助.随着Oracle版本的提升,从9i -> ...
- NULL指针 Void* 和野指针
在C和C++的语言中常常有这几个概念: NULL指针.空指针.Void *指针.野指针(Wild Pointer)甚至垂悬指针(Dangling Pointer). 1.NULL指针,一般用于指向一个 ...
- HDU 1102 Constructing Roads (最小生成树)
最小生成树模板(嗯……在kuangbin模板里面抄的……) 最小生成树(prim) /** Prim求MST * 耗费矩阵cost[][],标号从0开始,0~n-1 * 返回最小生成树的权值,返回-1 ...
- 引入less报错解决方法以及浏览器设计不同的地方
XMLHttpRequest cannot load file:///C:/Users/PAXST/Desktop/805/first.less. Cross origin requests are ...
- new Date() iso不支持兼容性问题
在IOS5以上版本(不包含IOS5)中的Safari浏览器能正确解释出Javascript中的 new Date('2013-10-21') 的日期对象. 但是在IOS5版本里面的Safari解释ne ...
- 皮皮果模式系统开发app
皮皮果系统定制开发,皮皮果网站系统开发. 皮皮果游戏横空出世,比QQ农场有过之而无不及,深得广大玩家喜爱.无论草根百姓还是达官贵人,都可以来学习娱乐的游戏.让你在娱乐中收获物质生活和精神生活,英伦果园 ...
- java transient简单介绍
我们都知道一个对象仅仅要实现了Serilizable接口,这个对象就能够被序列化,java的这样的序列化模式为开发人员提供了非常多便利,我们能够不必关系详细序列化的过程,仅仅要这个类实现了Serili ...
- YUV422蓝屏显示输出功能辅助调试
YUV422蓝屏显示输出功能辅助调试 YUV422有YUYV,YVYU,UYVY,VYUY四种,以下笔者就就以UYVY为例介绍一下数据构成.因为常常要跟视频输入打交道,所以YUV422这种常见的视频信 ...
- careercup-递归和动态规划 9.11
9.11 给定一个布尔表达式,由0.1.&.|和^等符号组成,以及一个想要的布尔结果result,实现一个函数,算出有几种括号的放法可使该表达式得出result值. 解法: 跟其他递归问题一样 ...
- 标准I/O的替代软件
标准I/O并不完善. 标准I/O库的一个不足之处是效率不高,这与它需要复制的数据量有关.当使用每次一行函数fgets和fputs时,通常需要复制两次数据:一次是在内核和标准I/O缓冲之间(当调用rea ...