Análisis léxico del principio de compilación en Java
Titulo
Prerrequisitos
Ingrese las condiciones de terminación (este es el título)
El carácter # indica que la entrada ha finalizado (aquí ingresé el último #)
Reglas de nomenclatura variable
Los nombres de variables solo pueden ser una combinación de letras, números y guiones bajos, y solo pueden comenzar con letras o guiones bajos
Considere la entrada compacta que puede ocurrir al asignar valores
Las asignaciones variables no están separadas por espacios, como
x:=9; 或 x :=9;
规范输入应该是
x := 9;
Considere la entrada inválida y considérela inválida
- Al comienzo de un carácter no válido, la cadena antes del espacio no es válida, como
Considerarbegin $@djsalfjsdfl1325end= 10 ;
$@djsalfjsdfl1325end=
inválido - Error de columna calculada (aparece al principio del número), como
Pensar10*x 写成 10x 10*x+30y/2; 10*x+2/30y;
10x
e30y
inválido
Ideas
Click para ampliar
Código
import java.util.Scanner;
/**
* @author yinglongwu
*/
public class LexicalAnalysis {
public static void main(String[] args) {
//获取输入,用空格正则表达式将字符串分割成字符串数组
String[] sArr = getString().split("\\ ");
System.out.println("正在进行词法分析,请稍等...");
//对字符串数组中的每个字符串进行词法分析
for (int i = 0; i < sArr.length; i++) {
//System.out.println("正在分析"+sArr[i]);
analysis(sArr[i]);
}
}
//获取输入
public static String getString() {
Scanner scanner = new Scanner(System.in);
String s = new String();
String sIn = new String();
System.out.println("请输入你要进行词法分析的语句(#表示输入结束):");
//获取输入,录入空格,不录入回车,不录入最后一个#
//(sIn=scanner.nextLine())获取字符串输入(每次回车为结束)endsWith("#")字符串是否以#结尾
while (true) {
if (!(sIn=scanner.nextLine()).endsWith("#")) {
s = s + sIn + " ";//如果用户输入回车,用空格表示切断
}else {
//s = s + sIn.substring(0,sIn.length()-1); //不录入最后一个#
s = s + sIn + " ";//录入最后一个#
break;
}
}
System.out.println("检测到#输入已结束。");
return s;
}
//对每个字符串进行分析
public static void analysis(String s) {
if (s.isEmpty()) {
return; //字符串为空则结束
}
//下面三个条件分别是,首字符为字母或下划线,首字符为关键符号,首字符为数字
if (String.valueOf(s.charAt(0)).matches("[a-zA-z[_]]")) {
//System.out.println(s+"的首字符为字母或下划线");
letterAnalysis(s);
} else if (String.valueOf(s.charAt(0)).matches("[+-[*]/:=<>()#;]")) { //*为正则表达式中的特殊字符所以需要单独写,否则报异常
//System.out.println(s+"的首字符为关键符号");
charAnalysis(s);
} else if (String.valueOf(s.charAt(0)).matches("[0-9]")){
//System.out.println(s+"的首字符为数字");
numAnalysis(s);
} else {
System.out.println("(无效字符串,"+s+")");
}
}
//首字符为字母或下划线的分析方法
public static void letterAnalysis(String s) {
switch (s) {
case "begin":
System.out.println("(1,begin)");
break;
case "if":
System.out.println("(2,if)");
break;
case "then":
System.out.println("(3,then)");
break;
case "while":
System.out.println("(4,while)");
break;
case "do":
System.out.println("(5,do)");
break;
case "end":
System.out.println("(6,end)");
break;
default: //不是关键字
boolean t = false;//默认没有非字母、数字、下滑线的字符
int n = s.length();//记录符号下标,默认没有符号,所以为长度
//判断是否有符号
for (int i = 0; i < s.length(); i++) {
if (s.substring(i, i+1).matches("[+-[*]/:=<>();]")) {
n = i; //记录下标
break;
}
}
//对符号前的每一个字符判断是否有非法字符
for (int i = 0; i < n; i++) {
if (!s.substring(i,i+1).matches("[a-zA-z[_]]")) {
t = true; //如果含有非法字符
System.out.println("(无效字符串,"+s.substring(0, n)+")");
break;
}
}
//如果没有非法字符,输出结果
if (!t) {
System.out.println("("+10+","+"'"+s.substring(0, n)+"'"+")");
}
//符号后的继续判断
analysis(s.substring(n));
break;
}
}
//首字符为符号的分析方法
public static void charAnalysis(String s) {
switch (s) {
case "+":
System.out.println("(13,+)");
break;
case "-":
System.out.println("(14,-)");
break;
case "*":
System.out.println("(15,*)");
break;
case "/":
System.out.println("(16,/)");
break;
case ":":
System.out.println("(17,:)");
break;
case ":=":
System.out.println("(18,:=)");
break;
case "<":
System.out.println("(20,<)");
break;
case "<>":
System.out.println("(21,<>)");
break;
case "<=":
System.out.println("(22,<=)");
break;
case ">":
System.out.println("(23,>)");
break;
case ">=":
System.out.println("(24,>=)");
break;
case "=":
System.out.println("(25,=)");
break;
case ";":
System.out.println("(26,;)");
break;
case "(":
System.out.println("(27,()");
break;
case ")":
System.out.println("(28,))");
break;
case "#":
System.out.println("(0,#)");
break;
default: //不是关键字符
boolean t = false;
for (int i = 1; i < s.length(); i++) {
//如果第二个字符满足双字符条件
if (s.substring(i, i+1).matches("[=>]")) {
t = true;
//截取第二个字符前的字符串调用自身进行判断
charAnalysis(s.substring(0, i+1));
//第二个字符后的继续判断
analysis(s.substring(i+1));
break;
}
}
if (!t) {//如果第二个字符不满足双字符条件
//截取第一个字符前的字符串调用自身进行判断
charAnalysis(s.substring(0, 1));
//第一个字符后的继续判断
analysis(s.substring(1));
}
break;
}
}
//首字符为数字的分析方法
public static void numAnalysis(String s) {
boolean t = false; //标记是否有字母
int n = s.length(); //记录符号下标,这里的意思是不存在符号
//对每一个字符进行判断是否为符号
for (int i = 0; i < s.length(); i++) {
//如果有符号
if (s.substring(i, i+1).matches("[+-[*]/:=<>()#;]")) {
n = i; //记录符号的下标
break;
}
}
//对关键符号前的每一个字符判断是否有非数字
for (int i = 0; i < n; i++) {
if (!s.substring(i,i+1).matches("[0-9]")) {
t = true; //如果含有字母
System.out.println("(无效字符串,"+s.substring(0, n)+")");
break;
}
}
//符号前没有字母的输出结果
if (!t) {
System.out.println("("+11+","+s.substring(0, n)+")");
}
//符号后的继续分析
analysis(s.substring(n));
}
}
Prueba
- Preguntas de ejemplo
- Considere la entrada compacta al asignar
- El nombre de la variable es ilegal
- Error de columna