Token.java
package sch.cauc.edu.token; /** * * * Token * 创建人:xrzhang * 时间:2018年5月10日-上午9:11:26 * @version 1.0.0 * */ public class Token { private TokenType type; private String token; private int line; private int column; /** * * 词法记号的构造器 * @param type 词法记号的类型 * @param token 词法记号的串值 * @param line 词法记号所在的行号,用于调试和检查输出 * @param column 词法记号所在的列号,用于调试和检查输出 */ public Token(TokenType type,String token,int line,int column) { this.line = line; this.type = type; this.token = token; this.column = column; } public TokenType getType(){ return type; } public int getLine(){ return line; } public int getColumn(){ return column; } public String getLexeme(){ return token; } /** * * 输出当前词法记号的信息,包括类型、串值、行号和列号 * 方法名:toStrong * 创建人:xrzhang * 时间:2018年5月10日-上午9:16:13 * 邮件:[email protected] * @return String 字符串标识的词法记号信息 * @exception * @since 1.0.0 */ public String toString() { return type+" "+token+" ("+line+","+column+")"; } } enum TokenType{ /**忽略的词法单位**/ IGNORE, /**变量**/ IDENTIFIER, //标识符 /**常量**/ INTEGER_LITERAL, //整型常量 BOOL_TRUE, //true BOOL_FALSE, //false /**保留字**/ KEY_INT, //int KEY_BOOLEAN,//boolean KEY_WHILE, //while KEY_IF, //if KEY_ELSE, //else /**算术运算符**/ PLUS, //+ MINUS, //- TIMES, //* DIVIDE, ///除 REMAINDER,//%取模 /**关系运算符**/ LESS, //< GREATER, //> LESS_EQUAL, //<= GREATER_EQUAL, //>= NOT_EQUAL, //!= EQUAL, ///== /**逻辑运算符**/ LOGICAL_NOT, //! LOGICAL_AND, //&& LOGICAL_OR, //|| /**赋值符号**/ ASSIGN, //= /**括号**/ LPAREN, //( RPAREN, //) LBRACKET, //{ RBRACKET, //} /**界符**/ COMMA, //逗号, SEMICOLON, //分号; /**文件结尾符**/ EOF, /**注释*/ NOTE }
BlockLexer.java
package sch.cauc.edu.token; import java.io.FileReader; import java.io.IOException; import java.io.PushbackReader; /** * Block 语言的词法分析器类 * <p>你需要在实验中扩张nextToken方法,是该词法分析器真正能识别Block语言中的各 * 种词法几号并跳过注释和空白符 * </p> * BlockLexer * 创建人:xrzhang * 时间:2018年5月10日-上午8:43:55 * @version 1.0.0 * */ public class BlockLexer { /**一个可回退的读取器*/ private PushbackReader in=null; /**词法分析的当前状态*/ private int state =0; /**词法分析的初始状态*/ private int start=0; /**当前记号对应的串值*/ private StringBuffer lexeme=new StringBuffer(); /**当前面临的输入字符*/ private char c; /**当前在输入文件中的行号*/ private int line=0; /**当前在输入文件中的列号*/ private int column=0; /** * 词法分析器的构造器 * 创建一个新的实例 BlockLexer. * @param infile 输入文件名 */ public BlockLexer(String infile) { PushbackReader reader=null; try { reader=new PushbackReader(new FileReader(infile)); } catch (IOException e) { e.printStackTrace(); System.exit(-1); } in=reader; } /** * * 取得下一个字符 * 方法名:nextChar * 创建人:xrzhang * 时间:2018年5月16日-上午8:28:00 * 邮件:[email protected] void * @exception * @since 1.0.0 */ private void nextChar() { try { c=(char)in.read(); lexeme.append(c); column++; } catch (IOException e) { e.printStackTrace(); System.exit(-1); } } /** * * 回退一个字符 * 方法名:pushbackChar * 创建人:xrzhang * 时间:2018年5月16日-上午8:28:16 * 邮件:[email protected] void * @exception * @since 1.0.0 */ private void pushbackChar() { try { in.unread(lexeme.charAt(lexeme.length()-1)); lexeme.deleteCharAt(lexeme.length()-1); column--; } catch (IOException e) { e.printStackTrace(); System.exit(-1); } } /** * * 取得记号,并重置状态变量 * 方法名:getToken * 创建人:xrzhang * 时间:2018年5月16日-上午8:28:40 * 邮件:[email protected] * @param type * @return Token * @exception * @since 1.0.0 */ private Token getToken(TokenType type) { state=0; start=0; String t=lexeme.toString(); lexeme.setLength(0); return new Token(type,t,line+1,column-t.length()+1); } /** * * 扔掉一个字符 * 方法名:dropChar * 创建人:xrzhang * 时间:2018年5月16日-上午8:29:11 * 邮件:[email protected] void * @exception * @since 1.0.0 */ private void dropChar() { lexeme.setLength(0); } public Token nextToken(){ while(true){ switch(state){ case 0: //获取下一个字符 nextChar(); //判断是否空白 if(Character.isWhitespace(c)){ if(c=='\n') { line++; column = 0; } dropChar(); }else if (Character.isDigit(c)) //数字 { state=1; }else if(Character.isLetter(c)) //字母 { state =3; }else if (c=='+') { return getToken(TokenType.PLUS); }else if (c=='-') { return getToken(TokenType.MINUS); }else if (c=='*') { return getToken(TokenType.TIMES); }else if (c=='/') { nextChar(); if(c=='*') { while(true) { nextChar(); if(c=='*') { nextChar(); if(c=='/') { //return getToken(TokenType.NOTE);可选择输出注释 //line--; break; } } } }else if (c=='/') { while(true){ nextChar(); if(c=='\n') { break; } } } else{ pushbackChar(); return getToken(TokenType.DIVIDE); } }else if (c=='%') { return getToken(TokenType.REMAINDER); }else if (c=='(') { return getToken(TokenType.LPAREN); }else if (c==')') { return getToken(TokenType.RPAREN); }else if (c=='{') { return getToken(TokenType.LBRACKET); }else if (c=='}') { return getToken(TokenType.RBRACKET); }else if (c==';') { return getToken(TokenType.SEMICOLON); }else if (c=='>') { nextChar(); if(c=='='){ return getToken(TokenType.GREATER_EQUAL); }else { pushbackChar(); return getToken(TokenType.GREATER); } }else if (c=='<') { nextChar(); if(c=='='){ return getToken(TokenType.LESS_EQUAL); }else { pushbackChar(); return getToken(TokenType.LESS); } } else if (c=='!') { nextChar(); if(c=='='){ return getToken(TokenType.NOT_EQUAL); }else { pushbackChar(); return getToken(TokenType.LOGICAL_NOT); } }else if (c=='&') { nextChar(); if(c=='&'){ return getToken(TokenType.LOGICAL_AND); } } else if (c=='|') { nextChar(); if(c=='|'){ return getToken(TokenType.LOGICAL_OR); } } else if (c=='=') { nextChar(); if(c=='='){ return getToken(TokenType.EQUAL); }else { pushbackChar(); return getToken(TokenType.ASSIGN); } }else if (c==',') { return getToken(TokenType.COMMA); }else if ((c&0xff)==0xff) {//文件结尾,返回EOF return getToken(TokenType.EOF); }else { System.out.println("get nextToken error!"); System.out.println("find illegal character"+c); System.out.println("at line "+line+",column "+column); System.exit(1); } break; case 1: nextChar(); if(Character.isDigit(c)) { state=1; }else { state=2; } break; case 2: pushbackChar(); return getToken(TokenType.INTEGER_LITERAL); case 3: nextChar(); if(Character.isLetterOrDigit(c)){ state =3; }else { state=4; } break; case 4: pushbackChar(); String t=lexeme.toString(); if(t.equalsIgnoreCase("int")){ return getToken(TokenType.KEY_INT); }else if (t.equalsIgnoreCase("boolean")) { return getToken(TokenType.KEY_BOOLEAN); }else if (t.equalsIgnoreCase("while")) { return getToken(TokenType.KEY_WHILE); } else if (t.equalsIgnoreCase("if")) { return getToken(TokenType.KEY_IF); }else if (t.equalsIgnoreCase("else")) { return getToken(TokenType.KEY_ELSE); } else { return getToken(TokenType.IDENTIFIER); } default: System.out.println("get nextToken error!"); System.out.println("find illegal state:"+state); System.exit(1); } } } }
Lab1Main.java
package sch.cauc.edu.token; /** * * 测试词法分析程序 * Lab1Main * 创建人:xrzhang * 时间:2018年5月10日-上午9:20:24 * @version 1.0.0 * */ public class Lab1Main { /** * * 方法名:main * 创建人:xrzhang * 时间:2018年5月10日-上午9:22:54 * 邮件:[email protected] * @param args void * @exception * @since 1.0.0 */ public static void main(String[] args) { BlockLexer l =new BlockLexer("test/expr.txt"); //BlockLexer l =new BlockLexer("test/expr2.txt"); Token s=l.nextToken(); while(s.getType()!=TokenType.EOF){ System.out.println(s); s=l.nextToken(); } } }
测试文件:expr.txt/*comment lines
*until here*/
{
int i1,i2,i3;
i1=14;
i2=i1+2*3;
i3=i1-5*(i2%2)+5;
if(i1==i4&&i2>=20){
i3=i3+1;}
else{
i3=i3+2;}
}
测试文件:expr2.txt{
//define two variables
int m,n;
m=12;n=21;
if(m<n){
int t;
t=m;m=n;n=t;
}
int r;
r=m%n;
while(r!=0){m=n;n=r;r=m%n;}
}