包 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不是词法单元他们将在抽象语法树中使用。

类Token和Num增加了方法toString;
 
   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 词法分析器的更多相关文章

  1. sizzle分析记录:词法分析器(tokenize)

    词法分析器(tokenize)? 词法分析器又称扫描器.词法分析是指将我们编写的文本代码流解析为一个一个的记号,分析得到的记号以供后续语法分析使用. sizzle引入了tokenize这个概念,意义? ...

  2. C# 词法分析器(五)转换 DFA

    系列导航 (一)词法分析介绍 (二)输入缓冲和代码定位 (三)正则表达式 (四)构造 NFA (五)转换 DFA (六)构造词法分析器 (七)总结 在上一篇文章中,已经得到了与正则表达式等价的 NFA ...

  3. 用词法分析器Flex过滤日志

    每日构造中,我的项目中 Visual Studio 的 MakeFile 后会产生大量信息,如下 Microsoft (R) Visual Studio Version 10.0.40219.1.Co ...

  4. Atitit 词法分析器的设计最佳实践说明attilax总结

    Atitit 词法分析器的设计最佳实践说明attilax总结 1.1. 手写的优点:代码可读,对源代码中的各种错误给出友好的提示信息,用户体验高,1 1.2. 使用状态表比较简单,dfa比较麻烦1 1 ...

  5. Atitit 发帖机系列(8)  词法分析器v5 版本新特性说明)

    Atitit 发帖机系列(8)  词法分析器v5 版本新特性说明) v5  增加对sql单引号的内部支持.可以作为string 结构调整,使用递归法重构循环发..放弃循环发. V4 java dsl词 ...

  6. 兼容90%标准C的词法分析器

    不能分词八进制和数字类型加前/后缀的情况 拿这个词法分析器跑了一遍整个Nginx源码,基本都能正确的分出结果,后面有测试例子~ #ifndef _STATES_H_ #define _STATES_H ...

  7. 编译原理(简单自动词法分析器LEX)

    编译原理(简单自动词法分析器LEX)源程序下载地址:  http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7 ...

  8. java简单词法分析器(源码下载)

    java简单词法分析器 : http://files.cnblogs.com/files/hujunzheng/%E7%AE%80%E5%8D%95%E8%AF%8D%E6%B3%95%E5%88%8 ...

  9. C# 词法分析器(一)词法分析介绍 update 2014.1.8

    系列导航 (一)词法分析介绍 (二)输入缓冲和代码定位 (三)正则表达式 (四)构造 NFA (五)转换 DFA (六)构造词法分析器 (七)总结 虽然文章的标题是词法分析,但首先还是要从编译原理说开 ...

  10. C# 词法分析器(二)输入缓冲和代码定位

    系列导航 (一)词法分析介绍 (二)输入缓冲和代码定位 (三)正则表达式 (四)构造 NFA (五)转换 DFA (六)构造词法分析器 (七)总结 一.输入缓冲 在介绍如何进行词法分析之前,先来说说一 ...

随机推荐

  1. java的IO操作之--RandomAccessFile

    目标: 1)掌握RandomAccessFile类的作用. 2)用RandomAccessFile读取指定位置的数据. 具体内容 RandomAccessFile类的主要功能是完成随机读取功能,可以读 ...

  2. Myeclipse+maven时Tomcat部署时maven的依赖文件不能部署到Tomcat上

    解决办法:

  3. C语言 数组做函数参数退化为指针的技术推演

    //数组做函数参数退化为指针的技术推演 #include<stdio.h> #include<stdlib.h> #include<string.h> //一维数组 ...

  4. 网站如何启用SSL安全证书?IIS7启用新建Https:/

    网站使用SSL,通过SSL证书申请,然后导入之后.我们需要对网站进行设置才能正常使用SSL证书,具体如何操作让网站启用SSL呢,本经验以一个网站添加SSL主机头的方式为例来,网站启用SSL服务器安全证 ...

  5. Itextsharp下根据Echarts图像生成pdf

    本文介绍如何在C#中使用ItextSharp生成带echarts图表的pdf 一.生成一个简单的pdf 后台代码 publicActionResultGetPdf() { MemoryStream m ...

  6. 如何部署Iveely.Computing分布式实时计算系统

    Iveely.Computing是参考Storm的分布式实时计算系统的部分原理,用纯Java实现的轻量级.迷你型,适合于搜索引擎的实时计算系统, Iveely 搜索引擎是一款基于Iveely.Comp ...

  7. 端口扫描之王——nmap入门精讲(二)

    接着讲上节的内容,上节中提到了一个时间优化的问题是使用参数-n,通过不解析地址来进行优化时间的,但是优化时间的方法还有很多,比如说我们可以通过时间优化(0-5),指定单位时间内的探针数,设置组的大小 ...

  8. [转载]使用HttpWebRequest进行请求时发生错误:基础连接已关闭,发送时发生错误处理

    转载,原文来自 http://blog.csdn.net/hawksoft/article/details/21776009 最近调试原来的微信模拟登陆时发生了“基础连接已关闭,发送时发生错误”的错误 ...

  9. 23.C#Queryable的扩展方法(十二章12.1-12.2)

    今天要写的知识还真心有点绕呢,对于第一节的内容,其实是把原先在内存中的数据源,换成了从数据库中提取出来的数据.从代码的使用方式上是一样的,直接跳过,来看看IEnumerable和IQueryable的 ...

  10. MySQL 5.6 my.cnf 参数说明

    # 以下选项会被MySQL客户端应用读取. # 注意只有MySQL附带的客户端应用程序保证可以读取这段内容. # 如果你想你自己的MySQL应用程序获取这些值. # 需要在MySQL客户端库初始化的时 ...