Hướng dẫn tạo bộ phân tích từ vựng cho ngôn ngữ Pascal
lượt xem 75
download
Cách dễ dàng và nhanh chóng nhất để xây dựng bộ phân tích từ vựng cho 1 ngôn ngữ nào đó là dùng ngôn ngữ Lex (Lexical Analyzer Generator). File Lex chứa các biểu thức chính quy, mỗi biểu thức chính quy miêu tả 1 token cụ thể của ngôn ngữ, định dạng tổng quát của file Lex như sau: %{ //các lệnh định nghĩa viết bằng C hay C++ %} %% //các biểu thức chính quy nhận dạng các token %% //các đoạn code C hay C++ miêu tả ứng dụng Sau đây là file Lex đọc file mã...
Bình luận(0) Đăng nhập để gửi bình luận!
Nội dung Text: Hướng dẫn tạo bộ phân tích từ vựng cho ngôn ngữ Pascal
- Hướng dẫn tạo bộ phân tích từ vựng cho ngôn ngữ Pascal Xin hướng dẫn tạo bộ phân tích từ vựng cho ngôn ngữ Pascal, tức là chương trình đọc tệp .pas và in kết quả phân tích từ vựng ra màn hình. Cách dễ dàng và nhanh chóng nhất để xây dựng bộ phân tích từ vựng cho 1 ngôn ngữ nào đó là dùng ngôn ngữ Lex (Lexical Analyzer Generator). File Lex chứa các biểu thức chính quy, mỗi biểu thức chính quy miêu tả 1 token cụ thể của ngôn ngữ, định dạng tổng quát của file Lex như sau: %{ //các lệnh định nghĩa viết bằng C hay C++ %} %% //các biểu thức chính quy nhận dạng các token %% //các đoạn code C hay C++ miêu tả ứng dụng Sau đây là file Lex đọc file mã nguồn pascal rồi xuất ra danh sách các token tương ứng: %{ #include //định nghĩa các biến cần dùng unsigned char ch; unsigned yline = 1; char buff[2048]; //hàm dò chuỗi chú thích void scan_comment() { unsigned char ch; while ((ch=input())>0 && ch != '}') if (ch == '\n') yline++; if (ch == '}') return; fprintf (stderr,"EOF duoc tim thay trong luc do chu thich (hang %d)\n",yline); exit(1); } //hàm dò hằng chuỗi void scan_string() { unsigned char ch, *pret; int i= 0; while ((ch=input()) >0 && ch != '\'') { if (ch == '\n') yline++; if (i >= 2047) { fprintf (stderr,"Chuoi qua dai (%d)\n",yline); exit(1); } buff[i++] = ch;
- } buff[i++] = 0; if (ch == '\'') return; fprintf (stderr,"EOF duoc tim thay trong luc do chuoi (hang %d)\n",yline); exit(1); } %} %% "{" { scan_comment(); } "'" { scan_string(); printf("[string,'%s'] ",buff); } "+" { printf ("[addop] "); } "-" { printf ("[subop] "); } "*" { printf ("[mulop] "); } "/" { printf ("[divop] "); } "" { printf ("[thanop] "); } "(" { printf ("[lparent] "); } ")" { printf ("[rparent] "); } "," { printf ("[comma] "); } ";" { printf ("[pcomma] "); } ":" { printf ("[toodot] "); } ":=" { printf ("[assign] "); } "=" { printf ("[equal] "); } "." { printf ("[dot] "); } [-][0-9]+ | [0-9]+ { printf ("[iconst,%s] ", yytext); } [0-9]*[.][0-9]* | [-][0-9]*[.][0-9]* | [0-9]*[.][0-9]*[eE][-]*[0-9]+ | [-][0-9]*[.][0-9]*[eE][-]*[0-9]+ { printf ("[rconst,%s] ", yytext); } [pP][rR][oO][gG][rR][aA][mM] { printf ("[program] "); } [uU][sS][eE][sS] { printf ("[uses] "); } [vV][aA][rR] { printf ("[var] "); } [tT][yY][pP][eE] { printf ("[type] "); } [bB][eE][gG][iI][nN] { printf ("[begin] "); } [eE][nN][dD] { printf ("[end] "); } [fF][uU][nN][cC][tT][iI][oO][nN] { printf ("[function] "); } [pP][rR][oO][cC][eE][dD][uU][rR][eE] { printf ("[procedure] "); } [iI][fF] { printf ("[if] "); } [tT][hH][eE][nN] { printf ("[then] "); } [eE][lL][sS][eE] { printf ("[else] "); } [dD][oO] { printf ("[do] "); } [rR][eE][pP][eE][aA][tT] { printf ("[repeat] "); } [uU][nN][tT][iI][lL] { printf ("[until] "); } [a-zA-Z][a-zA-Z0-9\_]* { printf ("[ident,%s] ", yytext);}
- [ \t\r]* { } [\n] { printf("\n"); yline++; } . { fprintf(stderr,"Syntax error: symbol '%c'(%d) o hang %d\n",yytext[0],yytext[0], yline); } %% //điểm nhập của chương trình void main(int argc,char *argv[]) { //mở file mã nguồn if ((yyin = fopen(argv[1],"r")) == 0) { fprintf(stderr,"Khong the mo file %s\n",argv[1]); exit(1); } //khởi động yylex yylex_init(); //gọi yylex phân tích từ vựng yylex(); } Lưu ý rằng chúng tôi chỉ đặc tả một số token Pascal thường dùng, bạn dựa vào các lệnh đặc tả để đặc tả thêm các token còn lại cho đủ. Sau khi đã viết xong file Lex, bạn có thể dùng tool Lex dịch nó ra file *.c tương ứng. Thí dụ dưới đây là hàng lệnh gọi tiện ích FLEX dịch file Lex ra *.c: flex -tl pascalscan.l >pascalscan.c Sau khi đã có file *.c, bạn có thể dùng chương trình dịch C hay C++ dịch nó ra file khả thi. Sau khi có file khả thi (thí dụ tên là pascalscan.exe), bạn có thể dùng nó với cú pháp sau đây: pascalscan mypro.pas để đọc file mã nguồn Pascal rồi hiển thị các token tương ứng lên màn hình. Hoặc dùng hàng lệnh sau: pascalscan mypro.pas >output để đọc file mã nguồn Pascal rồi xuất các token tương ứng lên file "output" để tham khảo sau đó. Lưu ý rằng chuỗi token nhận dạng được bởi bộ phân tích từ vựng thường được gửi tới bộ phân tích cú pháp chứ ít ai hiển thị hay xuất ra file như thí dụ trên. Bạn có thể tải tiện ích FLEX trên Internet (đây là ứng dụng mã nguồn mở). Tôi muốn viết một ứng dụng đọc và hiển thị file TXT dạng Unicode trên Windows, nhưng tôi không thể hiển thị đúng các ký tự Unicode mặc dù đã sử dụng kiểu widestring và widechar. Mặc dù mã Unicode đã được chuẩn hóa và tổng quát để miêu tả đồng thời nhiều ký tự của nhiều ngôn ngữ, nhưng hiện nay việc hiện thực xử lý mã Unicode không hoàn hảo, tùy vào môi trường lập trình và ngôn ngữ lập trình được dùng mà mức độ hỗ trợ mã Unicode rất khác nhau. Thí dụ nếu bạn dùng môi trường .Net (VC#, VJ#, VB .Net) thì mức độ hỗ trợ mã Unicode là rất tốt, hầu như trong suốt hoàn toàn với code mà bạn viết. Tuy nhiên nếu bạn dùng VB hay tệ hơn là VC++ thì mức độ hỗ trợ mã Unicode còn khá thấp và chưa được trong suốt cho người lập trình. Thí dụ
- các đối tượng giao diện có sẵn của môi trường VB 6.0 trở xuống không thể hiển thị đúng được chuỗi Unicode, bạn phải dùng các đối tượng tương ứng trong thư viện Form2 kèm theo VB. Còn trong VC++, nếu bạn dịch ứng dụng ở chế độ mặc định (ANSI) thì ứng dụng sẽ không xử lý được chuỗi Unicode. Điều kiện tiên quyết để viết ứng dụng xử lý tốt chuỗi Unicode trong VC++ là phải dịch ứng dụng ở chế độ Unicode (dùng macro dịch là -D "Unicode"). Về mặt lập trình VC++, nếu bạn muốn xử lý chuỗi Unicode cấp thấp hay muốn gọi các hàm API Windows để xử lý chuỗi Unicode, bạn sẽ dùng kiểu dữ liệu widechar và widestring để định nghĩa các biến chứa ký tự hay chuỗi Unicode. Lưu ý rằng Windows chia tập các hàm có thông số chuỗi ra thành 2 loại: loại chỉ xử lý chuỗi ANSI và loại chỉ xử lý chuỗi Unicode. Thí dụ hàm TextOut() chỉ hiển thị chuỗi ANSI, còn hàm TextOutW() chỉ hiển thị chuỗi Unicode. Việc chuyển chuỗi ANSI về mã Unicode luôn thành công, nhưng ngược lại, việc chuyển chuỗi Unicode về ANSI có thể làm mất thông tin. Sau đây là đoạn code VC++ thực hiện việc thiết lập font hỗ trợ Unicode cho Form, gọi hàm API TextOutW() để xuất chuỗi Unicode "Nguyễn Văn Hiệp" ra vị trí (10,100), xuất chuỗi "Nguyễn Văn Hiệp" ra TextBox được nhận dạng bởi biến m_edit. //xây dựng record miêu tả font cần dùng LOGFONT lgcursfont; // font structure lgcursfont.lfHeight = 24; lgcursfont.lfWidth = 10; lgcursfont.lfEscapement = 0; lgcursfont.lfOrientation = 0; lgcursfont.lfWeight = FW_NORMAL; lgcursfont.lfItalic = FALSE; lgcursfont.lfUnderline = FALSE; lgcursfont.lfStrikeOut = FALSE; lgcursfont.lfCharSet = ANSI_CHARSET; lgcursfont.lfOutPrecision = OUT_DEFAULT_PRECIS; lgcursfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; lgcursfont.lfQuality = DEFAULT_QUALITY; lgcursfont.lfPitchAndFamily = FF_DONTCARE; wcscpy(lgcursfont.lfFaceName, _T("Times")); //thiết lập font cho Form HDC hDC = this->GetDC()->m_hDC; HFONT hFont = ::CreateFontIndirect (&lgcursfont); ::SelectObject(hDC,hFont); //xây dựng chuỗi Unicode "Nguyễn Văn Hiệp" wchar_t buf[50]; buf[0] = 'N'; buf[1] = 'g'; buf[2] = 'u'; buf[3] = 'y'; buf[4] = 0x1ec5; buf[5] = 'n'; buf[6] = ' '; buf[7] = 'V'; buf[8] = 0x103; buf[9] = 'n'; buf[10] = ' '; buf[11] = 'H'; buf[12] = 'i'; buf[13] = 0x1ec7;
- buf[14] = 'p'; buf[15] = 0; //xuất chuỗi Unicode "Nguyễn Văn Hiệp" ra tọa độ (10,100) TextOutW(hDC,10,100,buf, wcslen(buf)); //xuất chuỗi Unicode "Nguyễn Văn Hiệp" ra TextBox UpdateData(TRUE); m_edit = buf; UpdateData(FALSE);
CÓ THỂ BẠN MUỐN DOWNLOAD
-
Hướng dẫn sử dụng phần mềm kế toán MISA-SME phiên bản 7.9 part 1
25 p | 902 | 302
-
Thiết kế website bằng phần mềm Adobe Dreamweaver CS5
13 p | 761 | 230
-
Hướng dẫn cách giữ thông tin an toàn và bí mật phần 7
11 p | 90 | 19
-
Tích hợp khai phá dữ liệu trong InfoSphere Warehouse với việc tạo báo cáo Cognos của IBM, Phần 4: Phân đoạn khách hàng với InfoSphere Warehouse và Cognos
37 p | 115 | 19
-
Hướng dẫn SQL & XQuery cho IBM DB2, Phần 4: Phân tích dữ liệu
39 p | 123 | 9
-
Giáo trình hướng dẫn phân tích cấu tạo mail RR SOA quản lý mail cho miền nội bộ p2
5 p | 51 | 8
-
Giáo trình hướng dẫn cách tạo ảnh thiên thần bằng phương pháp sử dụng filter trong bộ lọc p2
7 p | 70 | 7
-
Giáo trình hướng dẫn phân tích mail server quản lý mail cho miền nội bộ hoặc miền con p2
5 p | 76 | 7
-
Giáo trình hướng dẫn phân tích quá trình sử dụng dữ liệu của report để chỉnh sửa application p2
5 p | 76 | 6
-
Giáo trình hướng dẫn phân tích cấu tạo mail RR SOA quản lý mail cho miền nội bộ p7
5 p | 62 | 5
-
Giáo trình hướng dẫn phân tích cấu tạo mail RR SOA quản lý mail cho miền nội bộ p8
5 p | 55 | 5
-
Giáo trình hướng dẫn phân tích cấu tạo mail RR SOA quản lý mail cho miền nội bộ p9
5 p | 55 | 4
-
Giáo trình hướng dẫn phân tích cấu tạo mail RR SOA quản lý mail cho miền nội bộ p1
5 p | 45 | 4
-
Giáo trình hướng dẫn phân tích cấu tạo mail RR SOA quản lý mail cho miền nội bộ p6
5 p | 48 | 4
-
Giáo trình hướng dẫn phân tích cấu tạo mail RR SOA quản lý mail cho miền nội bộ p4
5 p | 45 | 4
-
Giáo trình hướng dẫn phân tích cấu tạo mail RR SOA quản lý mail cho miền nội bộ p3
5 p | 43 | 4
-
Giáo trình hướng dẫn phân tích cấu tạo mail RR SOA quản lý mail cho miền nội bộ p10
5 p | 45 | 3
Chịu trách nhiệm nội dung:
Nguyễn Công Hà - Giám đốc Công ty TNHH TÀI LIỆU TRỰC TUYẾN VI NA
LIÊN HỆ
Địa chỉ: P402, 54A Nơ Trang Long, Phường 14, Q.Bình Thạnh, TP.HCM
Hotline: 093 303 0098
Email: support@tailieu.vn