You are on page 1of 7

Âu Thị Quý – 20010795 – nhóm 5

1. Viết chương trình tính FIRST bằng C/C++/Java với


2. - Input: Cần mô tả
3. - Mảng 2 chiều production[][] mô tả 1 luật
4. - Ký hiệu kết thúc xâu: $
5. - Ký hiệu ký tự rỗng: #
6. - 1 xâu đầu vào kiểu string đối với C/C++ hoặc String đối với
Java
7. - Hàm tính First nhận bảng production
GIẢI
import java.util.*;
public class First {
public static Map<String, Set<String>> firstSet = new
HashMap<>();
public static Map<String, List<List<String>>> production =
new HashMap<>();

public static void main(String[] args) {


String[][] productionArray = {{"S", "AB", "BC"}, {"A",
"aA", "#"}, {"B", "bB", "#"}, {"C", "c"}};
String startSymbol = "S";
String epsilon = "#";
String endSymbol = "$";

initializeProduction(productionArray);
initializeFirstSet(startSymbol, epsilon, endSymbol);

System.out.println("FIRST set: " + firstSet);


}

public static void initializeProduction(String[][]


productionArray) {
for (String[] p : productionArray) {
String left = p[0];
List<List<String>> right = new ArrayList<>();
for (int i = 1; i < p.length; i++) {
List<String> r = new ArrayList<>();
for (char c : p[i].toCharArray()) {
r.add(String.valueOf(c));
}
right.add(r);
}
production.put(left, right);
}
}

public static void initializeFirstSet(String startSymbol, String


epsilon, String endSymbol) {
for (String key : production.keySet()) {
firstSet.put(key, new HashSet<>());
}

for (String key : production.keySet()) {


calculateFirst(key, startSymbol, epsilon, endSymbol);
}
}

public static void calculateFirst(String key, String startSymbol,


String epsilon, String endSymbol) {
List<List<String>> right = production.get(key);
for (List<String> rule : right) {
String firstSymbol = rule.get(0);
if (isTerminalSymbol(firstSymbol, startSymbol, epsilon,
endSymbol)) {
firstSet.get(key).add(firstSymbol);
} else if (isNonTerminalSymbol(firstSymbol)) {
calculateFirst(firstSymbol, startSymbol, epsilon,
endSymbol);
firstSet.get(key).addAll(firstSet.get(firstSymbol));
}
}
}

public static boolean isTerminalSymbol(String symbol, String


startSymbol, String epsilon, String endSymbol) {
return !symbol.equals(startSymbol) && !
symbol.equals(epsilon) && !symbol.equals(endSymbol);
}
public static boolean isNonTerminalSymbol(String symbol) {
return production.containsKey(symbol);
}
}

2. Viết chương trình tính FOLLOW bằng Java


Sửa chương trình để nó tự động phát hiện văn phạm có là
LL(1) hay không?
Cài đặt bộ phân tích thuật toán LL(1)
Cài đặt bộ phân tích thuật toán LR(1)
GIẢI
import java.util.*;

public class FollowCalculator {

private Map<String, Set<String>> productions;


private Map<String, Set<String>> follow;
private Set<String> nonTerminals;

public FollowCalculator(Map<String, Set<String>>


productions) {
this.productions = productions;
follow = new HashMap<>();
nonTerminals = productions.keySet();
for (String nonTerminal : nonTerminals) {
follow.put(nonTerminal, new HashSet<>());
}
follow.get("S").add("$"); // Thêm $ vào FOLLOW(S)
}

public Map<String, Set<String>> getFollow() {


boolean changed = true;
while (changed) {
changed = false;
for (String nonTerminal : nonTerminals) {
for (String production : productions.get(nonTerminal)) {
String[] symbols = production.split(" ");
for (int i = 0; i < symbols.length; i++) {
if (nonTerminals.contains(symbols[i])) {
// Rule 2: Add FIRST of everything after
nonTerminal to FOLLOW of nonTerminal
for (int j = i + 1; j < symbols.length; j++) {

follow.get(symbols[i]).addAll(first(symbols[j]));
if (first(symbols[j]).contains("ε")) {

follow.get(symbols[i]).addAll(follow.get(nonTerminal));
} else {
break;
}
}
}
}
for (int i = symbols.length - 1; i >= 0; i--) {
if (nonTerminals.contains(symbols[i])) {
// Rule 3: Add FOLLOW of nonTerminal to
FOLLOW of symbols[i]
if (i == symbols.length - 1) {

follow.get(symbols[i]).addAll(follow.get(nonTerminal));
} else {
if (first(symbols[i + 1]).contains("ε")) {

follow.get(symbols[i]).addAll(follow.get(nonTerminal));
}
follow.get(symbols[i]).addAll(first(symbols[i +
1]));
}
}
}
}
}
}
return follow;
}
private Set<String> first(String symbol) {
Set<String> first = new HashSet<>();
if (!nonTerminals.contains(symbol)) {
first.add(symbol);
return first;
}
for (String production : productions.get(symbol)) {
String[] symbols = production.split(" ");
for (int i = 0; i < symbols.length; i++) {
first.addAll(first(symbols[i]));
if (!first.contains("ε")) {
break;
}
if (i == symbols.length - 1 && first.contains("ε")) {
first.remove("ε");
}
}
}
return first;
}
}

You might also like