Khoa Khoa học máy tính
ĐỒ ÁN AUTOMAT
Viết chương trình phân tích cú pháp, tạo và hiển thị
cây cú pháp của một biểu thức chính quy.
MỤC LỤC:
Phần mở đầu
Phần I.Cơ sở lí thuyết.
Phần II.Chương trình.
Phần III.Phần code chính của chương trình.
Phần IV.Tài liệu tham khảo.
Phần mở đầu
• Mục đích của việc giải quyết bài toán được giao: Hiểu được định nghĩa về
biểu thức chính qui.Phương pháp phân tích biểu thức chính qui.
• Để thực hiện đò án Viết chương trình phân tích cú pháp, tạo và hiển thị cây
cú pháp của một biểu thức chính quy ta cần phải:
Thực hiện xử lí chuỗi nhập vào.Xác định xem biểu thức có phải biểu
thức chính qui không.
Định dạng lại biểu thức.
Đưa biểu thức về dạng hậu tố.
Biểu diễn biểu thức chính qui dưới dạng cây nhị phân.
Phần I.Cơ sở lí thuyết
I.Định nghĩa biểu thức chính qui:
Định nghĩa: Biểu thức chính quy được định nghĩa một cách đệ quy như sau:
1. ε là biểu thức chính quy. L(ε)={ε}.
∅ là biểu thức chính quy. L(∅)={∅}.
nếu a∈∑, a là biểu thức chính quy. L(a)={a}.
2. Nếu r, s là các biểu thức chính quy thì:
((r)) là biểu thức chính quy. L((r))=L(r);
r+s là biểu thức chính quy. L(r+s)=L(r)∪L(s);
r.s là biểu thức chính quy. L(r.s)=L(r).L(s);
r* là biểu thức chính quy. L(r*)=L(r)*.
3. Biểu thức chính quy chỉ định nghĩa như trong 1 và 2.
II.Tính chất của biểu thức chính qui:
1.Phép hợp:
• r + ∅ = ∅ + r = r
• r + r = r
• r + s = s + r
• (r + s) + t = r + (s + t) = r + s + t
2.Phép bao đóng:
• e* = e
• ∅* = ∅
• r*r* = r*
• (r*)* = r*
• r* = e + r + r
2
+ … + r
k
+ …
• r* = e + r
+
• (e + r)
+
= (e + r)* = r*
• r*r = r r* = r
+
3.
Phép nối kết:
• re = er = r
• r∅ = ∅r = ∅
• (r + s) t = rt + st
• r (s + t) = rs + rt
4.
Tổng hợp:
• (r* + s*)* = (r*s*)* = (r + s)*
• (rs)*r = r(sr)*
• (r*s)* r* = (r + s)*
5.
Thứ tự ưu tiên của phép toán: * (bao đóng), . (phép nối kết), + (phép hợp).
Ví dụ: Biểu thức chính quy cho ngôn ngữ gồm các xâu nhị phân mà không có hai
số 0 hay hai số 1 liên nhau.
(01)
*
+(10)
*
+0(10)
*
+1(01)
*
hoặc là:
(ε+1)(01)
*
(ε+0)
Thứ tự ưu tiên của phép toán: *, . , +
Do đó: 01
*
+ 1 được hiểu như sau: (0(1)
*
) + 1 (Biểu thức dạng hậu tố).
Phần II.Chương trình
1.Cấu trúc chương trình:
Chương trình được viết bằng ngôn ngữ c# trên ứng dụng WindowsForm của
chương trình visual studio 2008.
Chương trình được viết trên 2 Form, class.
frm_KhoiDong:Hiển thị thông tin đồ án.
frm_ChuongTrinhChinh:Thực hiện các công việc được phải làm.
Các class hỗ trợ cho việc thực hiện chương trình.
-KiemTraRE:Kiểm tra biểu thức chính qui nhập vào.
-RE:Định dạng biểu thức chính qui và đưa biểu thức chính qui về
dạng hậu tố.
-State,map,CacLoi,ThongTinBanDau hỗ trợ cho các class
KiemTraRE,RE.
2.Sơ đồ khối thuật toán:
False
Hiển thị cây
Nhập vào biểu thức chính qui
True
Đưa về dạng hậu tốĐịnh dạng biểu thức
3.Giao diện chương trình:
Khởi động
Chương trình chính
Kết quả
Phần III.Phần code chính của chương trình
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.IO;
namespace Automata
{
public partial class frm_ChuongTrinhChinh : Form
{
RE BieuThucChinhQui = new RE();
Bitmap NoiVe;
Graphics g;
VeNut[] HinhCay;
Point[] ViTriNut;
public frm_ChuongTrinhChinh()
{
InitializeComponent();
ptb_MoPhong.Height = gr_Cay.Height;
ptb_MoPhong.Width = gr_Cay.Width;
KhoiTaoViTri();
NoiVe = new Bitmap(ptb_MoPhong.Width, ptb_MoPhong.Height);
g = Graphics.FromImage(NoiVe);
}
private void KhoiTaoViTri()
{
HinhCay = new VeNut[30];
ViTriNut = new Point[30];
ViTriNut[0] = new Point(238, 31);
for (int i = 0; i < 30; i++)
{
if (i > 0 && i < 3)
{
ViTriNut[i] = new Point(198 + (i - 1) * 79, 91);
}
if(i>2&&i<7)
{
ViTriNut[i] = new Point(198 + (i - 3) * 111, 151);
}
if(i>6&&i<15)
{
ViTriNut[i] = new Point(198 + (i - 7) * 49, 211);
}
if (i > 14 && i < 30)
{
ViTriNut[i] = new Point(198 + (i - 15) * 44, 271);
}
}
}
private void btn_Browse_Click(object sender, EventArgs e)
{
OpenFileDialog ofdt = new OpenFileDialog();
ofdt.InitialDirectory = "C:\\";
ofdt.Filter = "All text file(.txt)|*.txt";
if (ofdt.ShowDialog() == DialogResult.OK)
{
FileStream fs = new FileStream(ofdt.FileName, FileMode.Open);
StreamReader Sts = new StreamReader(fs);
string tempstr = "";
tempstr = Sts.ReadToEnd();
Sts.Close();
fs.Close();
txt_RE.Text = tempstr;
}
}
private void btn_Compile_Click(object sender, EventArgs e)
{
if (txt_RE.Text.Length == 0)
{
MessageBox.Show("Bạn phải nhập vào một Biểu Thức Chính Quy.", "Lỗi!",
MessageBoxButtons.OK, MessageBoxIcon.Error);
txt_RE.Select();
return;
}
try
{
CacLoi errCode = BieuThucChinhQui.CompileWithStats(this.txt_RE.Text,
txt_RE,txt_BanDau,txt_SauDinhDang,txt_Hauto);
if (errCode != CacLoi.DinhDangDung)
{
string sErrSubstring =
txt_RE.Text.Substring(BieuThucChinhQui.GetLastErrorPosition(),
BieuThucChinhQui.GetLastErrorLength());
string sFormat = "Phát hiện lỗi khi biên dịch \nMã lỗi : {0}\nTại vị
trí thứ : {1}\nKý tự : {2}";
sFormat = String.Format(sFormat, errCode.ToString(),
BieuThucChinhQui.GetLastErrorPosition(), sErrSubstring);
txt_RE.Select(BieuThucChinhQui.GetLastErrorPosition(),
BieuThucChinhQui.GetLastErrorLength());
MessageBox.Show(sFormat);
txt_RE.Select();
return;
}
}
catch (Exception ex)
{
MessageBox.Show("Lỗi . !!\n\n" + ex.Message);
txt_RE.Select();
return;
}
}
private void btn_Moi_Click(object sender, EventArgs e)
{
txt_RE.Text = "";
txt_BanDau.Text = "";
txt_Hauto.Text = "";
txt_SauDinhDang.Text = "";
}
private void gr_Cay_SizeChanged(object sender, EventArgs e)
{
ptb_MoPhong.Height = gr_Cay.Height;
ptb_MoPhong.Width = gr_Cay.Width;
}
private bool KiemTraToanTu(string toantu)
{
bool kq;
if (toantu == "." || toantu == "+" || toantu == "*")
kq = true;
else
kq = false;
return kq;
}
private void TaoChiSoThuTu(ref CayNhiPhan CayCanVe)
{
if (CayCanVe.ConTrai!=null)
{
CayCanVe.GanThuTuChoConTrai();
TaoChiSoThuTu(ref CayCanVe.ConTrai);
}
if (CayCanVe.ConPhai!=null)
{
CayCanVe.GanThuTuChoConPhai();
TaoChiSoThuTu(ref CayCanVe.ConPhai);
}
}
private void TaoThuCacNutCay(CayNhiPhan CayCanVe)
{
TaoChiSoThuTu(ref CayCanVe);
GiaTri[0] = CayCanVe.GiaTri;
DuyetHetMang(CayCanVe);
}
string[] GiaTri = new string[30];
CayNhiPhan Phu;
private void ChoVaoMangVe(CayNhiPhan CayCanVe)
{
for (int i = 0; i < GiaTri.Length; i++)
{
if (i == CayCanVe.ThuTu)
{
GiaTri[i] = CayCanVe.GiaTri;
break;
}
}
}
private void DuyetHetMang(CayNhiPhan CayCanVe)
{
if (CayCanVe.ConTrai != null)
{
ChoVaoMangVe(CayCanVe.ConTrai);
DuyetHetMang(CayCanVe.ConTrai);
}
if (CayCanVe.ConPhai != null)
{
ChoVaoMangVe(CayCanVe.ConPhai);
DuyetHetMang(CayCanVe.ConPhai);
}
}
private void bt_Ve_Click(object sender, EventArgs e)
{
for (int j = 0; j < GiaTri.Length; j++)
{
GiaTri[j] = "";
}
CayNhiPhan CayCanVe =
CayBieuThuc.HauToVaoCay(txt_Hauto.Text.ToString());
Phu = CayCanVe;
TaoThuCacNutCay(CayCanVe);
for (int i = 0; i < GiaTri.Length; i++)
{
if (GiaTri[i] != "")
{
if (GiaTri[i] == "." || GiaTri[i] == "*" || GiaTri[i] == "+")
{
HinhCay[i] = new VeNut(ViTriNut[i].X, ViTriNut[i].Y, GiaTri[i],
"ToanTu");
HinhCay[i].HienThi(g);
if (i != 0)
{
HinhCay[i].NoiNut(HinhCay[(i - 1) / 2], HinhCay[i], g);
}
else
{
}
ptb_MoPhong.Image = NoiVe;
}
else
{
HinhCay[i] = new VeNut(ViTriNut[i].X, ViTriNut[i].Y, GiaTri[i],
"ToanHang");
HinhCay[i].HienThi(g);
if (i != 0)
{
HinhCay[i].NoiNut(HinhCay[(i - 1) / 2], HinhCay[i], g);
}
else
{
}
ptb_MoPhong.Image = NoiVe;
}
}
}
}
}
}
Phần IV.Tài liệu tham khảo.
1.Tài liệu slide bài giảng Automat &NNHT-TS. Hà Chí Trung-Bộ môn KHMT-
Khoa CNTT- HVKTQS.
2.Code nguồn trên website .