一、实验目的:
利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
二、实验原理
每个非终结符都对应一个子程序。
该子程序根据下一个输入符号(SELECT集)来确定按照哪一个产生式进行处理,再根据该产生式的右端:
- 每遇到一个终结符,则判断当前读入的单词是否与该终结符相匹配,若匹配,再读取下一个单词继续分析;不匹配,则进行出错处理
- 每遇到一个非终结符,则调用相应的子程序
三、实验要求说明
输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。
例如:
输入begin a:=9;x:=2*3;b:=a+x end #
输出success
输入x:=a+b*c end #
输出‘end' error
四、实验步骤
1.待分析的语言的语法(参考P90)
2.将其改为文法表示,至少包含
–语句
–条件
–表达式
E -> E+T | T
T -> T*F | F
F -> (E) | i
3. 消除其左递归
E->T+E'
E'->+TE'|ε
T->FT'
T'->*FT'|ε
F -> (E) | i
4. 提取公共左因子
5. SELECT集计算
FIRST集:
FIRST(E)={(,i}
FIRST(E')={+,ε}
FIRST(T)={(,i}
FIRST(T')={*,ε}
FIRST(F)={(,i}
FOLLOW集:
FOLLOW(E)={),#}
FOLLOW(E')={),#}
FOLLOW(T)={+,),#}
FOLLOW(T')={+,),#}
FOLLOW(F)={*,+,),#}
SELECT集:
SELECT(E→TE')={ ( , i }
SELECT(E'→+TE')={+}
SELECT(E'→ε)={),#}
SELECT(T→FT')={ ( , i }
SELECT(T'→*FT')={*}
SELECT(T'→ε)={+,),#}
SELECT(F→(E))={(}
SELECT(F→i)={i}
6. LL(1)文法判断
此文法为LL(1)文法。
7. 递归下降分析程序
词法分析程序Check.java:
import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class Check { public boolean check(String s2) { if ("".equals(s2)) { return false; } Map<Integer, String> map = new HashMap<Integer, String>(); map.put(1, "begin"); map.put(2, "if"); map.put(3, "then"); map.put(4, "while"); map.put(5, "do"); map.put(6, "end"); map.put(13, "+"); map.put(14, "-"); map.put(15, "*"); map.put(16, "/"); map.put(17, ":"); map.put(18, ":="); map.put(20, "<"); map.put(21, "<>"); map.put(22, "<="); map.put(23, ">"); map.put(24, ">="); map.put(25, "="); map.put(26, ":"); map.put(27, "("); map.put(28, ")"); map.put(0, "#"); char s3[] = s2.toCharArray(); for (int i = 0; i < s3.length; i++) { int news3 = (int) s3[i]; boolean flag1 = false; if (((news3 >= 65) && (news3 <= 90)) || ((news3 >= 97) && (news3 <= 122))) { while (((news3 >= 65) && (news3 <= 90)) || ((news3 >= 97) && (news3 <= 122)) || (news3 >= 48 && news3 <= 57)) { flag1 = true; i++; if (i>=s3.length) { break; } news3 = (int) s3[i]; } i--; } news3 = (int) s3[i]; boolean flag2 = false; while (news3 >= 48 && news3 <= 57) { i++; if (i>=s3.length) { break; } news3 = (int) s3[i]; flag2 = true; } if (flag2) i--; boolean flag3 = false; boolean flag5 = true; if (map.containsValue(""+s3[i])) { i++; flag3 = true; if (i>=s3.length) { i--; break; } if (map.containsValue(""+s3[i])) { String x=""+s3[i-1]+s3[i]; if (map.containsValue(x)) { continue; }else { flag5=false; } } i--; } if (flag5==false) return false; news3 = (int) s3[i]; boolean flag4 = false; String zfc = ""; if (news3 == 34) { flag4 = true; zfc += s3[i]; i++; news3 = (int) s3[i]; while (news3 != 34) { zfc += s3[i]; i++; if (i>=s3.length) { i--; break; } news3 = (int) s3[i]; } if(news3!=34) return false; } if (news3 == 32) { continue; } if (flag1||flag2||flag3||flag4) { } else { return false; } } return true; } }
语法分析程序Work.java:
import java.util.Scanner; import static java.lang.System.exit; public class Work { static int index=0; static Scanner sc = new Scanner(System.in); static String s2 = sc.nextLine(); static char s3[] = s2.toCharArray(); public static void main(String[] args) throws Exception { Check ck = new Check(); if (ck.check(s2)&&s2.endsWith("#")) { ParseE(); } else { System.out.print("输入有误!"); } } static void ParseE(){ ParseT(); ParseE1(); } private static void ParseE1() { switch (s3[index]){ case '+': index+=1; ParseT(); ParseE1(); break; case '#': break; case ')': index+=1; break; default: System.out.println("synax error!"); exit(0); break; } } private static void ParseT1() { switch (s3[index]){ case '*': index+=1; ParseF(); ParseT1(); break; case '#': break; case ')': index+=1; break; case '+': break; default: System.out.println("synax error!"); exit(0); break; } } private static void ParseF() { switch (s3[index]){ case '(': index+=1; ParseE(); break; case 'i': index+=1; break; default: System.out.println("synax error!"); exit(0); } } private static void ParseT() { ParseF(); ParseT1(); } }
结果: