1. Trang chủ
  2. » Giáo Dục - Đào Tạo

(Đồ án) Phân tích cú pháp theo phương pháp Ơle

18 749 3
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 18
Dung lượng 131 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Tóm tắt Giải thuật Earley là một giải thuật cơ bản, được sử dụng tương đối rộng rãi trong các hệ thống phân tích cú pháp.. Giải thuật Earley là một trong những giải thuật được sử dụng p

Trang 1

HỌC VIỆN KỸ THUẬT QUÂN SỰ KHOA CÔNG NGHỆ THÔNG TIN

-o0o -BÀI TẬP LỚN

Môn: Automata và ngôn ngữ hình thức

Đề tài: Viết chương trình phân tích cú pháp theo phương pháp Earley.

Có trình bày các bước tính toán và dẫn xuất nếu có.

Giáo viên hướng dẫn:

Nhóm SV thực hiện:

1 Vương Thị Tuyến

2 Lưu Thị Thảnh

3 Nguyễn Huy Linh

Lớp: Tin Học 9A

Hà Nội, tháng 01 năm 2013

Trang 2

MỤC LỤC

1 Tóm tắt

Giải thuật Earley là một giải thuật cơ bản, được sử dụng tương đối rộng rãi trong các hệ thống phân tích cú pháp Tuy nhiên, giải thuật này vẫn còn hạn chế như

Trang 3

sinh ra quá nhiều luật dư thừa trong quá trình phân tích Trong bài này, chúng tôi

đề xuất ra phương pháp phân tích cú pháp theo giải thuật Earley

Giải thuật Earley là một trong những giải thuật được sử dụng phổ biến trong việc xây dựng các hệ thống phân tích cú pháp Giải thuật này sử dụng chiến lược phân tích kiểu trên xuống (top-down), bắt đầu với một ký hiệu không kết thúc đại diện cho câu và sử dụng các luật khai triển cho đến khi thu được câu vào Hạn chế của cách tiếp cận này là không chú trọng nhiều đến các từ đầu vào Vì vậy trong quá trình phân tích, giải thuật Earley sản sinh ra rất nhiều luật dư thừa.Ngoài ra, giải thuật Earley được xây dựng cho tiếng Anh nên khi áp dụng cho tiếng Việt sẽ có hạn chế Mỗi câu vào tiếng Anh chỉ có một cách tách từ, trong khi với tiếng Việt, mỗi câu vào có thể có nhiều cách tách từ khác nhau Với đặc điểm đầu vào của giải thuật Earley chỉ là một câu với một cách tách, bộ phân tích cú pháp sẽ phải thực hiện lặp đi lặp lại giải thuật này cho từng trường hợp tách từ đối với tiếng Việt Để giải quyết vấn đề này, chúng tôi nhận thấy trong các cách tách từ Việt tồn tại các cặp cách tách giống nhau ở danh sách các từ loại đầu tiên và chỉ khác nhau

ở phần đuôi của chúng.

Giải thuật Earley cơ bản, giúp người đọc có thể hình dung một cách khái quát về giải thuật này.

Trang 4

2 Giải thuật Earley

Giải thuật Earley cơ bản được phát biểu như sau:

Đầu vào: Văn phạm G = (N, T, S, P), trong đó:

• N: tập kí hiệu không kết thúc.

• T: tập kí hiệu kết thúc.

• S: kí hiệu không kết thúc bắt đầu.

• P: tập luật cú pháp.

Xâu vào w = a1a2 an.

Đầu ra: Phân tích đối với w hoặc "sai".

Kí hiệu:

• α, β, γ biểu diễn xâu chứa các kí hiệu kết thúc, không kết thúc hoặc rỗng.

• X, Y, Z biểu diễn các kí hiệu không kết thúc đơn.

• a biểu diễn kí hiệu kết thúc.

Earley sử dụng cách biểu diễn luật thông qua dấu chấm “• ”

X→ α • β có nghĩa :

• Trong P có một luật sản xuất X→ α β.

• α đã được phân tích.

• β đang được chờ phân tích.

• Khi dấu chấm “ • ” được chuyển ra sau β có nghĩa đây là một luật hoàn thiện Thành phần X đã được phân tích đầy đủ, ngược lại nó là một luật chưa hoàn thiện Đối với mỗi từ thứ j của xâu đầu vào, bộ phân tích khởi tạo một bộ có thứ tự các trạng thái S(j).

Mỗi bộ tương ứng với một cột trong bảng phân tích Mỗi trạng thái có dạng (X →

α • β, i), thành phần sau dấu phẩy xác định rằng luật này được phát sinh từ cột thứ i.

a.Khởi tạo

• S(0) được khởi tạo chứa ROOT → • S.

• Nếu tại bộ cuối cùng ta có luật (ROOT → S•, 0) thì có nghĩa xâu vào được phân tích thành công.

Trang 5

b Thuật toán

Thuật toán phân tích thực hiện 3 bước: Dự đoán (Predictor), Duyệt (Scanner), và Hoàn thiện (Completer) đối với mỗi bộ S(j).

+) Dự đoán

Với mọi trạng thái trong S(j): (X → α • Y β, i), ta thêm trạng thái (Y → • γ, j) vào S(j) nếu có luật sản xuất Y → γ trong P.

+) Duyệt

Nếu a là kí hiệu kết thúc tiếp theo Với mọi trạng thái trong S(j): (X → α • a β, i), ta thêm trạng thái (X → α a • β, i) vào S(j+1).

+) Hoàn thiện

Với mọi trạng thái trong S(j): (X → γ• , i), ta tìm trong S(i) trạng thái (Y → α •

X β, k), sau đó thêm (Y → α X • β, k) vào S(j).

Ở mỗi bộ S(j) phải kiểm tra xem trạng thái đã có chưa trước khi thêm vào để tránh trùng lặp.

Để minh họa cho thuật toán trên, chúng ta phân tích câu “học sinh học sinh học” với tập luật cú pháp sau:

S → N VP

S → P VP

S → N AP

S → VP AP

VP → V N

VP → V NP

NP → N N

NP → N A

AP → R A

N → học sinh

N → sinh học

V → học

V → sinh

Trong đó:

S – câu

VP – cụm động từ

NP – cụm danh từ

AP – cụm tính từ

P – đại từ

N – danh từ

V – động từ

A – tính từ

R – phụ từ

Trang 6

Do câu trên có nhiều cách tách từ, trong khi đầu vào của giải thuật Earley chỉ là một câu với một cách tách từ nên chúng tôi minh họa giải thuật Earley với cách

tách từ trong trường hợp câu được phân tích là: học sinh, học, sinh học.

Bảng phân tích cho cách tách này như sau:

ROOT • S, 0 N học sinh•, 0 V học•, 1 N sinh học•, 2

S •N VP, 0 S N •VP, 0 VP V •N, 1 VP V N•, 1

S •P VP, 0 S N •AP, 0 VP V •NP, 1 NP N •N, 2

S •N AP, 0 VP •V N, 1 NP •N N, 2 NP N •A, 2

S •VP AP, 0 VP •V NP, 1 NP •N A, 2 S N VP•, 0

VP •V N, 0 AP •R A, 1 N •học sinh, 2 ROOT S•, 0

VP •V NP, 0 V •học, 1 N •sinh học, 2

N •học sinh, 0

N •sinh học, 0

V •học, 0

Bảng 1 Bảng minh họa giải thuật Earley

Trang 7

3 Chương trình phân tích cú pháp câu theo phương pháp Early Parser

#include <iostream>

#include <fstream>

#include <map>

#include <vector>

#include <string>

using namespace std;

#define noun 1

#define verb_i 2

#define verb_t 4

#define prep 128

#define SENT 256

#define NUMRHS 1

#define TABLE 3

void nhapDanhTu(map<string, unsigned int> &TL)

{

fstream fin;

fin.open("noun.txt");

int n;

fin >> n;

string str;

for (int i = 0; i < n; i++)

{

fin >> str;

TL[str] = TL[str] | noun;

}

fin.close();

}

void nhapNoiDongTu(map<string, unsigned int> &TL)

{

fstream fin;

fin.open("verb_i.txt");

Trang 8

int n;

fin >> n;

string str;

for (int i = 0; i < n; i++)

{

fin >> str;

TL[str] = TL[str] | verb_i;

}

fin.close();

}

void nhapNgoaiDongTu(map<string, unsigned int> &TL) {

fstream fin;

fin.open("verb_t.txt");

int n;

fin >> n;

string str;

for (int i = 0; i < n; i++)

{

fin >> str;

TL[str] = TL[str] | verb_t;

}

fin.close();

}

void nhapTinhTu(map<string, unsigned int> &TL) {

fstream fin;

fin.open("adj.txt");

int n;

fin >> n;

string str;

for (int i = 0; i < n; i++)

{

fin >> str;

TL[str] = TL[str] | adj;

}

fin.close();

}

void nhapGioiTu(map<string, unsigned int> &TL) {

fstream fin;

fin.open("prep.txt");

int n;

fin >> n;

Trang 9

string str;

for (int i = 0; i < n; i++)

{

fin >> str;

TL[str] = TL[str] | prep;

}

fin.close();

}

void nhapMaoTu(map<string, unsigned int> &TL) {

fstream fin;

fin.open("det.txt");

int n;

fin >> n;

string str;

for (int i = 0; i < n; i++)

{

fin >> str;

TL[str] = TL[str] | det;

}

fin.close();

}

void nhapDaiTu(map<string, unsigned int> &TL) {

fstream fin;

fin.open("pro.txt");

int n;

fin >> n;

string str;

for (int i = 0; i < n; i++)

{

fin >> str;

TL[str] = TL[str] | pro;

}

fin.close();

}

void nhapTroDongTu(map<string, unsigned int> &TL) {

fstream fin;

fin.open("auxi.txt");

int n;

fin >> n;

string str;

Trang 10

for (int i = 0; i < n; i++)

{

fin >> str;

TL[str] = TL[str] | aux;

}

fin.close();

}

void nhapDanhSachLuat(vector<int> Luat[], int &iNumRule) {

map<string, int> BangTra;

BangTra["noun"] = noun;

BangTra["verb_i"] = verb_i;

BangTra["verb_t"] = verb_t;

BangTra["adj"] = adj;

BangTra["prep"] = prep;

BangTra["pro"] = pro;

BangTra["aux"] = aux;

BangTra["det"] = det;

BangTra["S"] = SENT;

BangTra["NP"] = NP;

BangTra["VP"] = VP;

BangTra["PP"] = PP;

BangTra["NP2"] = NP2;

BangTra["NP3"] = NP3;

fstream fin;

char str[100];

fin.open("Rules.txt");

fin >> iNumRule;

fin.getline(str, 100, '\n');

for (int i = 0; i < iNumRule; i++)

{

fin.getline(str, 100, '\n');

int j = 0;

int k;

char* p = strtok(str, "-> ,+");

while (p != NULL) {

if (j == 0) {

j++;

k = BangTra[p];

Luat[i].push_back(k);

Luat[i].push_back(0);

Luat[i].push_back(0);

Luat[i].push_back(0);

} else {

Luat[i].push_back(BangTra[p]);

Trang 11

}

p = strtok(NULL, "-> ,+");

} }

fin.close();

}

void nhapCauInput(vector<string> &Cau)

{

Cau.clear();

char str[100];

gets(str);

char* p = strtok(str, " ");

while ( p != NULL)

{

Cau.push_back(p);

p = strtok(NULL, " ");

}

}

bool isTerminal(int term)

{

return (term < 128);

}

bool DauChamCuoiCau(vector<int> &Luat)

{

return (Luat[DOT] == Luat[NUMRHS]);

}

// Tu loa 1 va tu loai 2 phai la cac terminal

bool CungTuLoai(int TuLoai1, int TuLoai2)

{

if ( (TuLoai1 & TuLoai2) != 0)

return true; else

return false; }

void thuatToan(vector<string> Cau, vector<int> Luat[], map<string, unsigned int> &TuLoai, int iNumRule, vector<vector<int> > Table[]) {

/*

Trong khi chua ket thuc cau

Lay tu do ra, kiem tra tu loai cua tu do Tim trong bang truoc do nhung cau co chi so la n-1

Neu tu loai sau dau cham = tu loai cua tu dang xet

Dich chuyen cac dau cham, nho cap nhat lai chi

so cua cau

Voi moi cau vua cap nhat lai chi so

Neu dau cham truoc non-terminal

thi trien khai else Neu dau cham truoc terminal

Trang 12

thi khong trien khai else Neu dau cham nam o cuoi cung

Backtracking

*/

int i;

int n = Cau.size();

// Init

i = 0;

while (i < iNumRule)

{

if (Luat[i][LHS] == SENT) {

//Luat[i][TABLE] = -1;

Table[0].push_back(Luat[i]);

} i++;

}

int j = 0;

int num = Table[0].size();

vector<int> DSKhaiTrien;

while(j < num)

{

int pos = Table[0][j][DOT];

int iTuLoai = Table[0][j][pos+4];

int flag = 0;

for (int l = 0; l < DSKhaiTrien.size(); l++)

if (DSKhaiTrien[l] == iTuLoai)

flag = 1;

if ( flag == 0 && !isTerminal(iTuLoai)) {

DSKhaiTrien.push_back(iTuLoai);

for(int k = 0; k < iNumRule; k++) {

if (Luat[k][LHS] == iTuLoai) {

vector<int> temp (Luat[k]);

temp[TABLE] = 0;

Table[0].push_back(temp);

} }

} j++;

}

DSKhaiTrien.clear();

//////////////////////////////////////////////////////////////////////// //////////////////

int flag;

Trang 13

// Vong lap thuat toan

i = 1;

while (i <= n)

{

// Lay tu ra

string Word = Cau[i-1];

// Kiem tra trong bang i-1 xem phan tu nao cung tu loai

j = 0;

int num = 0;

// Trong khi ma chua xet het cac bieu thuc trong Table(i-1)

while (j < Table[i-1].size()) {

// Neu bieu thuc thuoc bang i-1

if (Table[i-1][j][TABLE] == i-1) {

int pos = Table[i-1][j][DOT] + 4;

// Vi tri cua dau cham

//int temp1 = Table[i-1][j][pos];

//int temp2 = TuLoai[Word];

if (CungTuLoai(Table[i-1][j][pos], TuLoai[Word])) // Neu Tu loai trung nhau

{

// Dich chuyen cac dau cham, nho cap nhat lai chi so cua cau

Table[i].push_back(Table[i-1][j]);

// Them cau vao bang moi

Table[i][num][DOT]++;

// Dich chuyen vi tri cua dau cham sang ben phai

num++;

} }

j++;

}

// Voi moi cau vua cap nhat lai chi so

j = 0;

// Neu dau cham truoc non-terminal

while (j < num) {

int pos = Table[i][j][DOT];

if (pos < Table[i][j][NUMRHS]) {

int iTuLoai = Table[i][j][pos+4];

flag = 0;

for (int l = 0; l < DSKhaiTrien.size(); l++)

if (DSKhaiTrien[l] == iTuLoai)

flag = 1;

if (flag == 0 && ! isTerminal(iTuLoai)) {

DSKhaiTrien.push_back(iTuLoai);

for(int k = 0; k < iNumRule; k++) {

if (Luat[k][LHS] == iTuLoai)

Trang 14

vector<int> temp (Luat[k]); temp[TABLE] = i;

Table[i].push_back(temp); }

} }

} j++;

} DSKhaiTrien.clear();

// Neu dau cham truoc terminal

j = 0;

while(j < num) {

int pos = Table[i][j][DOT];

if (pos < Table[i][j][NUMRHS]) {

int iTuLoai = Table[i][j][pos+4];

if ( isTerminal(iTuLoai)) {

vector<int> temp(Table[i][j]);

temp[TABLE] = i;

Table[i].push_back(temp);

} }

j++;

}

// Neu dau cham nam o vi tri cuoi cung

j = 0;

vector<vector<int> > Stack;

while (j < num) {

int pos = Table[i][j][DOT];

if (pos == Table[i][j][NUMRHS]) {

vector<int> temp(Table[i][j]);

Stack.push_back(temp);

while(Stack.size() != 0) {

temp = Stack[Stack.size()-1];

Stack.pop_back();

int k = temp[TABLE];

for (int l = 0; l < Table[k].size() && temp[LHS] != SENT; l++)

{

pos = Table[k][l][DOT] + 4;

if (Table[k][l][pos] == temp[LHS] && (Table[k][l][TABLE] == k-1 || Table[k][l][LHS] == SENT))

{

vector<int> LuatPhatSinh =

LuatPhatSinh[DOT]++;

Stack.push_back(LuatPhatSinh); Table[i].push_back(LuatPhatSinh);

Trang 15

} }

} }

j++;

}

// Trien khai tiep tuc nhung luat moi them vao

for (j = num; j < Table[i].size(); j++) {

// Neu chi so bang nho hon chi so bang hien tai

if (Table[i][j][TABLE] < i ) {

int pos = Table[i][j][DOT];

// Neu dau cham chua nam o vi tri cuoi cung

if (pos < Table[i][j][NUMRHS]) {

int iTuLoai = Table[i][j][pos+4];

flag = 0;

for (int l = 0; l < DSKhaiTrien.size(); l+ +)

if (DSKhaiTrien[l] == iTuLoai)

flag = 1;

if (flag == 0 &&! isTerminal(iTuLoai)) {

DSKhaiTrien.push_back(iTuLoai); for(int k = 0; k < iNumRule; k++) {

if (Luat[k][LHS] == iTuLoai) {

vector<int> temp (Luat[k]);

temp[TABLE] = i;

Table[i].push_back(temp);

} }

} }

} }

DSKhaiTrien.clear();

i++;

}

}

void testInput(vector<string> &Cau, map<string, unsigned int> TuLoai, vector<int> Luat[], int &iNumRule)

{

int n;

// Test Danh sach luat

map<int, string> BangTra;

BangTra[noun] = "noun";

BangTra[verb_i] = "verb_i";

Trang 16

BangTra[verb_t] = "verb_t";

BangTra[adj] = "adj";

BangTra[prep] = "prep";

BangTra[pro] = "pro";

BangTra[aux] = "aux";

BangTra[det] = "det";

BangTra[SENT] = "SENT";

BangTra[NP] = "NP";

BangTra[VP] = "VP";

BangTra[PP] = "PP";

BangTra[NP2] = "NP2";

BangTra[NP3] = "NP3";

for (int i = 0; i < iNumRule; i++)

{

vector<int>::iterator j;

j = Luat[i].begin();

cout << BangTra[*j] << " "; j++;

cout << *j << " "; j++;

cout << *j << " "; j++;

cout << *j << " "; j++;

while (j != Luat[i].end()) {

cout << BangTra[*j] << " "; j++;

} cout << endl;

}

// Test Cau nhap vao + Test tu loai

cout << endl << "Test input sentence:";

n = Cau.size();

for(int i = 0; i < n; i++)

{

cout << Cau[i] << " " << TuLoai[Cau[i]] << endl; }

}

void testTableOutput(vector<vector<int> > Table[], int iNumWord) {

map<int, string> BangTra;

BangTra[noun] = "noun";

BangTra[verb_i] = "verb_i";

BangTra[verb_t] = "verb_t";

BangTra[adj] = "adj";

BangTra[prep] = "prep";

BangTra[pro] = "pro";

BangTra[aux] = "aux";

BangTra[det] = "det";

BangTra[SENT] = "SENT";

Trang 17

BangTra[NP] = "NP";

BangTra[VP] = "VP";

BangTra[PP] = "PP";

BangTra[NP2] = "NP2";

BangTra[NP3] = "NP3";

for (int i = 0; i <= iNumWord; i++)

{

cout << "Table " << i << " :" << endl;

for (int j = 0; j < Table[i].size(); j++) {

cout << BangTra[Table[i][j][0]] << " "; cout << Table[i][j][1] << " ";

cout << Table[i][j][2] << " "; cout << Table[i][j][3] << " "; for (int k = 0; k < Table[i][j][NUMRHS]; k++) {

cout << BangTra[Table[i][j][k+4]] << " "; }

cout << endl;

} }

}

void main()

{

vector<string> Cau;

map<string, unsigned int> TuLoai;

vector<int> Luat[100];

int iNumRule;

vector<vector<int> > Table[100];

nhapDaiTu(TuLoai);

nhapDanhTu(TuLoai);

nhapGioiTu(TuLoai);

nhapMaoTu(TuLoai);

nhapNgoaiDongTu(TuLoai);

nhapNoiDongTu(TuLoai);

nhapTinhTu(TuLoai);

nhapTroDongTu(TuLoai);

nhapDanhSachLuat(Luat, iNumRule);

nhapCauInput(Cau);

// testInput(Cau, TuLoai, Luat, iNumRule);

thuatToan(Cau, Luat, TuLoai, iNumRule, Table);

testTableOutput(Table, Cau.size());

getch();

}

Ngày đăng: 13/05/2014, 20:55

HÌNH ẢNH LIÊN QUAN

Bảng 1. Bảng minh họa giải thuật Earley - (Đồ án) Phân tích cú pháp theo phương pháp Ơle
Bảng 1. Bảng minh họa giải thuật Earley (Trang 6)

TỪ KHÓA LIÊN QUAN

w