词法分析器——java实现

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;}
}



猜你喜欢

转载自blog.csdn.net/as1072966956/article/details/80332988