Cài đặt thuật toán

Một phần của tài liệu Tổng quan về phân tích văn bản (Trang 51 - 52)

Để dựng được cây phân tích, bao giờ ta cũng cần tìm dẫn xuất trái của quá trình phân tích. Dẫn xuất trái là một dẫn xuất tại mỗi bước luôn luôn chọn chữ phụ đầu tiên của xâu trung gian để thực hiện phép thế. Như vậy, một xâu ω bất kỳ thuộc vào ngôn ngữ sinh bởi văn phạm G khi và chỉ khi có tồn tại dẫn xuất trái để từ ký hiệu khởi đầu S suy dẫn được ra ω. Ta gọi dãy các số hiệu của các quy tắc suy dẫn i1i2...in là dãy trái. Ta quy bài toán phân tích câu về bài toán tìm dãy trái của ω.

Với những cấu trúc dữ liệu và thuật toán đã trình bày, ta có phương thức tìm dãy trái của một xâu như sau:

¾ Input: Một câu tiếng Anh ω, các từ cách nhau ít nhất một ký tự trắng, không có các dấu chấm câu

¾ Output: Dãy trái của ω nếu phân tích được, hoặc trả lời không đoán nhận được

public Vector parse(String w) { int i,j;

boolean recognizable = false; // đã đoán nhận được?

Vector parsingOrder = new Vector();// dãy trái của phân tích // Lấy ra các từ trong câu

StringTokenizer stk = new StringTokenizer(w); int n = stk.countTokens();

tokens = new String[n]; i = 0;

while (stk.hasMoreTokens()) { tokens[i] = stk.nextToken(); i++;

}

String curState = ""; // trạng thái hiện tại

int curPos = 0; // vị trí hiện tại

Stack backupStates = new Stack(); // các trạng thái sao lưu

Stack positions = new Stack(); // các vị trí sao lưu

Stack ruleIdxs = new Stack(); // chỉ số các quy tắc được chọn

backupStates.push(startSymbol); // startSymbol = S - câu

ruleIdxs.push(new Vector()); positions.push(new Integer(0));

// vòng lặp phân tích

while ((!backupStates.isEmpty()) && (!recognizable)) { curState = (String)backupStates.pop();

parsingOrder = (Vector)ruleIdxs.pop();

curPos = ((Integer)positions.pop()).intValue(); j = 0;

while ((curState.length() > 0) &&

(Character.isLowerCase(curState.charAt(j)))) {

// lo•i b• nh•ng ph••ng án không th• ••a t•i k•t qu•… while ((curState.length() > n-curPos) &&

(!backupStates.isEmpty())) { curState = (String)backupStates.pop(); curPos = ((Integer)positions.pop()).intValue(); parsingOrder = (Vector)ruleIdxs.pop(); } // nếu từ hiện tại thuộc kiểu từ loại này…

curState = (curState.length() == 1)? "" : curState.substring(1);

j = 0;

if ((curPos >= tokens.length) && curState.compareTo("") == 0)){ recognizable = true;

break; }

} else { // n•u không thì xét v• trí và tr•ng thái sao l•u… if (!positions.isEmpty()) curPos = ((Integer)positions.pop()).intValue(); if (!backupStates.isEmpty()) { curState = (String)backupStates.pop(); parsingOrder = (Vector)ruleIdxs.pop(); } else break; } }

// Áp d•ng các suy d•n: ••a các ph••ng án ti•p theo vào các ng•n x•p, // ch• ••a vào các ph••ng án có kh• n•ng cho k•t qu•

if ((!recognizable) && (curState.compareTo("") != 0)) for (i = 0; i < numberOfRules; i++)

if ((left[i].compareTo("" + curState.charAt(0)) == 0) && (curState.length() <= tokens.length-curPos+1)) { backupStates.push(right[i]+

((curState.length() >= 1) ? curState.substring(1) : ""));

positions.push(new Integer(curPos)); Vector tempVec = new Vector();

for (Enumeration e = parsingOrder.elements(); e.hasMoreElements();)

tempVec.addElement((Integer)e.nextElement()); tempVec.addElement(new Integer(i+1));

ruleIdxs.push(tempVec); }

} // kết thúc vòng lặp phân tích

if (!recognizable) return new Vector(); else return parsingOrder;

}

Phương thức parse nêu trên tìm dãy trái của ω và đưa nó vào một vector các số nguyên, mỗi phần tử của vector này là số hiệu của các quy tắc suy dẫn tương ứng.

Một phần của tài liệu Tổng quan về phân tích văn bản (Trang 51 - 52)

Tải bản đầy đủ (PDF)

(63 trang)