E文法表達式類
G 定義文法類
LL 文法分析類 , 包含對First,Follow,Select集合的求解以及對表達式的分析函數
Main測試分析程式,并輸出結果
E.java
import java.util.ArrayList;
import java.util.List;
/**
* 文法表達式類
* @author jiangliuhong
* @createTime 2016年5月30日 上午11:28:43
* @function
*/
public class E {
//文法左部
private String left;
//文法右部
private String right;
private List<String> rights = new ArrayList<>();
public String getLeft() {
return left;
}
public void setLeft(String left) {
this.left = left;
}
public String getRight() {
return right;
}
public void setRight(String right) {
this.right = right;
}
public List<String> getRights() {
return rights;
}
public void setRights(List<String> rights) {
this.rights = rights;
}
public E() {
}
public E(String left, String right) {
this.left = left;
this.right = right;
createTaken();
}
public void createTaken() {
// this.getLefts().add(this.getLeft());
String right = this.getRight();
/*if (right.equals("$")) {
this.getRights().add(right);
} else {*/
/* while (right.contains("$")) {
right = right.replaceFirst("$", "#");
}*/
if (right.length() == 1) {
this.getRights().add(right);
} else {
for (int i = 0; i < right.length(); i++) {
if ((i + 1 < right.length())
&& String.valueOf(right.charAt(i + 1)).equals("'")) {
this.getRights().add(right.charAt(i) + "'");
} else {
if (!(String.valueOf(right.charAt(i)).equals("'"))) {
if (String.valueOf(right.charAt(i)).equals("#")) {
this.getRights().add("$");
} else {
this.getRights().add(
String.valueOf(right.charAt(i)));
}
}
}
}
}
}
/**
* 格式化實處文法表達式
* 重寫toString方法
* @return
*/
public String toString(){
return this.left+"->"+this.right;
}
}
G.java 文法定義類
import java.util.Arrays;
import java.util.List;
/**
* 文法定義類
*
* @author jiangliuhong
* @createTime 2016年5月30日 上午11:33:06
* @function
*/
public class G {
// 開始非終結符
private String start;
// 文法表達式
private List<E> es;
// 終結符
private List<String> terminator;
// 非終結符
private List<String> nonterminator;
public G() {
}
public G(String start, List<E> es) {
this.start = start;
this.es = es;
}
public G(String start) {
this.start = start;
}
public String getStart() {
return start;
}
public void setStart(String start) {
this.start = start;
}
public List<E> getEs() {
return es;
}
public void setEs(List<E> es) {
this.es = es;
}
public List<String> getTerminator() {
return terminator;
}
public void setTerminator(List<String> terminator) {
this.terminator = terminator;
}
public void setTerminator(String terminator) {
//this.terminator = new ArrayList<>();
/*for (int i = 0; i < terminator.length(); i++) {
this.terminator.add(terminator.charAt(i) + "");
}*/
String[] split = terminator.split(",");
this.terminator = Arrays.asList(split);
}
public List<String> getNonterminator() {
return nonterminator;
}
public void setNonterminator(List<String> nonterminator) {
this.nonterminator = nonterminator;
}
public void setNonterminator(String nonterminator) {
//this.nonterminator = new ArrayList<>();
/*for (int i = 0; i < nonterminator.length(); i++) {
this.nonterminator.add(nonterminator.charAt(i) + "");
}*/
String[] split = nonterminator.split(",");
this.nonterminator = Arrays.asList(split);
}
/**
* 向文法中添加表達式
*
* @param e
*/
public void andE(E e) {
this.es.add(e);
}
}
LL.java ll文法分析類
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
/**
* ll文法分析類
*
* @author jiangliuhong
* @createTime 2016年5月30日 上午11:38:52
* @function
*/
public class LL {
private G g;
// 三個集合
private Map<String, List<String>> first = new HashMap<>();
private Map<String, List<String>> follow = new HashMap<>();
private Map<String, List<String>> select = new HashMap<>();
//分析棧
private Stack<String> stack = new Stack<String>();
private Stack<String> str = new Stack<String>();
public LL(G g) {
this.g = g;
}
public G getG() {
return g;
}
public void setG(G g) {
this.g = g;
}
/**
* 分析輸入串
*/
public void chkString(String string){
//判斷是否為标準文法
//判斷終結符
for(int i = string.length()-1 ;i>=0;i--){
String s = string.charAt(i) + "";
str.push(s);
if(!g.getTerminator().contains(s)){
System.out.println("輸入串不符合規則");
return ;
}
}
//分析串
boolean flag = true;
int ii = 1;
stack.push("#");
stack.push(g.getStart());
System.out.println("步驟\t分析棧\t剩餘輸入串\t推導所用比對");
ff:while(flag){
if(str.isEmpty()){
return ;
}
if(ii == 100){
return ;
}
System.out.print(ii+"\t");
String peek = stack.peek();
String speek = str.peek();
for (Map.Entry<String, List<String>> entry : select.entrySet()) {
String key = entry.getKey();
List<String> list = entry.getValue();
if(list.contains(speek)){
String first = getSelectFirtsOrFollow(true,key);
if(!first.equals(peek)){
continue;
}
String kright = getSelectFirtsOrFollow(false, key);
if(peek.equals(speek)){
if(speek.equals("#")&&peek.equals("#")){
System.out.print(stack.toString()+"\t"+str.toString()+"\t"+"接受\n");
return;
}
System.out.print(stack.toString()+"\t"+str.toString()+"\t"+speek+"比對\n");
str.pop();
stack.pop();
}else{
System.out.print(stack.toString()+"\t"+str.toString()+"\t"+key+"\n");
stack.pop();
}
for(int j = kright.length()-1;j>=0;j--){
String ss = kright.charAt(j)+"";
if(ss.equals("'")){
ss = kright.charAt(j-1)+ss;
j--;
}
stack.push(ss);
}
ii++;
continue ff;
}
}
ii++;
//select中無比對項 , 輸入串錯誤
//System.out.println("\n輸入串錯誤");
//return;
}
}
/**
* 列印分析表
*/
public void printfAnalyzeTable(){
//列印表頭
System.out.print("\t\t");
for(String term : g.getTerminator()){
System.out.print("\t"+term+"\t");
}
System.out.println();
/*for (Map.Entry<String, List<String>> entry : select.entrySet()) {
String key = entry.getKey();
int indexOf = key.indexOf("->");
String nonter = key.substring(0, indexOf);
}*/
for(E e : g.getEs()){
System.out.print("\t"+e.getLeft()+"\t");
for(String term : g.getTerminator()){
Map<String, List<String>> selectLikeKey = findSelectLikeKey(e.getLeft());
for(String term_ : g.getTerminator()){
for (Map.Entry<String, List<String>> entry : selectLikeKey.entrySet()) {
List<String> value = entry.getValue();
if(value.contains(term_)){
String key = entry.getKey();
int indexOf = key.indexOf(">");
String string = key.substring(indexOf+1 );
System.out.print("\t->"+string+"\t");
}else{
System.out.print("\t");
}
}
}
}
System.out.println();
}
}
/**
* 得到 select key中含指定非終結符的映射
*/
private Map<String, List<String>> findSelectLikeKey(String likeKey){
Map<String, List<String>> result = new HashMap<>();
for (Map.Entry<String, List<String>> entry : select.entrySet()) {
String key = entry.getKey();
String skey = getSelectFirtsOrFollow(true,key);
if(skey.equals(likeKey)){
result.put(key, entry.getValue());
}
}
return result;
}
/**
* 取select ->前部分
*/
private String getSelectFirtsOrFollow(boolean isFirst,String key){
if(isFirst){
int indexOf = key.indexOf("-");
String skey = key.substring(0, indexOf);
return skey;
}else{
int indexOf = key.indexOf(">");
String skey = key.substring(indexOf+1);
return skey;
}
}
/**
* 列印Select集合
*/
public void printfSelect(){
System.out.println("Select集合為:");
for (Map.Entry<String, List<String>> entry : select.entrySet()) {
List<String> list = entry.getValue();
System.out.print("Select(" + entry.getKey() + ")={");
System.out.print(list.toString());
System.out.println("}");
}
}
/**
* 分析Select 集合
*/
public void chkSelect(){
//周遊文法
for(E e : g.getEs()){
String right = e.getRight();
String left = e.getLeft();
// | 判斷
String[] split = right.split("\\|");
for(String sp : split){
// $ 判斷
if(!right.contains("$")){
String begin = right.charAt(0) + "";
if(g.getNonterminator().contains(begin)){
//非終結符,存入first
select.put(left+"->"+sp,first.get(begin) );
}else{
//終結符
List<String> sel = new ArrayList<>();
sel.add(begin);
select.put(left+"->"+sp,sel);
}
}else{
select.put(left+"->"+sp,follow.get(left));
}
}
}
}
/**
* 列印follow集合
*/
public void printfFollow() {
System.out.println("Follow集合為:");
for (Map.Entry<String, List<String>> entry : follow.entrySet()) {
List<String> list = entry.getValue();
System.out.print("Follow(" + entry.getKey() + ")={");
System.out.print(list.toString());
System.out.println("}");
}
}
/**
* 分析follow集合
*/
public void chkFollow() {
//給每個非終結符建立一個map集合
for (String symbol : g.getNonterminator()) {
List<String> list = new ArrayList<String>();
list.add("#");
follow.put(symbol, list);
}
//定義一個循環上線
int count = 100;
//周遊非終結符
for (int i = 0, j = 0; i < g.getNonterminator().size()
&& j < count; i = (i + 1) % (g.getNonterminator().size()), j++) {
String symbol = g.getNonterminator().get(i);
//周遊文法表達式
for (E e : g.getEs()) {
if (e.getRight().contains(symbol)) {
for (int k = 0; k < e.getRights().size(); k++) {
//該文法表達式右部包含該非終結符
if (e.getRights().get(k).equals(symbol)) {
// 開始文法分析
//定義循環變量
boolean canDo = false, meDo = false;
for (int n = k; n < e.getRights().size() && !(e.getRights().get(n).equals("|"))
&& !canDo; n++) {
//判斷後補是否為非終結符
if (n + 1 < e.getRights().size()) {
String rightString = e.getRights().get(n + 1);
if (g.getNonterminator().contains(rightString)) {
if (!canDo && !meDo) {
meDo = true;
List<String> leftFirst = first.get(rightString);
List<String> symbolFollow = follow.get(symbol);
for (int m = 0; m < leftFirst.size(); m++) {
if (!(symbolFollow.contains(leftFirst.get(m)))
) {
if (!(leftFirst.get(m).equals("$")))
if (!(leftFirst.get(m).equals("|")))
symbolFollow.add(leftFirst.get(m));
}
}
follow.put(symbol, symbolFollow);
}
} else {
List<String> symbolFollow = follow.get(symbol);
if (!(symbolFollow.contains(rightString)) && !(rightString.equals("|"))) {
symbolFollow.add(rightString);
follow.put(symbol, symbolFollow);
canDo = true;
}
}
}
}
// | 的文法判斷
if (k == e.getRights().size() - 1
|| e.getRights().get(k + 1).equals("|") && !canDo) {
String leftSymbol = e.getLeft();
List<String> leftFollow = follow.get(leftSymbol);
List<String> symbolFollow = follow.get(symbol);
for (int m = 0; m < leftFollow.size(); m++) {
if (!(symbolFollow.contains(leftFollow.get(m)))) {
if (!(leftFollow.get(m).equals("$")))
if (!(leftFollow.get(m).equals("|")))
symbolFollow.add(leftFollow.get(m));
}
}
follow.put(symbol, symbolFollow);
canDo = true;
} else {
int nonTerminatingSymbol = 0;
int isepsilon = 0;
boolean isMe = false;
for (int n = k; n < e.getRights().size()
&& !(e.getRights().get(n).equals("|")); n++) {
if (n + 1 < e.getRights().size()) {
String rightString = e.getRights().get(n + 1);
if (g.getTerminator().contains(rightString)) {
isMe = true;
}
if (g.getNonterminator().contains(rightString)) {
nonTerminatingSymbol++;
if (hasepsilon(rightString)) {
isepsilon++;
}
}
}
}
if (nonTerminatingSymbol == isepsilon && !canDo && !isMe) {
String leftSymbol = e.getLeft();
List<String> leftFollow = follow.get(leftSymbol);
List<String> symbolFollow = follow.get(symbol);
for (int m = 0; m < leftFollow.size(); m++) {
if (!(symbolFollow.contains(leftFollow.get(m)))) {
if (!(leftFollow.get(m).equals("$")))
if (!(leftFollow.get(m).equals("|")))
symbolFollow.add(leftFollow.get(m));
}
}
follow.put(symbol, symbolFollow);
}
}
}
}
}
}
}
}
/**
* 判斷是否含有 $ $ 即 epsilon
* @param symbol
* @return
*/
private boolean hasepsilon(String symbol) {
for (E e : g.getEs()) {
if (e.getLeft().equals(symbol)) {
int index = e.getRights().indexOf("$");
if (index < 0) {
return false;
} else {
if (e.getRights().size() == 1 && e.getRights().contains("$")) {
return true;
} else {
if (index == e.getRights().size() - 1 && e.getRights().get(index - 1).equals("|")) {
return true;
} else {
if (index + 1 < e.getRights().size() && e.getRights().get(index + 1).equals("|")
&& index == 0) {
return true;
} else {
if (index + 1 < e.getRights().size()
&& e.getRights().get(index + 1).equals("|") && index - 1 > 0
&& e.getRights().get(index - 1).equals("|")) {
return true;
}
}
}
}
}
}
}
return false;
}
/**
* 輸出first集合
*/
public void printfFirst() {
System.out.println("First集合為:");
for (Map.Entry<String, List<String>> entry : first.entrySet()) {
List<String> list = entry.getValue();
System.out.print("First(" + entry.getKey() + ")={");
System.out.print(list.toString());
System.out.println("}");
}
}
/**
* 分析first集合
*/
public void chkFirst() {
// 周遊非終結符
for (String nonter : g.getNonterminator()) {
List<String> listFirst = new ArrayList<String>();
iterativeToFirst(nonter, listFirst);
}
}
/**
* 文法分析
*
* @param symbol
* @param listFirst
*/
private void iterativeToFirst(String symbol, List<String> listFirst) {
for (E e : g.getEs()) {
if (e.getLeft().equals(symbol)) {
// 根據| 劃分文法表達式
String[] rights = e.getRight().split("\\|");
for (String right : rights) {
if (!isStartWithSymbol(right)) {
// 不是非終結符,加入list
listFirst.add(getStartWithSymbol(right));
} else {
iterativeToFirst(getStartWithSymbol(right), listFirst);
}
}
}
}
first.put(symbol, listFirst);
}
/**
* 判斷開始是否為非終結符
*
* @param symbol
* @return
*/
private boolean isStartWithSymbol(String symbol) {
for (String nonTerminatingSymbol : g.getNonterminator()) {
if (symbol.startsWith(nonTerminatingSymbol)) {
return true;
}
}
return false;
}
/**
* 得到文法的第一個字元
*
* @param symbol
* @return
*/
private String getStartWithSymbol(String symbol) {
for (String nonTerminatingSymbol : g.getNonterminator()) {
if (symbol.startsWith(nonTerminatingSymbol)) {
return nonTerminatingSymbol;
}
}
// $ 代替epsilon
if (symbol.equals("$")) {
return "$";
} else {
return String.valueOf(symbol.charAt(0));
}
}
}
Main.java測試類
import java.util.ArrayList;
import java.util.List;
/**
* @author jiangliuhong
* @createTime 2016年5月30日 上午11:31:15
* @function
*/
public class Main {
public static void main(String[] args) {
List<E> es = new ArrayList<>();
es.add(new E("E", "TE'"));
es.add(new E("E'", "+TE'|$"));
es.add(new E("T", "FT'"));
es.add(new E("T'", "*FT'|$"));
es.add(new E("F", "i|(E)"));
G g = new G("E", es );
List<String> non = new ArrayList<>();
g.setNonterminator("E,E',T,T',F");
g.setTerminator("i,+,*,(,),#");
LL ll = new LL(g);
ll.chkFirst();
ll.printfFirst();
ll.chkFollow();
ll.printfFollow();
ll.chkSelect();
ll.printfSelect();
ll.printfAnalyzeTable();
ll.chkString("i+i*i#");
}
}
控制台輸出結果
First集合為:
First(E)={[i, (]}
First(T)={[i, (]}
First(T')={[*, $]}
First(F)={[i, (]}
First(E')={[+, $]}
Follow集合為:
Follow(T)={[#, +, )]}
Follow(E)={[#, )]}
Follow(F)={[#, *, +, )]}
Follow(T')={[#, +, )]}
Follow(E')={[#, )]}
Select集合為:
Select(F->(E))={[i]}
Select(F->i)={[i]}
Select(E'->+TE')={[#, )]}
Select(T->FT')={[i, (]}
Select(E'->$)={[#, )]}
Select(E->TE')={[i, (]}
Select(T'->$)={[#, +, )]}
Select(T'->*FT')={[#, +, )]}
i + * ( ) #
E ->TE' ->TE'
E' ->TE' ->$ ->$
T ->FT' ->FT'
T' ->$ ->*FT' ->$ ->$
F ->i ->(E)
步驟 分析棧 剩餘輸入串 推導所用比對
1 [#, E] [#, i, *, i, +, i] E->TE'
2 [#, E', T] [#, i, *, i, +, i] T->FT'
3 [#, E', T', F] [#, i, *, i, +, i] F->i
4 [#, E', T', i] [#, i, *, i, +, i] i比對
5 [#, E', T'] [#, i, *, i, +] T'->$
6 [#, E'] [#, i, *, i, +] E'->+TE'
7 [#, E',T,+] [#, i, *, i, +] +比對
8 [#, E',T] [#, i, *, i] T->FT'
9 [#, E',T',F] [#, i, *, i] F->i
10 [#, E',T',i] [#, i, *, i] i比對
11 [#, E',T'] [#, i, *] T'->*FT'
12 [#, E',T',F,*] [#, i, *] *比對
13 [#, E',T',F] [#, i] F->i
14 [#, E',T',i] [#, i] i比對
15 [#, E',T'] [#] T'->$
16 [#, E'] [#] E'->$
17 [#] [#] 接受