包 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. 027医疗项目-模块二:药品目录的导入导出-导入功能的Action的编写

    前一篇文章我们写了Service层,这篇文章我们写一下Action层. 实现的功能: 1:我们先下载模板:然后按照模板里面的规则,插入数据.比如存在d盘. 2:然后浏览找到那个文件,上传上去. 然后把 ...

  2. 【转】【Asp.Net】了解使用 ASP.NET AJAX 进行局部页面更新

    简介Microsoft的 ASP.NET 技术提供了一个面向对象.事件驱动的编程模型,并将其与已编译代码的优势结合起来.但其服务器端的处理模型仍存在技术本身所固有的几点不足: 进行页面更新需要往返服务 ...

  3. 使用SilverLight开发区域地图分析模块

    本人最近接收开发一个代码模块,功能主要是在页面上显示安徽省市地图,并且在鼠标移动到地图某市区域时,显示当前区域的各类信息等,一开始准备用百度地图,高德地图等地图工具进行开发,最后发现都不适合进行此类开 ...

  4. IBatis.Net学习笔记六--再谈查询

    在IBatis.Net学习笔记五--常用的查询方式 中我提到了一些IBatis.Net中的查询,特别是配置文件的写法. 后来通过大家的讨论,特别是Anders Cui 的提醒,又发现了其他的多表查询的 ...

  5. VS2010报错无法编译:LINK : fatal error LNK1123: failure during conversion to COFF: file invalid

    win7 64位 专业版 + vs2010 从vc6.0下转过来的一个项目,突然遇到这个问题. 解决方案: 用C:\Windows\winsxs\x86_netfx-cvtres_for_vc_and ...

  6. AWS S3使用小结

    使用场景一:储存网站的图片,并能被任何人访问 1. 创建一个bucket,名字与需要绑定的域名一致. 例如,根域名是mysite.com,希望把所有图片放在pic.mysite.com下面,访问的时候 ...

  7. Linux第七次实验笔记

    #期中总结 习题总结与分析 填空:Linux Bash中,Ctrl+a快捷键的作用是(将光标移至输入行头,相当于Home键). [ctrl]+u 从游标处向前删除指令串 [ctrl]+k 从游标处向后 ...

  8. 小甲鱼第51讲:《__name__="__main__"、搜索路径和包》课后练习题

    测试题: 0. __name__属性指的是在调用该模块的时候调用的函数名称,方便在模块的被调用的时候,模块内部被调用的函数不会被运行. 1. 当模块作为主程序运行的时候,__name__属性的值是“_ ...

  9. (旧)子数涵数·PS ——翻页效果

    一.首先在网络上下载一张图片,作为素材.这是我下载的素材,至于为什么选择这张照片呢,当然不是因为自己的一些羞羞的念头啦. 二.打开Photoshop,我使用的版本是CS3(因为CS3所占的磁盘空间较小 ...

  10. OWIN-WebAPI-Windows Service

    tks: https://github.com/danesparza/OWIN-WebAPI-Service add 2015 0717:http://kb.cnblogs.com/page/5092 ...