这学期的编译原理要做一个完整的编译器,我选择了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 ;
}
}
嗯,就是这样,这次代码不算太挫,看起来还好
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
嗯,最近感觉学计算机的学生都好苦逼的。。。。。