一个简略词法分析器的实现代码(java实现)

一个简单词法分析器的实现代码(java实现)

一个简单词法分析器的实现代码(java实现)

 

Main.java

[java] view plaincopyprint?
  1. /* 
  2.  * 主程序 
  3.  */  
  4. import java.io.*;  
  5. import lexer.*;  
  6.   
  7. public class Main {  
  8.     public static void main(String[] args) throws IOException {  
  9.         Lexer lexer = new Lexer();  
  10.           
  11.         while (lexer.getReaderState() == false) {  
  12.             lexer.scan();  
  13.         }  
  14.           
  15.         /* 保存相关信息 */  
  16.         lexer.saveTokens();  
  17.         lexer.saveSymbolsTable();  
  18.           
  19.     }  
  20. }  

 

Lexer.java

[java] view plaincopyprint?
  1. package lexer;  
  2.   
  3. import java.io.*;  
  4. import java.util.*;  
  5.   
  6. import symbols.*;  
  7.   
  8. public class Lexer {  
  9.     public static int line = 1;     /* 记录行号 */  
  10.     char peek = ' ';        /* 下一个读入字符 */  
  11.     Hashtable<String, Word> words =   
  12.         new Hashtable<String, Word>();  
  13.     /* 符号表 */  
  14.     private Hashtable<Token, String> table =   
  15.         new Hashtable<Token, String>();  
  16.     /* token序列 */  
  17.     private List<String> tokens =   
  18.         new LinkedList<String> ();  
  19.     /* 读取文件变量 */  
  20.     BufferedReader reader = null;   
  21.     /* 保存当前是否读取到了文件的结尾  */  
  22.     private Boolean isEnd = false;  
  23.       
  24.     /* 是否读取到文件的结尾 */  
  25.     public Boolean getReaderState() {  
  26.         return this.isEnd;  
  27.     }  
  28.       
  29.     /* 保存存储在table中的 */  
  30.     public void saveSymbolsTable() throws IOException {  
  31.         FileWriter writer = new FileWriter("符号表.txt");  
  32.         writer.write("[符号]          [符号类型信息]\n");  
  33.         writer.write("\r\n");  
  34.           
  35.         Enumeration<Token> e = table.keys();  
  36.         while( e.hasMoreElements() ){  
  37.             Token token = (Token)e.nextElement();  
  38.             String desc = table.get(token);  
  39.               
  40.             /* 写入文件 */  
  41.             writer.write(token + "\t\t\t" + desc + "\r\n");  
  42.         }  
  43.               
  44.         writer.flush();  
  45.     }  
  46.       
  47.     /* 保存Tokens */  
  48.     public void saveTokens() throws IOException {  
  49.         FileWriter writer = new FileWriter("Tokens表.txt");  
  50.         writer.write("[符号]  \n");  
  51.         writer.write("\r\n");  
  52.           
  53.         for(int i = 0; i < tokens.size(); ++i) {  
  54.             String tok = (String)tokens.get(i);  
  55.               
  56.             /* 写入文件 */  
  57.             writer.write(tok + "\r\n");  
  58.         }     
  59.               
  60.         writer.flush();  
  61.     }  
  62.       
  63.     void reserve(Word w) {  
  64.         words.put(w.lexme, w);  
  65.     }  
  66.       
  67.     /* 
  68.      * 构造函数中将关键字和类型添加到hashtable words中 
  69.      */  
  70.     public Lexer() {  
  71.         /* 初始化读取文件变量 */  
  72.         try {  
  73.             reader = new BufferedReader(new FileReader("输入.txt"));  
  74.         }  
  75.         catch(IOException e) {  
  76.             System.out.print(e);  
  77.         }  
  78.           
  79.           
  80.         /* 关键字 */  
  81.         this.reserve(new Word("if", Tag.IF));  
  82.         this.reserve(new Word("then", Tag.THEN));  
  83.         this.reserve(new Word("else", Tag.ELSE));  
  84.         this.reserve(new Word("while", Tag.WHILE));  
  85.         this.reserve(new Word("do", Tag.DO));  
  86.           
  87.         /* 类型 */  
  88.         this.reserve(Word.True);  
  89.         this.reserve(Word.False);  
  90.         this.reserve(Type.Int);  
  91.         this.reserve(Type.Char);  
  92.         this.reserve(Type.Bool);  
  93.         this.reserve(Type.Float);  
  94.     }  
  95.       
  96.     public void readch() throws IOException {  
  97.         /* 这里应该是使用的是 */  
  98.         peek = (char)reader.read();  
  99.         if((int)peek == 0xffff){  
  100.             this.isEnd = true;  
  101.         }  
  102.         // peek = (char)System.in.read();   
  103.     }  
  104.       
  105.     public Boolean readch(char ch) throws IOException {  
  106.         readch();  
  107.         if (this.peek != ch) {  
  108.             return false;  
  109.         }  
  110.           
  111.         this.peek = ' ';  
  112.         return true;  
  113.     }  
  114.       
  115.     public Token scan() throws IOException {  
  116.         /* 消除空白 */   
  117.         for( ; ; readch() ) {  
  118.             if(peek == ' ' || peek == '\t')  
  119.                 continue;  
  120.             else if (peek == '\n')   
  121.                 line = line + 1;  
  122.             else  
  123.                 break;  
  124.         }  
  125.           
  126.         /* 下面开始分割关键字,标识符等信息  */  
  127.         switch (peek) {  
  128.         /* 对于 ==, >=, <=, !=的区分使用状态机实现 */  
  129.         case '=' :  
  130.             if (readch('=')) {  
  131.                 tokens.add("==");  
  132.                 return Word.eq;   
  133.             }  
  134.             else {  
  135.                 tokens.add("=");  
  136.                 return new Token('=');  
  137.             }  
  138.         case '>' :  
  139.             if (readch('=')) {  
  140.                 tokens.add(">=");  
  141.                 return Word.ge;  
  142.             }  
  143.             else {  
  144.                 tokens.add(">");  
  145.                 return new Token('>');  
  146.             }  
  147.         case '<' :  
  148.             if (readch('=')) {  
  149.                 tokens.add("<=");  
  150.                 return Word.le;  
  151.             }  
  152.             else {  
  153.                 tokens.add("<");  
  154.                 return new Token('<');  
  155.             }  
  156.         case '!' :  
  157.             if (readch('=')) {  
  158.                 tokens.add("!=");  
  159.                 return Word.ne;  
  160.             }  
  161.             else {  
  162.                 tokens.add("!");  
  163.                 return new Token('!');  
  164.             }     
  165.         }  
  166.           
  167.         /* 下面是对数字的识别,根据文法的规定的话,这里的 
  168.          * 数字只要是能够识别整数就行. 
  169.          */  
  170.         if(Character.isDigit(peek)) {  
  171.             int value = 0;  
  172.             do {  
  173.                 value = 10 * value + Character.digit(peek, 10);  
  174.                 readch();  
  175.             } while (Character.isDigit(peek));  
  176.               
  177.             Num n = new Num(value);  
  178.             tokens.add(n.toString());  
  179.             //table.put(n, "Num");   
  180.             return n;  
  181.         }  
  182.           
  183.         /* 
  184.          * 关键字或者是标识符的识别 
  185.          */  
  186.         if(Character.isLetter(peek)) {  
  187.             StringBuffer sb = new StringBuffer();  
  188.               
  189.             /* 首先得到整个的一个分割 */  
  190.             do {  
  191.                 sb.append(peek);  
  192.                 readch();  
  193.             } while (Character.isLetterOrDigit(peek));  
  194.               
  195.             /* 判断是关键字还是标识符 */  
  196.             String s = sb.toString();  
  197.             Word w = (Word)words.get(s);  
  198.               
  199.             /* 如果是关键字或者是类型的话,w不应该是空的 */  
  200.             if(w != null) {  
  201.                 // table.put(w, "KeyWord or Type");   
  202.                 tokens.add(w.toString());  
  203.                 return w; /* 说明是关键字 或者是类型名 */  
  204.             }  
  205.               
  206.             /* 否则就是一个标识符id */  
  207.             w = new Word(s, Tag.ID);  
  208.             tokens.add(w.toString());  
  209.             table.put(w, "id");  
  210.             words.put(s,  w);  
  211.               
  212.             return w;  
  213.         }  
  214.           
  215.         /* peek中的任意字符都被认为是词法单元返回 */  
  216.         Token tok  = new Token(peek);  
  217.         // table.put(tok, "Token or Seprator");   
  218.         if ((int)peek != 0xffff )   
  219.             tokens.add(tok.toString());  
  220.         peek = ' ';  
  221.           
  222.         return tok;  
  223.     }  
  224. }  

 

Num.java

[java] view plaincopyprint?
  1. package lexer;  
  2.   
  3. public class Num extends Token{  
  4.     public final int value;  
  5.       
  6.     public Num(int v) {  
  7.         super(Tag.NUM);  
  8.         this.value = v;  
  9.     }  
  10.       
  11.     public String toString() {  
  12.         return  "" + value;  
  13.     }  
  14. }  

 

Tag.java

[java] view plaincopyprint?
  1. package lexer;  
  2.   
  3. public class Tag {  
  4.     public final static int  
  5.         AND     = 256,  
  6.         BASIC   = 257,  
  7.         BREAK   = 258,  
  8.         DO      = 259,  
  9.         ELSE    = 260,  
  10.         EQ      = 261,  /* == */  
  11.         FALSE   = 262,  
  12.         GE      = 263,  
  13.         ID      = 264,  
  14.         IF      = 265,  
  15.         INDEX   = 266,  
  16.         LE      = 267,  
  17.         MINUS   = 268,  
  18.         NE      = 269,  
  19.         NUM     = 270,  
  20.         OR      = 271,  
  21.         REAL    = 272,  
  22.         TEMP    = 273,  
  23.         TRUE    = 274,  
  24.         WHILE   = 275,  
  25.         /* 后面添加 */  
  26.         THEN    = 276;  
  27. }  

 

Token.java

[java] view plaincopyprint?
  1. package lexer;  
  2.   
  3. public class Token {  
  4.     public final int tag;  
  5.       
  6.     public Token(int t) {  
  7.         this.tag = t;  
  8.     }  
  9.       
  10.     public String toString() {  
  11.         return "" + (char)tag;  
  12.     }  
  13.       
  14.     public static void main(String[] args) {  
  15.         Token tok = new Token('a');  
  16.         System.out.println(tok);  
  17.     }  
  18. }  

 

Word.java

[java] view plaincopyprint?
  1. /* 
  2.  * 类word用于管理保留字,标识符以及像&&这样的复合单词元素 。 
  3.  */  
  4. package lexer;  
  5.   
  6. public class Word extends Token {  
  7.     public String lexme = "";  
  8.       
  9.     public Word (String s, int t) {  
  10.         super(t);  
  11.         this.lexme = s;  
  12.     }  
  13.       
  14.     public String toString() {  
  15.         return this.lexme;  
  16.     }  
  17.       
  18.     public static final Word   
  19.         and = new Word("&&", Tag.AND),  
  20.         or = new Word("||", Tag.OR),  
  21.         eq = new Word ("==", Tag.EQ),  
  22.         ne = new Word("!=", Tag.NE),  
  23.         le = new Word("<=", Tag.LE),  
  24.         ge = new Word(">=", Tag.GE),  
  25.         minus = new Word("minus", Tag.MINUS),  
  26.         True = new Word("true", Tag.TRUE),  
  27.         False = new Word("false", Tag.FALSE),  
  28.         temp = new Word("t", Tag.TEMP);  
  29. }  

 

Type.java

[java] view plaincopyprint?
  1. /* 
  2.  * 说明数据类型 
  3.  */  
  4. package symbols;  
  5.   
  6. import lexer.*;  
  7.   
  8. public class Type extends Word{  
  9.     public Type(String s, int tag) {  
  10.         super(s, tag);  
  11.     }  
  12.       
  13.     public static final Type  
  14.         Int = new Type("int", Tag.BASIC),  
  15.         Float = new Type("float", Tag.BASIC),  
  16.         Char = new Type ("char", Tag.BASIC),  
  17.         Bool =  new Type("bool", Tag.BASIC);  
  18.  }