FIRSTVT与LASTVT的求解
实验内容
根据相关算法对FIRSTVT或LASTVT进行求解
实验目的
算符优先文法是自低向上语法分析的一个很有效地方法.本次设计的主要要求是输入一个算符优先文法,然后将它的FIRSTVT集合求出来.
得到两个样例的结果
(1)
S → #E#
E → E+T
E → T
T → T*F
T → F
F → P!F|P
P → (E)
P → i
(2)
S → a|@|(T)
T → T,S|S
上机环境
Windows 10, Eclipse
设计思想(流程)
我将这个程序分为三个部分来处理.第一部分是从文本文件中将某个算符优先文法读入,并将它结构化,存入一个结构中.第二部分是对这个结构进行分析处理,得到它的FIRSTVT集合,存入一个数组中.最后一部分将这个数组的数组的内容输出.
第一部分可现将算符文法存入文本,然后通过一个函数去逐行分析这个文本,提取出所有的终结符,非终结符,产生式左边和右边等等有用信息(具体的文本格式后面有说明),并将这些数据存入相应的数据结构中.我是分别使用一个结构体数组存放每个产生式的左边,结构体数组的每项右生成一个链表来存放产生式的右边.再用两个链表存放所有的终结符和非终结符.
实验代码
package test1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestFirstVT {
//用于存所有产生式
public List<Grammar> grammars;
//后进先出栈
public ArrayDeque<String> stack;
//数组F
public int[][] F = new int[26][94];//非终结符范围A ~ Z,终结符范围'!' ~ '~'
//结果
Map<Character,List<Character>> result;
public static final String RIGHT_INFER_QUOTE = " → ";
public static final String REGEX = "\\|";
public TestFirstVT() throws IOException {
init();
}
public TestFirstVT(List<Grammar> grammars,ArrayDeque<String> stack){
this.grammars = grammars;
this.stack = stack;
}
/**
* 输入以及初始化
*/
public void init() throws IOException {
grammars = new ArrayList();
stack = new ArrayDeque();
System.out.println("输入文法的产生式:形如A → Ba");
System.out.println("约定所有非终结符为英文大写字母,终结符为!至~(ASCII码值33~126)");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = "";
while (!"".equals(line = br.readLine().trim())){
String[] strings = line.split(RIGHT_INFER_QUOTE);
for(String s : strings[1].split(REGEX)){
Grammar grammar = new Grammar(strings[0],s);
grammars.add(grammar);
char cT = s.charAt(0);
if (!Character.isUpperCase(cT)){//形如A → a...
insert(strings[0].charAt(0),cT);
}else if (s.length()>1){
if (!Character.isUpperCase((cT = s.charAt(1)))){//形如A → Ba...
insert(strings[0].charAt(0),cT);
}
}
}
}
//System.out.println(grammars.toString());
System.out.println("输入结束........");
}
/**
*
* @param A 非终结符
* @param a 终结符
*/
public void insert(char A,char a){
if (F[A-'A'][a-'!'] == 0){
F[A-'A'][a-'!'] = 1;
stack.addLast(A+""+a);
//输出栈顶的内容
System.out.println("("+A+","+a+")");
}
}
/**
* 主程序
*/
public void solve(){
//init();
if (stack == null){
System.out.println("未初始化!");
return;
}
while (!stack.isEmpty()){
//取栈顶
String s = stack.removeLast();
char cN = s.charAt(0);
char cT = s.charAt(1);
for(Grammar grammar : grammars){
if(grammar.right.charAt(0) == cN){//形如A → B...
insert(grammar.left.charAt(0),cT);
}
}
}
}
/**
*
* @return 所有非终结符的FIRSTVT集
*/
public Map<Character,List<Character>> getResult(){
result = new HashMap();
for(int i = 0;i<26;i++){
for(int j = 0;j<94;j++){
if(F[i][j] == 1){
char cN = (char)(i+'A');
char cT = (char)(j+'!');
if(result.containsKey(cN)){
result.get(cN).add(cT);
}else{
List<Character> cTList = new ArrayList();
cTList.add(cT);
result.put(cN,cTList);
}
}
}
}
return result;
}
/**
* 打印所有非终结符的FIRSTVT集
*/
public void print(){
System.out.println("所有非终结符的FIRSTVT集为:");
//得到结果
getResult();
for(Character cN: result.keySet()){
//得到非终结符的FIRSTVT集
List<Character> cT = result.get(cN);
System.out.println(String.format("FIRSTVT(%c)={%s}",cN,cT.toString().substring(1,3*cT.size()-1)));
}
}
/**
* 测试
*
* @param args
* @throws IOException
*/
/*测试案例
S → #E#
E → E+T
E → T
T → T*F
T → F
F → P!F|P
P → (E)
P → i
S → a|@|(T)
T → T,S|S
*/
public static void main(String[] args) throws IOException {
TestFirstVT firstvt = new TestFirstVT();
firstvt.solve();
firstvt.print();
}
}
class Grammar {
public String left;//产生式左部
public String right;//产生式右部
public Grammar(){
}
public Grammar(String left,String right){
this.left = left;
this.right = right;
}
@Override
public String toString() {
return left + " → " +
right;
}
}
运行结果
输入
S → #E#
E → E+T
E → T
T → T*F
T → F
F → P!F|P
P → (E)
P → i
输出
输入文法的产生式:形如A → Ba
约定所有非终结符为英文大写字母,终结符为!至~(ASCII码值33~126)
S → #E#
(S,#)
E → E+T
(E,+)
E → T
T → T*F
(T,*)
T → F
F → P!F|P
(F,!)
P → (E)
(P,()
P → i
(P,i)
输入结束........
(F,i)
(T,i)
(E,i)
(F,()
(T,()
(E,()
(T,!)
(E,!)
(E,*)
所有非终结符的FIRSTVT集为:
FIRSTVT(P)={(, i}
FIRSTVT(S)={#}
FIRSTVT(T)={!, (, *, i}
FIRSTVT(E)={!, (, *, +, i}
FIRSTVT(F)={!, (, i}
输入
S → a|@|(T)
T → T,S|S
输出
输入文法的产生式:形如A → Ba
约定所有非终结符为英文大写字母,终结符为!至~(ASCII码值33~126)
S → a|@|(T)
(S,a)
(S,@)
(S,()
T → T,S|S
(T,,)
输入结束........
(T,()
(T,@)
(T,a)
所有非终结符的FIRSTVT集为:
FIRSTVT(S)={(, @, a}
FIRSTVT(T)={(, ,, @, a}
实验小结
在这次设计的整个过程中,由于吸取了上次语法分析器设计中出现的问题的经验,因此在短时间内较为顺利的完成了实验的要求.并且通过这个试验,让我再次对语法分析的自下而上分析和算符有限文法有了进一步的了解.掌握了FRISTVT 和LASTVT 的构造方法以及进一步的语法分析的构成。
参考
https://wenku.baidu.com/view/1ffd25640740be1e640e9a67.html
https://blog.csdn.net/weixin_45685353/article/details/106683395