实验目的:对循环语句和条件判断语句编写词法分析编译程序,只能通过一遍扫描完成。
实验要求:
- 关键字:
for if then else while do until int input output
所有关键字都是小写。
(2)运算符和分隔符:
: = + - * / < > <= <> >= ; ( ) #
- 其他标识符(ID)和整型常数(NUM),通过以下模式定义:
ID=letter(letter | digit)*
NUM=digit digit*
(4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM、运算符、分隔符和关键字,词法分析阶段通常被忽略。
各种词法单元对应的词法记号如下:
词法单元 | 词法记号 | 词法单元 | 词法记号 |
for | 1 | : | 17 |
if | 2 | := | 18 |
then | 3 | < | 20 |
else | 4 | <> | 21 |
while | 5 | <= | 22 |
do | 6 | > | 23 |
letter(letter+digit)* | 10 | >= | 24 |
digit digit* | 11 | = | 25 |
+ | 13 | ; | 26 |
- | 14 | ( | 27 |
* | 15 | ) | 28 |
/ | 16 | # | 0 |
until | 29 | int | 30 |
input | 31 | output | 32 |
浮点数 33
词法分析程序的功能
输入:源程序
输出:二元组(词法记号,属性值/其在符号表中的位置)构成的序列。
例如:对源程序
int x:=5; if (x>0) then x:=2*x+1/3; else x:=2/x; #
经词法分析后输出如下序列:
(30, int)(10,’x’)(18, :=) (11,5) (26, ;) (2, if ) (27,( )……
我的思路:
状态转换图如下:
其中1,7,8,9,10是确定终态,其他是非确定终态。
用move函数模拟状态转换。
word类(封装词法分析相关的函数):
import java.util.HashMap;
public class word {
//关键字、操作符都与对应的状态号形成映射,便于查找
HashMap<String,Integer> op = new HashMap<String, Integer>(){{
put("+",13);
put("-",14);
put("*",15);
put("/",16);
put(":",17);
put(":=",18);
put("<",20);
put("<>",21);
put("<=",22);
put(">",23);
put(">=",24);
put("=",25);
put(";",26);
put("(",27);
put(")",28);
put("#",0);
}};
HashMap<String,Integer> kw = new HashMap<String,Integer>(){{
put("for",1);
put("if",2);
put("then",3);
put("else",4);
put("while",5);
put("do",6);
put("until",29);
put("int",30);
put("input",31);
put("output",32);
}};
//判断扫描到的字符串是不是映射中已有的操作符
int matchOp(String ope){
if(op.containsKey(ope))
return op.get(ope);
else
return -1;
}
//判断扫描到的字串是不是映射中已有的关键字
int matchKw(String kwo){
if(kw.containsKey(kwo))
return kw.get(kwo);
else
return -1;
}
//模拟状态转换
int Move(int beg,char c){
int en = 0;
int c_asc = (int)c;
switch(beg){
case 0:
if(c_asc>=48&&c_asc<=57)
en = 6;
else if((c_asc>=65&&c_asc<=90)||(c_asc>=97&&c_asc<=122))
en = 11;
else if(c==' ')
en = 1;
else{
if(c==':')
en = 4;
else if(c=='>')
en = 3;
else if(c=='<')
en = 2;
else
en = 5;}
break;
case 2:
if(c=='>')
en = 7;
else if(c=='=')
en = 8;
else
en = 1;
break;
case 3:
if(c=='=')
en = 9;
else
en = 1;
break;
case 4:
if(c=='=')
en = 10;
else
en = 1;
break;
case 5:
en = 1;
break;
case 6:
if(c_asc>=48&&c_asc<=57)
en = 6;
else if(c=='.')
en = 14;
else
en = 1;
break;
case 11:
if(c_asc>=48&&c_asc<=57)
en = 13;
else if((c_asc>=65&&c_asc<=90)||(c_asc>=97&&c_asc<=122))
en = 12;
else
en = 1;
break;
case 12:
if(c_asc>=48&&c_asc<=57)
en = 13;
else if((c_asc>=65&&c_asc<=90)||(c_asc>=97&&c_asc<=122))
en = 12;
else
en = 1;
break;
case 13:
if(c_asc>=48&&c_asc<=57)
en = 13;
if(c_asc>=65&&c_asc<=90||c_asc>=97&&c_asc<=122)
en = 13;
else
en = 1;
break;
case 14:
if(c_asc>=48&&c_asc<=57)
en = 15;
else
en = 1;
break;
case 15:
if(c_asc>=48&&c_asc<=57)
en = 15;
else
en =1;
break;
}
return en;
}
void handle(String s){
int state=0,state2=0;
String temp = "";
char c;
int end = 0;
//如果是空格,直接截掉
while(s.length()>0){
while(s.charAt(end)==' ')
s = s.substring(1);
do{
c = s.charAt(end++);
state = Move(state,c);
if(state!=1){
state2 = state;
temp += c;
}
}while(state!=1&&state!=7&&state!=8&&state!=9&&state!=10&&s.length()>end);
//这些全是操作符
if(state2>1&&state2<=10&&state2!=6){
System.out.print("("+matchOp(temp)+","+temp+") ");
}
//这是数字
if(state2==6){
System.out.print("(11,"+temp+") ");
}
if(state2==14){ //如果输入x.则转化为x.0,假装浮点数的词法记号是33
System.out.print("(33," + temp+"0) ");
}
if(state2==15){
System.out.println("(33,"+temp+") ");
}
//剩下是字母/数字串,字母串要匹配关键字
if(state2==13||state2==11){
System.out.print("(10,"+temp+") ");
}
if(state2==12&&matchKw(temp)!=-1){
System.out.print("("+matchKw(temp)+","+temp+") ");
}
if(state2==12&&matchKw(temp)==1){
System.out.println("(10,"+temp+") ");
}
//切掉
s = s.substring(temp.length());
temp = "";
end = 0;
state = 0;
state2 = 0;
}
}
}
主函数类:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int i;
word w = new word();
String s;
Scanner in = new Scanner(System.in);
s = in.nextLine();
w.handle(s);
}
}