词法分析

词法分析过程

  • 作为第一阶段,任务是从左到右逐个字符读入。对字符流进行扫描和分解,识别出一个个单词。

分析逻辑

  • 读取测试数据
  • 转化为字符流
  • 设计算法分析字符流,产生相应档次
    以c语言为例:标识符、整数(为了简单)、分界符、运算符、注释符、关键字。
    能力有限,本人只能分解出(标识符、关键字)(分界符、运算符)

核心算法实现

标识符:或字母开头,后面、字母、数字
整数:数字开始后面都是数字

思路读取一个字符,判断是 字母 、数字、、运算符
字母,判断下一个 是否是字母、
、数字_ ,否则完成一个成分
数字,判断下一个 是否是数字,否则完成一成分
,与字母类似
default:则是运算符,判断下一个是否是字母数字
,否则完成一成分
判断字母得出的是标识符和关键字,后期需要进行分离

public ArrayList<String> token(ArrayList<Character> c){
		ArrayList<String> a = new ArrayList<String>();
		String a1 = "";
		ListIterator<Character> it =  c.listIterator();

		boolean flag=true; //标志是否完成一部分
		int a2=0;
		while(it.hasNext()){
			
			if(flag==true){//判断是否开始新的识别
				char c1 = ' ';
				c1=it.next().charValue();
				if(this.num( c1)) {
					a2=1;
				}
					
				if(this.identifier(c1)) {
					a2=2;
					
				}
					
				if(c1=='_') {
					a2=3;
				}
					
				if(c1==' ') {
					continue;
				}
				
				if(!(this.num(c1)|this.identifier(c1)|c1=='_'|c1==' '))
					a2 =0;
				it.previous();
					
			}

			switch(a2){
				case 1 :
					a1 = a1 + (it.next()).toString();
					if(this.num(( it.next()).charValue())&&it.hasNext())
						flag=false;
					else {
						flag=true;
						a.add(a1);a1="";
					}
						
					it.previous();
					break;
				case 2 :
					a1 = a1 + (it.next()).toString();
					if(this.identifier(( it.next()).charValue())&&it.hasNext())
						flag=false;
						
					else {
						flag=true;
						a.add(a1);
						a1="";
					}
					it.previous();
					break;
				case 3 :
					a1 = a1 + (it.next()).toString();
					if(this.identifier((it.next()).charValue())&&it.hasNext())
						flag=false;
					else {
						flag=true;
						a.add(a1);a1="";
					}
					it.previous();
					break;
				default  :
					char c3 = it.next();
					a1 = a1 +(new Character(c3).toString());
					char c2 = ' ';
					if(it.hasNext())
						c2 = it.next().charValue();
					if(c2==' '|this.identifier(c2 )|this.num(c2)|!(c2=='='&&(c3=='>'|c3=='!'|c3=='=')))
						{flag=true;a.add(a1);a1="";}
					else {
						flag=false;
						
					}
					if(!(c2==' '))
						it.previous();
					break;
			}
		 }
		return a;
	}

源码

package temp;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ListIterator;


interface Judge{
	//判断数字
	boolean num(char c);
	//判断标识符
	boolean identifier (char c);
	//获取测试数据,转化为String,分割单个字符存储
	ArrayList<Character> getString(String s);
	//获取相关文件数据
	HashMap<String,String> readData(String s);
	//保存当前识别的单个字符
	ArrayList<String> token(ArrayList<Character> c);
	 //获取string的name
	String getN(String s, String path);
	//获取种别
	String getT(String s, String path,String path1);
}
class Word implements Judge{
	public boolean num(char c){
		if('0'<=c && c<='9')
			return true;
		else
			return false;
			
	}
	public boolean identifier(char c){
		if(c=='_'|('a'<=c && c<='z')|('A'<=c && c<='Z'))
			return true;
		else
			return false;
	}
	public ArrayList<Character>  getString(String s){
		BufferedReader b1 = null ;
		
		ArrayList<Character> c = new ArrayList<Character>();
		try{
			InputStreamReader file = new InputStreamReader(new FileInputStream(s),"utf-8");
			b1 = new BufferedReader(file);
			int ch ;
			while((ch= b1.read())!=-1){
				if(ch==10|ch==11|ch==13|ch==9)
					c.add(' ');
				else
					c.add((char)ch);				
			}
		}catch(IOException e){
			e.printStackTrace();
		}
		
		return c;
	}
	public HashMap<String,String> readData(String s){
		BufferedReader b1 = null;
		
		HashMap<String,String> m = new HashMap<String,String>();
		try{
			InputStreamReader file = new InputStreamReader(new FileInputStream(s),"utf-8");
			b1 = new BufferedReader(file);
			String line;
			while((line=b1.readLine()) != null){
				String[] s1 = line.split(" ");
				int i = 0;
				while(i<s1.length){
					m.put(s1[i],s1[++i]);
					i++;
				}
			}
		}catch(IOException e){
			e.printStackTrace();
		}
		
		return m;
	}
	//将单个字符,识别成相应的字符串存储
	public ArrayList<String> token(ArrayList<Character> c){
		ArrayList<String> a = new ArrayList<String>();
		String a1 = "";
		ListIterator<Character> it =  c.listIterator();

		boolean flag=true; //标志是否完成一部分
		int a2=0;
		while(it.hasNext()){
			
			if(flag==true){//判断是否开始新的识别
				char c1 = ' ';
				c1=it.next().charValue();
				if(this.num( c1)) {
					a2=1;
				}
					
				if(this.identifier(c1)) {
					a2=2;
					
				}
					
				if(c1=='_') {
					a2=3;
				}
					
				if(c1==' ') {
					continue;
				}
				
				if(!(this.num(c1)|this.identifier(c1)|c1=='_'|c1==' '))
					a2 =0;
				it.previous();
					
			}

			switch(a2){
				case 1 :
					a1 = a1 + (it.next()).toString();
					if(this.num(( it.next()).charValue())&&it.hasNext())
						flag=false;
					else {
						flag=true;
						a.add(a1);a1="";
					}
						
					it.previous();
					break;
				case 2 :
					a1 = a1 + (it.next()).toString();
					if(this.identifier(( it.next()).charValue())&&it.hasNext())
						flag=false;
						
					else {
						flag=true;
						a.add(a1);
						a1="";
					}
					it.previous();
					break;
				case 3 :
					a1 = a1 + (it.next()).toString();
					if(this.identifier((it.next()).charValue())&&it.hasNext())
						flag=false;
					else {
						flag=true;
						a.add(a1);a1="";
					}
					it.previous();
					break;
				default  :
					char c3 = it.next();
					a1 = a1 +(new Character(c3).toString());
					char c2 = ' ';
					if(it.hasNext())
						c2 = it.next().charValue();
					if(c2==' '|this.identifier(c2 )|this.num(c2)|!(c2=='='&&(c3=='>'|c3=='!'|c3=='=')))
						{flag=true;a.add(a1);a1="";}
					else {
						flag=false;
						
					}
					if(!(c2==' '))
						it.previous();
					break;
			}
		 }
		return a;
	}
	public String getN(String s,String path){//该方法需实现识别整数、标识符、关键字(包括关键字和运算符和分隔符),首先识别集合范围小的最终得出补集(标识符)
		HashMap<String,String> h =readData(path);
		try {							//通过是否产生异常判断整数
			Integer.valueOf(s);	
			return "整型常量";
		}catch(Exception e) {
			if(h.get(s)==null)
				return "标识符";
		}
		return h.get(s);
	}
	public String getT(String s,String path,String path1){
		HashMap<String , String > h = readData(path);
		
		try {
			Integer.valueOf(s);
			return "11";
		}catch(Exception e) {
			if(this.getN(s, path1)=="标识符")
				return "10";
		}
		return h.get(s);
	}
}
public class Test{
	public static void main(String args[]) throws IOException{
		File file  = new File("Result.txt");
		FileWriter f = new FileWriter(file.getName().intern(),true);
		//BufferedWriter b1 =  new BufferedWriter(f);
		Word w = new Word();
		ArrayList<Character> a = w.getString("src/temp/testdata.txt");
		ArrayList<String> b = w.token(a);
		ListIterator<String> i = b.listIterator();
		while(i.hasNext()) {
			String s = i.next();
			String s1 =w.getN(s,"src/temp/name.txt")+"\t--"+w.getT(s,"src/temp/type_code.txt","src/temp/name.txt")+"\t,"+s+"\n"; 
			System.out.print(s1);
			f.write(s1);
		
		}	
		f.flush();
		f.close();
		
	}
}

小结

  • 思路整理:
    首先判断整数常量,再判断标识符(包含关键字和标识符),最后判断符号(运算符和界符)
    由于关键字和运算符、界符是有限的可以进行分离(可以采用补集的思想,先分出小集合得出大集合)
  • 总结
    本次对于词法分析的实现,加深了编译原理里的词法规则的理解,即一个合法的单词的组成规则,理解了规则通过代码实现各种类型的判断。