A.3 词法分析器
包 lexer 是词法分析器的代码的扩展。类 Tag 定义了各个词法单元对应的常量。
1: package lexer;
2: public class Tag {
3: public final static int
4: AND = 256 , BASIC = 257 , BREAK = 258 , DO = 259 , ELSE = 260 ,
5: EQ = 261 , FALSE = 262 , GE = 263 , ID = 264 , IF = 265 ,
6: INDEX = 266 , LE = 267 , MINUS = 268 , NE = 269 , NUM = 270 ,
7: OR = 271 , REAL = 272 , TEMP = 273 , TRUE = 274 , WHILE = 275 ;
8: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
其中的三个常量 INDEX、MINUS、和TEMP不是词法单元他们将在抽象语法树中使用。
1: package lexer;
2: public class Token {
3: public final static int tag;
4:
5: public Token(int t){
6: tag=t;
7: }
8:
9: public String toString(){
10: return ""+(char)tag;
11: }
12: }
13:
14: package lexer; //文件 Num.java
15: public class Num extends Token{
16: public final value;
17:
18: public Num(int v){
19: super(Tag.NUM);
20: value=v;
21: }
22:
23: public String toString(){
24: return "" + value;
25: }
26: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
类Word用于管理保留字、标识符和像 && 这样的复合词法单元的词素。它也可以用来管理在中间代码中运算符的书写符号形式;比如单目减号。例如,原文件中的 –2 的中间形式是minus 2.
1: package lexer;
2: public class Word extends Token{
3: public String lexeme = "";
4:
5: public Word(String s ,int tag){
6: super(tag);
7: lexeme = s;
8: }
9:
10: public String toString(){
11: return lexeme;
12: }
13:
14: public static final Word
15: and = new Word("&&",Tag.AND), or = new Word("||",Tag.OR),
16: eq = new Word("==",Tag.EQ), ne = new Word("!=",Tag.NE),
17: le = new Word("<=",Tag.LE), ge = new Word(">=",Tag.GE),
18: minus = new Word("minus",Tag.MINUS),
19: True = new Word("true",Tag.TRUE),
20: False = new Word("false",Tag.FAlSE),
21: temp = new Word("t",Tag.TEMP);
22: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
类Real用于处理浮点数:
1: package lexer;
2: public class Real extends Token{
3: public final float value;
4:
5: public Real(float v){
6: super(Tag.REAL);
7: value = v;
8: }
9:
10: public String toString(){
11: return "" + value;
12: }
13: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
类Lexer的主方法,即函数scan,识别数字、标识符和保留字。
类Lexer中的第9~13行保留了关键字。第14~16行保留了在其他地方定义的对象的词素。对象Word.True和Word.False在类Word中定义。对应于基本类型 int 、char、bool 和 float 的对象在类 Type 中定义。类Type 是Word 的一个子类。类 Type 来自包 symbols .
1: package lexer; //文件Lexer.java
2: import java.io.*;
3: import java.util.*;
4: import symbols.*;
5: public class Lexer{
6: public static int line = 1;
7: char peek = ' ';
8: Hashtable words = new Hashtalbe();
9:
10: void reverse(Word w){
11: words.put(w.lexeme,w);
12: }
13:
14: public Lexer(){
15: reverse(new Word("if",Tag.IF));
16: reverse(new Word("else",Tag.ELSE));
17: reverse(new Word("while",Tag.WHILE));
18: reverse(new Word("do",Tag.DO));
19: reverse(new Word("break",Tag.BREAK));
20: reverse(Word.True);
21: reverse(Word.False);
22: reverse(Word.Int);
23: reverse(Word.Char);
24: reverse(Word.Bool);
25: reverse(Word.Float);
26: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
函数readch()(第18行)用于把下一个输入字符读到变量peek中。名字readch被复用或重载,(第19~24行),以便帮助识别复合的词法单元。比如,一看到输入字符<,调用readch(“=”)就会把下一个字符读入peek,并检查它是否为=。
1: void readch() throws IOException{
2: peek=(char) System.in.read();
3: }
4:
5: boolean readch(char c)throws IOException{
6: readch();
7: if(peek != c)
8: return false;
9: peek = ' ';
10: return true;
11: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
函数scan一开始首先略过所有的空白字符(第26~30行)。它首先试图识别像<=这样的复合词法单元(第31~34行)和项365这样的数字(第45~58行)。如果不成功,他就试图读入一个字符串(第59~70行)。
1: public Token scan() throws IOException{
2: for( ; ; readch()){
3: if(peek == ' '|| peek == '\t')
4: continue;
5: else if(peek == '\n')
6: line=line+1;
7: else
8: break;
9:
10: switch(peek){
11: case '&':
12: if(readch('&'))
13: return Word.and;
14: else
15: return new Token('&');
16: case '|':
17: if(readch('|'))
18: return Word.or;
19: else
20: return new Token('|');
21: case '=':
22: if(readch('='))
23: return Word.eq;
24: else
25: return new Token('=');
26: case '!':
27: if(readch('!'))
28: return Word.ne;
29: else
30: return new Token('!');
31: case '<':
32: if(readch('<'))
33: return Word.le;
34: else
35: return new Token('<');
36: case '>':
37: if(readch('>'))
38: return Word.ge;
39: else
40: return new Token('>');
41: }
42:
43: if(Character.isDigit(peek)){
44: int v=0;
45: do{
46: v=10*v=Character.digit(peek,10);
47: readch();
48: }while(Character.isDigit(peek));
49:
50: if(peek!='.')
51: return new Num(v);
52: float x= v;
53: float d=10;
54: for( ; ; ){
55: readch();
56: if(! Character.isDigit(peek))
57: break;
58: x=x+Character.digit(peek,10)/d;
59: d=d*10;
60: }
61: return new Real(x);
62: }
63:
64: if(Character.isLetter(peek)){
65: StringBuffer b=new StringBuffer();
66: do{
67: b.append(peek);
68: readch();
69: }while(Character.isLetterOrDigit(peek));
70: String s=b.toString();
71: Word w=(Word)words.get(s);
72: if(w!=null)
73: return w;
74: w = new Word(s,Tag.ID);
75: words.put(s,w);
76: return w;
77: }
78: Token tok=new Token(peek);
79: peek=' ';
80: return tok;
81: }
82: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
最后,peek中的任意字符都被作为词法单元返回。
A.3 词法分析器的更多相关文章
- sizzle分析记录:词法分析器(tokenize)
词法分析器(tokenize)? 词法分析器又称扫描器.词法分析是指将我们编写的文本代码流解析为一个一个的记号,分析得到的记号以供后续语法分析使用. sizzle引入了tokenize这个概念,意义? ...
- C# 词法分析器(五)转换 DFA
系列导航 (一)词法分析介绍 (二)输入缓冲和代码定位 (三)正则表达式 (四)构造 NFA (五)转换 DFA (六)构造词法分析器 (七)总结 在上一篇文章中,已经得到了与正则表达式等价的 NFA ...
- 用词法分析器Flex过滤日志
每日构造中,我的项目中 Visual Studio 的 MakeFile 后会产生大量信息,如下 Microsoft (R) Visual Studio Version 10.0.40219.1.Co ...
- Atitit 词法分析器的设计最佳实践说明attilax总结
Atitit 词法分析器的设计最佳实践说明attilax总结 1.1. 手写的优点:代码可读,对源代码中的各种错误给出友好的提示信息,用户体验高,1 1.2. 使用状态表比较简单,dfa比较麻烦1 1 ...
- Atitit 发帖机系列(8) 词法分析器v5 版本新特性说明)
Atitit 发帖机系列(8) 词法分析器v5 版本新特性说明) v5 增加对sql单引号的内部支持.可以作为string 结构调整,使用递归法重构循环发..放弃循环发. V4 java dsl词 ...
- 兼容90%标准C的词法分析器
不能分词八进制和数字类型加前/后缀的情况 拿这个词法分析器跑了一遍整个Nginx源码,基本都能正确的分出结果,后面有测试例子~ #ifndef _STATES_H_ #define _STATES_H ...
- 编译原理(简单自动词法分析器LEX)
编译原理(简单自动词法分析器LEX)源程序下载地址: http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7 ...
- java简单词法分析器(源码下载)
java简单词法分析器 : http://files.cnblogs.com/files/hujunzheng/%E7%AE%80%E5%8D%95%E8%AF%8D%E6%B3%95%E5%88%8 ...
- C# 词法分析器(一)词法分析介绍 update 2014.1.8
系列导航 (一)词法分析介绍 (二)输入缓冲和代码定位 (三)正则表达式 (四)构造 NFA (五)转换 DFA (六)构造词法分析器 (七)总结 虽然文章的标题是词法分析,但首先还是要从编译原理说开 ...
- C# 词法分析器(二)输入缓冲和代码定位
系列导航 (一)词法分析介绍 (二)输入缓冲和代码定位 (三)正则表达式 (四)构造 NFA (五)转换 DFA (六)构造词法分析器 (七)总结 一.输入缓冲 在介绍如何进行词法分析之前,先来说说一 ...
随机推荐
- easyui添加自定义验证规则
$.extend($.fn.validatebox.defaults.rules, { phone: { validator: function (value) { return /^(\d{3,4} ...
- POJ 1141 Brackets Sequence
Brackets Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 29502 Accepted: 840 ...
- 003医疗项目-关于<context:property-placeholder location="classpath:db.properties"/>的问题
项目结构如下:
- Linux Linux程序练习八
题目:自己动手实现一个守护进程,当控制台窗口关闭时还可以在后台运行.每隔一秒钟向my.log文件中插入一条记录,记录格式如下:yyyy-mm-dd hh:mi:se 记录内容,其中yyyy为年,mm为 ...
- 集锦.txt
不同的时代,有不同的需要以前,我们都以为自己可以为爱情去死,可是后来爱情死了,我们还活着. 小时候男孩子喜欢电动玩具,女孩子喜欢娃娃.长大了男孩子喜欢娃娃,女孩子喜欢电动玩具.也许这就是成长吧! 我大 ...
- Redmine 项目管理工具----完全攻略
摘要: 此篇博客涉及 安装,插件修改,插件安装,代码显示,中文乱码,SVN配置等内容,几乎覆盖所有redmine基本功能. 本机环境: Redmine 版本: 3.2.0 本机环境: win7 64位 ...
- 让Java说话-用Java实现语音引擎
让Java说话-用Java实现语音引擎 2005-11-07 10:04:09 分类: Java技术 为应用程序加上语音能力有什么好处呢?粗略地讲,是为了趣味,它适合所有注重趣味的应用,比如游戏.当然 ...
- C#脚本引擎 CS-Script 之(三)——如何部署
本文不但介绍了CS-Script如何部署,还介绍了CS-Script的部署后面的原理,并用一个框图详细介绍了部署中的各种细节. 一.获取资源 1.从官网上下载编译好的csscript资源:cs-scr ...
- Audrion小车实验过程
Audrion小车实验过程 一.实验过程 拷贝光盘文件,安装驱动及Arduino软件,观看了教学视频,明白了软件操作界面的各类按钮的含义,进行了事例的上传实验. 接下来就进行了小车的安装工作,这部分不 ...
- 创建Maven工程
一.Maven工程创建 File->New->Other,进入: 点击Next,进入: 勾选上Create a simple project(不使用骨架) 点击Next,进入: 输入项目名 ...