词法分析器

这学期的编译原理要做一个完整的编译器,我选择了SNL,这两天把词法分析器写了,话说用java正不习惯;稍微注意了一下写注释

好吧,这个词法分析器其实很简单,就是切词,然后把切出来的词归类,分成保留字,符号,变量等等

从一个source.txt中读取源程序,然后产生一个token链

好吧直接上代码:

scanner.java:(主要)

 

/**********************/
/* auther:    lishicao*/
/* date  :    2013.3.7*/
/* lexical analyzer   */
/**********************/

package lex;

import java.io.*   ; 
import common.Enum ;
import common.Enum.lexType;
import common.Node ; 
import java.util.*;


public class scanner {
	
	static int line = 1 , row = 1 , cur = 0 ;
	static String Buffer ;
	
	public static void main( String[] args ) throws Exception {
		String filePath = "source.txt" ;
		ArrayList< Node > TokenList = new ArrayList< Node > () ;
		Buffer = readTxt( filePath ) ;
		TokenList = getTokenList() ; 
		for( int i = 0 ; i < TokenList.size() ; i ++ ){
			System.out.println( TokenList.get(i).getData() + " " + TokenList.get(i).getType() 
								+ " 行:" + TokenList.get(i).getLine() + " 列:" + TokenList.get(i).getRow() ) ;
		}
	}
	
	
	/************************************/
	/*传入文件地址(string),读入源文件,返回string*/
	/*       功能是将源文件读入Buffer中                       */
	/************************************/
	public static String readTxt( String filePath ) throws Exception {
		FileReader file = new FileReader( filePath ) ;
		BufferedReader reader = new BufferedReader( file ) ;
		String temp = "" ;
		while( reader.ready() ) {
			temp += reader.readLine() ;
			temp += '\n' ;
		}
		return temp ;
	}
	
	
	/************************************/
	/*  取得下一个非空字符,并将该字符的下标赋值给cur */
	/*          如果到了文件结束返回‘\0’       */
	/************************************/
	public static char getNextChar() {
		int   i  ;
		char  ch ;
		if( cur == Buffer.length() - 1 ) {
			ch = '\0' ;
			return ch ; 
		}
		for( i = cur ; i < Buffer.length() ; i ++ ) {
			if( Buffer.charAt( i ) == '\n' ) {
				line ++ ;
				row = 1 ;
			}
			else if( Buffer.charAt( i ) == ' ' ) row ++ ;
			else if( Buffer.charAt( i ) == '\t' ) row += 4 ;
			else break ;
		}
		ch = Buffer.charAt( i ) ;
		cur = i ;
		return ch ;
	}
	
	
	/***********************************/
	/*	        	识别数字                                         */
	/***********************************/
	public static String isNumber( char ch ){
		String res = "" ;
		int  temp = cur ; 
		while( Buffer.charAt( temp ) >= '0' && Buffer.charAt( temp ) <= '9' ){
			res += Buffer.charAt( temp ) ; 
			temp ++ ;
			row  ++ ;
		}
		if( ( Buffer.charAt( temp ) >= 'a' && Buffer.charAt( temp ) <= 'z' ) || ( Buffer.charAt( temp ) >= 'A' && Buffer.charAt( temp ) <= 'Z' ) )
			res = null ;
		cur = temp ;
		return res ; 
	}
	
	
	/***********************************/
	/*			识别标示符或者保留字                             */
	/***********************************/
	public static String isName( char ch ){
		String res = "" ;
		int  temp = cur ; 
		while( ( Buffer.charAt( temp ) >= '0' && Buffer.charAt( temp ) <= '9' ) || ( Buffer.charAt( temp ) >= 'a' && Buffer.charAt( temp ) <= 'z' ) 
				|| ( Buffer.charAt( temp ) >= 'A' && Buffer.charAt( temp ) <= 'Z' ) ) {
			res += Buffer.charAt( temp ) ;
			temp ++ ;
			row  ++ ;
		}
		cur = temp ;
		return res ;
	}
	
	
	/***********************************/
	/*			识别具体是哪个保留字		   */
	/***********************************/
	public static lexType recognizeName( String name ){
		switch( name ) {
			case "program"   : return Enum.lexType.PROGRAM   ;
			case "type"      : return Enum.lexType.TYPE      ;
			case "var"       : return Enum.lexType.VAR       ;
			case "procedure" : return Enum.lexType.PROCEDURE ;
			case "begin"     : return Enum.lexType.BEGIN     ;
			case "end"		 : return Enum.lexType.END       ;
			case "array"	 : return Enum.lexType.ARRAY	 ;
			case "of"		 : return Enum.lexType.OF 		 ; 
			case "record"    : return Enum.lexType.RECORD    ;
			case "if"		 : return Enum.lexType.IF        ;
			case "then"		 : return Enum.lexType.THEN		 ; 
			case "else"		 : return Enum.lexType.ELSE 	 ;
			case "fi"		 : return Enum.lexType.FI		 ;
			case "while"	 : return Enum.lexType.WHILE	 ;
			case "do"		 : return Enum.lexType.DO		 ; 
			case "endwh"	 : return Enum.lexType.ENDWH	 ;
			case "read"		 : return Enum.lexType.READ		 ; 
			case "write"	 : return Enum.lexType.WRITE	 ; 
			case "return"	 : return Enum.lexType.RETURN	 ;
			case "integer"	 : return Enum.lexType.INTEGER	 ; 
			case "char"		 : return Enum.lexType.CHAR		 ;
			default          : return Enum.lexType.ID		 ; 		
		} 
	}
	
	
	/***********************************/
	/*          识别具体是哪个符号                                       */
	/***********************************/
	public static lexType recognizeSymbol( char symbol ) {
		switch( symbol ) {
			case '+'		 : return Enum.lexType.PLUS		 ; 
			case '-'		 : return Enum.lexType.MINUS	 ; 
			case '*'		 : return Enum.lexType.TIMES	 ;
			case '/'		 : return Enum.lexType.OVER		 ;
			case '('		 : return Enum.lexType.LPAREN	 ; 
			case ')'		 : return Enum.lexType.RPAREN	 ;
			case '.'		 : return Enum.lexType.DOT		 ; 
			case '['		 : return Enum.lexType.LMIDPAREN ;
			case ']'		 : return Enum.lexType.RMIDPAREN ; 
			case ';'		 : return Enum.lexType.SEMI		 ; 
			case ':'		 : return Enum.lexType.COLON	 ; 
			case ','		 : return Enum.lexType.COMMA	 ; 
			case '<'		 : return Enum.lexType.LT		 ; 
			case '='		 : return Enum.lexType.EQ		 ; 
			case '\''		 : return Enum.lexType.CHARC	 ;
			case '\0' 		 : return Enum.lexType.ENDFILE	 ;
		}
		return null ;
	}
	
	
	/************************************/
	/*         得到下一个 token             */
	/************************************/
	public static Node getNextToken() {
		Node now = new Node() ;
		char c ;
		c = getNextChar() ;
		if( c == '\0' ) return null ;
		now.setLine( line ) ;
		now.setRow(  row  ) ;
		if( c >= '0' && c <= '9' ){
			String temp = isNumber( c ) ;
			if( temp != null ) {
				now.setData( temp ) ;
				now.setType( Enum.lexType.INTC ) ;
			}
			else now = null ;
		}
		else if( ( c >= 'a' && c<= 'z' ) || ( c >= 'A' && c <= 'Z' ) ){
			String temp = isName( c ) ;
			if( temp != null ) now.setData( temp ) ;
			else now = null ;
			now.setType( recognizeName( temp ) ) ;
		}
		else if( c == '{' ) {
			int  i ;
			int  num = 1 ;
			for( i = cur + 1 ; i < Buffer.length() ; i ++ ) {
				if( Buffer.charAt( i ) == '{' ) num ++ ;
				else if( Buffer.charAt( i ) == '}' ) num -- ;
				if( Buffer.charAt( i ) == '\n' ) {
					line ++ ;
					row = 1 ;
				}
				else if( Buffer.charAt( i ) == '\t' ) row += 4 ;
				else row ++ ;
				if( num == 0 ) break ;
			}
			cur = i + 1 ;
			now.setData( null ) ;
		}
		else{
			if( c == ':' && Buffer.charAt( cur + 1 ) == '=' ) {
				now.setData( ":=" ) ;
				now.setType( Enum.lexType.ASSIGN ) ;
				cur += 2 ; row += 2 ;
			}
			else if( c == '.' && Buffer.charAt( cur + 1 ) == '.' ) {
				now.setData( ".." ) ;
				now.setType( Enum.lexType.UNDERANGE ) ;
				cur += 2 ; row += 2 ; 
			}
			else {
				String temp = new String() ;
				temp += c ;
				now.setType( recognizeSymbol( c ) ) ;
				now.setData( temp ) ;
				cur ++ ; row ++ ;
			}
		}
		return now ;
	}


	/************************************/
	/*          得到一个tokenlist          */
	/************************************/
	public static ArrayList< Node > getTokenList() {
		ArrayList< Node > TokenList = new ArrayList < Node > () ;
		while( true ) {
			Node temp = new Node () ; 
			temp = getNextToken() ;
			if( temp == null ) break ;
			if( temp.getData() == null ) continue ; 
			TokenList.add( temp ) ;
		}
		return TokenList ;
	}

}

 

node.java :

package common;

import common.Enum.lexType;

public class Node {
	String Data ;
	int    Line , Row ;
	lexType    type ;
	public Node(){
	}
	public String getData() {
		return Data;
	}
	public void setData(String data) {
		Data = data;
	}
	public int getLine() {
		return Line;
	}
	public void setLine(int line) {
		Line = line;
	}
	public int getRow() {
		return Row;
	}
	public void setRow(int row) {
		Row = row;
	}
	public lexType getType() {
		return type;
	}
	public void setType(lexType integer) {
		this.type = integer;
	}
}


 

Enum.java:

 

package common;

public interface Enum {
	public enum lexType{
		/* 簿记单词符号 */
	    ENDFILE,	ERROR,
		/* 保留字 */
	    PROGRAM,	PROCEDURE,	TYPE,	VAR,		IF,
		THEN,		ELSE,		FI,		WHILE,		DO,
		ENDWH,		BEGIN,		END,	READ,		WRITE,
		ARRAY,		OF,			RECORD,	RETURN, 

		INTEGER,	CHAR,
		/* 多字符单词符号 */
	    ID,			INTC,		CHARC,
	    /*特殊符号 */
		ASSIGN,		EQ,			LT,		PLUS,		MINUS,
		TIMES,		OVER,		LPAREN,	RPAREN,		DOT,
		COLON,		SEMI,		COMMA,	LMIDPAREN,	RMIDPAREN,
		UNDERANGE ; 
	}
}


 


嗯,就是这样,这次代码不算太挫,看起来还好

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

嗯,最近感觉学计算机的学生都好苦逼的。。。。。

你可能感兴趣的:(风雨飘摇路)