词法分析器java_利用Java实现简单的词法分析器实例代码
首先看下我们要分析的代码段如下:
输出结果如下:
输出结果(a).PNG
输出结果(b).PNG
输出结果(c).PNG
括号里是一个二元式:(单词类别编码,单词位置编号)
代码如下:
package Yue.LexicalAnalyzer;
import java.io.*;
/*
* 主程序
*/
public class Main {
public static void main(String[] args) throws IOException {
Lexer lexer = new Lexer();
lexer.printToken();
lexer.printSymbolsTable();
}
}
package Yue.LexicalAnalyzer;
import java.io.*;
import java.util.*;
/*
* 词法分析并输出
*/
public class Lexer {
/*记录行号*/
public static int line = 1;
/*存放最新读入的字符*/
char character = ' ';
/*保留字*/
Hashtable keywords = new Hashtable();
/*token序列*/
private ArrayList tokens = new ArrayList();
/*符号表*/
private ArrayList symtable = new ArrayList();
/*读取文件变量*/
BufferedReader reader = null;
/*保存当前是否读取到了文件的结尾*/
private Boolean isEnd = false;
/* 是否读取到文件的结尾 */
public Boolean getReaderState() {
return this.isEnd;
}
/*打印tokens序列*/
public void printToken() throws IOException {
FileWriter writer = new FileWriter("E:\\lex.txt");
System.out.println("词法分析结果如下:");
System.out.print("杜悦-2015220201031\r\n\n");
writer.write("杜悦-2015220201031\r\n\r\n");
while (getReaderState() == false) {
Token tok = scan();
String str = "line " + tok.line + "\t(" + tok.tag + "," + tok.pos + ")\t\t"
+ tok.name + ": " + tok.toString() + "\r\n";
writer.write(str);
System.out.print(str);
}
writer.flush();
}
/*打印符号表*/
public void printSymbolsTable() throws IOException {
FileWriter writer = new FileWriter("E:\\symtab1.txt");
System.out.print("\r\n\r\n符号表\r\n");
System.out.print("编号\t行号\t名称\r\n");
writer.write("符号表\r\n");
writer.write("编号 " + "\t行号 " + "\t名称 \r\n");
Iterator e = symtable.iterator();
while (e.hasNext()) {
Symbol symbol = e.next();
String desc = symbol.pos + "\t" + symbol.line + "\t" + symbol.toString();
System.out.print(desc + "\r\n");
writer.write(desc + "\r\n");
}
writer.flush();
}
/*打印错误*/
public void printError(Token tok) throws IOException{
FileWriter writer = new FileWriter("E:\\error.txt");
System.out.print("\r\n\r\n错误词法如下:\r\n");
writer.write("错误词法如下:\r\n");
String str = "line " + tok.line + "\t(" + tok.tag + "," + tok.pos + ")\t\t"
+ tok.name + ": " + tok.toString() + "\r\n";
writer.write(str);
}
/*添加保留字*/
void reserve(KeyWord w) {
keywords.put(w.lexme, w);
}
public Lexer() {
/*初始化读取文件变量*/
try {
reader = new BufferedReader(new FileReader("E:\\输入.txt"));
} catch (IOException e) {
System.out.print(e);
}
/*添加保留字*/
this.reserve(KeyWord.begin);
this.reserve(KeyWord.end);
this.reserve(KeyWord.integer);
this.reserve(KeyWord.function);
this.reserve(KeyWord.read);
this.reserve(KeyWord.write);
this.reserve(KeyWord.aIf);
this.reserve(KeyWord.aThen);
this.reserve(KeyWord.aElse);
}
/*按字符读*/
public void readch() throws IOException {
character = (char) reader.read();
if ((int) character == 0xffff) {
this.isEnd = true;
}
}
/*判断是否匹配*/
public Boolean readch(char ch) throws IOException {
readch();
if (this.character != ch) {
return false;
}
this.character = ' ';
return true;
}
/*数字的识别*/
public Boolean isDigit() throws IOException {
if (Character.isDigit(character)) {
int value = 0;
while (Character.isDigit(character)) {
value = 10 * value + Character.digit(character, 10);
readch();
}
Num n = new Num(value);
n.line = line;
tokens.add(n);
return true;
} else
return false;
}
/*保留字、标识符的识别*/
public Boolean isLetter() throws IOException {
if (Character.isLetter(character)) {
StringBuffer sb = new StringBuffer();
/*首先得到整个的一个分割*/
while (Character.isLetterOrDigit(character)) {
sb.append(character);
readch();
}
/*判断是保留字还是标识符*/
String s = sb.toString();
KeyWord w = keywords.get(s);
/*如果是保留字的话,w不应该是空的*/
if (w != null) {
w.line = line;
tokens.add(w);
} else {
/*否则就是标识符,此处多出记录标识符编号的语句*/
Symbol sy = new Symbol(s);
Symbol mark = sy; //用于标记已存在标识符
Boolean isRepeat = false;
sy.line = line;
for (Symbol i : symtable) {
if (sy.toString().equals(i.toString())) {
mark = i;
isRepeat = true;
}
}
if (!isRepeat) {
sy.pos = symtable.size() + 1;
symtable.add(sy);
} else if (isRepeat) {
sy.pos = mark.pos;
}
tokens.add(sy);
}
return true;
} else
return false;
}
/*符号的识别*/
public Boolean isSign() throws IOException {
switch (character) {
case '#':
readch();
AllEnd.allEnd.line = line;
tokens.add(AllEnd.allEnd);
return true;
case '\r':
if (readch('\n')) {
readch();
LineEnd.lineEnd.line = line;
tokens.add(LineEnd.lineEnd);
line++;
return true;
}
case '(':
readch();
Delimiter.lpar.line = line;
tokens.add(Delimiter.lpar);
return true;
case ')':
readch();
Delimiter.rpar.line = line;
tokens.add(Delimiter.rpar);
return true;
case ';':
readch();
Delimiter.sem.line = line;
tokens.add(Delimiter.sem);
return true;
case '+':
readch();
CalcWord.add.line = line;
tokens.add(CalcWord.add);
return true;
case '-':
readch();
CalcWord.sub.line = line;
tokens.add(CalcWord.sub);
return true;
case '*':
readch();
CalcWord.mul.line = line;
tokens.add(CalcWord.mul);
return true;
case '/':
readch();
CalcWord.div.line = line;
tokens.add(CalcWord.div);
return true;
case ':':
if (readch('=')) {
readch();
CalcWord.assign.line = line;
tokens.add(CalcWord.assign);
return true;
}
break;
case '>':
if (readch('=')) {
readch();
CalcWord.ge.line = line;
tokens.add(CalcWord.ge);
return true;
}
break;
case '
if (readch('=')) {
readch();
CalcWord.le.line = line;
tokens.add(CalcWord.le);
return true;
}
break;
case '!':
if (readch('=')) {
readch();
CalcWord.ne.line = line;
tokens.add(CalcWord.ne);
return true;
}
break;
}
return false;
}
/*下面开始分割关键字,标识符等信息*/
public Token scan() throws IOException {
Token tok;
while (character == ' ')
readch();
if (isDigit() || isSign() || isLetter()) {
tok = tokens.get(tokens.size() - 1);
} else {
tok = new Token(character);
printError(tok);
}
return tok;
}
}
package Yue.LexicalAnalyzer;
/*
* Token父类
*/
public class Token {
public final int tag;
public int line = 1;
public String name = "";
public int pos = 0;
public Token(int t) {
this.tag = t;
}
public String toString() {
return "" + (char) tag;
}
}
package Yue.LexicalAnalyzer;
/*
* 单词类别赋值
*/
public class Tag {
public final static int
BEGIN = 1, //保留字
END = 2, //保留字
INTEGER = 3, //保留字
FUNCTION = 4, //保留字
READ = 5, //保留字
WRITE = 6, //保留字
IF = 7, //保留字
THEN = 8, //保留字
ELSE = 9, //保留字
SYMBOL = 11, //标识符
CONSTANT = 12, //常数
ADD = 13, //运算符 "+"
SUB = 14, //运算符 "-"
MUL = 15, //运算符 "*"
DIV = 16, //运算符 "/"
LE = 18, //运算符 "<="
GE = 19, //运算符 ">="
NE = 20, //运算符 "!="
ASSIGN = 23, //运算符 ":="
LPAR = 24, //界符 "("
RPAR = 25, //界符 ")"
SEM = 26, //界符 ";"
LINE_END = 27, //行尾符
ALL_END = 28; //结尾符 "#"
}
package Yue.LexicalAnalyzer;
/**
* 保留字
*/
public class KeyWord extends Token {
public String lexme = "";
public KeyWord(String s, int t) {
super(t);
this.lexme = s;
this.name = "保留字";
}
public String toString() {
return this.lexme;
}
public static final KeyWord
begin = new KeyWord("begin", Tag.BEGIN),
end = new KeyWord("end", Tag.END),
integer = new KeyWord("integer", Tag.INTEGER),
function = new KeyWord("function", Tag.FUNCTION),
read = new KeyWord("read", Tag.READ),
write = new KeyWord("write", Tag.WRITE),
aIf = new KeyWord("if", Tag.IF),
aThen = new KeyWord("then", Tag.THEN),
aElse = new KeyWord("else", Tag.ELSE);
}
package Yue.LexicalAnalyzer;
/*
* 标识符
*/
public class Symbol extends Token {
public String lexme = "";
public Symbol(String s) {
super(Tag.SYMBOL);
this.lexme = s;
this.name = "标识符";
}
public String toString() {
return this.lexme;
}
}
package Yue.LexicalAnalyzer;
/**
* 运算符
*/
public class CalcWord extends Token {
public String lexme = "";
public CalcWord(String s, int t) {
super(t);
this.lexme = s;
this.name = "运算符";
}
public String toString() {
return this.lexme;
}
public static final CalcWord
add = new CalcWord("+", Tag.ADD),
sub = new CalcWord("-", Tag.SUB),
mul = new CalcWord("*", Tag.MUL),
div = new CalcWord("/", Tag.DIV),
le = new CalcWord("<=", Tag.LE),
ge = new CalcWord(">=", Tag.GE),
ne = new CalcWord("!=", Tag.NE),
assign = new CalcWord(":=", Tag.ASSIGN);
}
package Yue.LexicalAnalyzer;
/**
* 界符
*/
public class Delimiter extends Token {
public String lexme = "";
public Delimiter(String s, int t) {
super(t);
this.lexme = s;
this.name = "界符";
}
public String toString() {
return this.lexme;
}
public static final Delimiter
lpar = new Delimiter("(", Tag.LPAR),
rpar = new Delimiter(")", Tag.RPAR),
sem = new Delimiter(";", Tag.SEM);
}
package Yue.LexicalAnalyzer;
/*
* 常数
*/
public class Num extends Token {
public final int value;
public Num(int v) {
super(Tag.CONSTANT);
this.value = v;
this.name = "常数";
}
public String toString() {
return "" + value;
}
}
package Yue.LexicalAnalyzer;
/**
* 行尾符
*/
public class LineEnd extends Token {
public String lexme = "";
public LineEnd(String s) {
super(Tag.LINE_END);
this.lexme = s;
this.name = "行尾符";
}
public String toString() {
return this.lexme;
}
public static final LineEnd lineEnd = new LineEnd("\r\n");
}
package Yue.LexicalAnalyzer;
/**
* 结尾符
*/
public class AllEnd extends Token {
public String lexme = "";
public AllEnd(String s) {
super(Tag.ALL_END);
this.lexme = s;
this.name = "结尾符";
}
public String toString() {
return this.lexme;
}
public static final AllEnd allEnd = new AllEnd("#");
}
总结
以上就睡这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。
您可能感兴趣的文章:
词法分析器java_利用Java实现简单的词法分析器实例代码相关推荐
- 基于《仙剑奇侠传柔情版》利用Java的简单实现(一)
基于<仙剑奇侠传柔情版>利用Java的简单实现(一) 2018-12-01 23:55:36 by Louis 一,新建一个类GameFrame.class,具体代码如下: pack ...
- python爬虫简单实例-Python 利用Python编写简单网络爬虫实例3
利用Python编写简单网络爬虫实例3 by:授客 QQ:1033553122 实验环境 python版本:3.3.5(2.7下报错 实验目的 获取目标网站"http://bbs.51tes ...
- Java 实现简单的发红包代码
Java 实现简单的发红包代码 一.实现思路 1.参考微信发红包,会有2个参数: 红包个数 和 红包金额 ,假设红包个数是num,红包金额是money ,使用随机数的方式进行划分,不考虑多线程情况下的 ...
- android 代码浏览,Webview实现android简单的浏览器实例代码
WebView是Android中一个非常实用的组件,它和Safai.Chrome一样都是基于Webkit网页渲染引擎,可以通过加载HTML数据的方式便捷地展现软件的界面,下面通过本文给大家介绍Webv ...
- php django mysql配置文件_Mysql学习Django+mysql配置与简单操作数据库实例代码
<Mysql学习Django+mysql配置与简单操作数据库实例代码>要点: 本文介绍了Mysql学习Django+mysql配置与简单操作数据库实例代码,希望对您有用.如果有疑问,可以联 ...
- php mysql简单留言本_php+mysql写的简单留言本实例代码
php+mysql写的简单留言本实例代码 更新时间:2008年07月25日 09:41:32 作者: 方便新手学习php guestbook.php: COLOR: #002878; TEXT-D ...
- mysql mongo关联查询语句_MySQL与Mongo简单的查询实例代码 筋斗云网络
简介 本文通过一个实例给大家用MySQL和mongodb分别写一个查询,本文图片并茂给大家介绍的非常详细,感兴趣的朋友参考下吧 首先在这里我就不说关系型数据库与非关系型数据库之间的区别了(百度上有很多 ...
- python计算面积代码_利用Python求阴影部分的面积实例代码
利用Python求阴影部分的面积实例代码 来源:中文源码网 浏览: 次 日期:2019年11月5日 [下载文档: 利用Python求阴影部分的面积实例代码.txt ] (友情提示:右键点 ...
- 天天酷跑java_利用Java怎么实现一个天天酷跑游戏
利用Java怎么实现一个天天酷跑游戏 发布时间:2020-12-15 17:25:03 来源:亿速云 阅读:102 作者:Leah 利用Java怎么实现一个天天酷跑游戏?很多新手对此不是很清楚,为了帮 ...
最新文章
- 关系数据理论中的范式
- Centos 7 安装 ifconfig 管理命令
- WSP框架:WEB组件的原理
- 信息系统项目管理师-信息系统项目管理基础核心知识点思维脑图
- ProcessExplore 最新版
- Centos 7初始化脚本
- mysql8安装目录linux7.5_Linux系统下 MySQL 5.7和8.0 版本安装指南
- 一句话解释什么是回归
- SpringBoot2.0之八 多数据源配置
- SQL Server 中 GO 的用法
- 无法删除文件,无法读源文件或磁盘:U盘文件夹乱码无法删除的原因及解决方案...
- git切换远程分支并拉取最新代码
- python绘制折线图怎么样填充空白颜色_两条折线图之间填充颜色
- COSTDOWN Project's BSP(一)
- Nano Measurer 1.2.5 for win 纳米颗粒粒度分析
- HTML+CSS系列学习 第五篇
- 服务网关(Gateway)自定义全局过滤器统一Token处理
- Vue3中reactive的理解
- GetElementByName
- C#通信,结构体和byte数组互转
热门文章
- Pytorch的反向传播backward()详解
- Linux操作系统下开启wifi热点的方法
- 关于__declspec(dllimport)的理解
- HTML5响应式手机模板:【超炫购物模板】——仿拍鞋网商城手机网站模板( HTML+CSS+JavaScript) 企业手机网站模板
- 标准分辨率QVGA,VGA,SVGA,XGA,SXGA+,UVGA的定义
- ifstream java_ifstream :: seekg给出了错误的结果
- 电脑里有两个edge浏览器怎么办?
- manage.py: error: unrecognized arguments: runserver 8888运行pytorch模型报错
- linux ntp时间服务器配置 (资料)
- 学而思网校王闯老师简介 初中物理名师