Bài tập lập trình số 01
Phân tích từ vựng
I. Từ vựng của ngôn ngữ SLANG
SLANG gồm các từ loại sau
ident_token – tên (bắt đầu bằng chữ cái hoặc dấu gạch dưới, theo
sau là chữ cái, chữ số hoặc dấu gạch dưới)
num_token – số nguyên
comment_token – chú thích (chú thích kiểu C – trong cặp /* comment
*/)
begin_token – từ khóa begin
end_token – từ khóa end
int_token – từ khóa kiểu int
var_token – từ khóa var (khai báo biến)
procedure_token – từ khóa procedure (khai báo thủ tục)
call_token – từ khóa call (gọi thủ tục)
read_token – từ khóa read (đọc từ bàn phím)
write_token – từ khóa write (viết ra màn hình)
if_token – từ khóa if
then_token – từ khóa then
else_token – từ khóa else
fi_token – từ khóa fi (kết thúc if)
while_token – từ khóa while
do_token – từ khóa do
od_token – từ khóa od (kết thúc do)
negate_token – toán tử neg
absolute_token – toán tử abs
open_token – dấu mở ngoặc
close_token – dấu đóng ngoặc
list_token – dấu phẩy
period_token – dấu chấm
separator_token – dấu chấm phẩy
becomes_token – dấu gán (=)
plus_token – dấu cộng (+)
minus_token – dấu trừ (-)
times_token – dấu nhân (*)
over_token – dấu chia (/)
modulo_token – dấu lấy phần dư (%)
equal_token – dấu bằng (==)
not_equal_token – dấu khác (!=)
less_than_token – dấu nhỏ hơn (<)
less_or_equal_token – dấu nhỏ hơn hoặc bằng (<=)
greater_than_token – dấu lớn hơn (>)
greater_or_equal_token – dấu lớn hơn hoặc bằng (>=)
err_token – lỗi từ vựng
Lưu ý: SLANG phân biệt chữ hoa chữ thường
II. Lập trình
Viết bộ phân tích từ vựng của ngôn ngữ SLANG
- Khai báo lớp Token thể hiện từ tố gồm các thành viên: từ loại, thuộc tính,
tên file, số dòng. Các hàm thành viên bao gồm: các hàm set, get thuộc tính,
hàm in từ tố ra màn hình.
- Viết lớp Lexer có thành viên là tên file hoặc một luồng nhập (C++ istream
hoặc Java InputStream) và hàm thành viên next_token() có kiểu trả về là
Token.
- Hàm next_token() đọc từ file hoặc luồng nhập và trả lại lần lượt các từ
vựng thuộc ngôn ngữ SLANG hoặc err_token nếu có lỗi từ vựng.
- Viết một hàm main() để thử chạy hàm next_token() với một chương trình
thuộc ngôn ngữ SLANG.
Ví dụ:
Mã nguồn:
begin
var int number, sum;
sum = 0;
read(number);
while number != 0 do
sum = sum + num;
read(number);
od;
write(sum);
end
Output (ví dụ)
<begin_token, >
<var_token, >
<int_token, >
<ident_token, number>
<list_token, >
<ident_token, sum>
<separator_token, >
<ident_token, sum>
<becomes_token, >
<num_token, 0>
<separator_token, >
<read_token, >
<open_token, >
<ident_token, number>
<close_token, >
<separator_token, >
<while_token, >
<ident_token, number>
<not_equal_token, >
<num_token, 0>
<do_token, >
<ident_token, sum>
<becomes_token, >
<ident_token, sum>
<plus_token, >
<ident_token, number>
<separator_token, >
<read_token, >
<open_token, >
<ident_token, number>
<close_token, >
<separator_token, >
<od_token, >
<separator_token, >
<write_token, >
<open_token, >
<ident_token, sum>
<close_token, >
<separator_token, >
<end_token, >
III. Cải tiến chương trình phân tích từ vựng
- Thêm vào các từ tố cho các câu lệnh for, switch … case
- Thông báo lỗi từ vựng: chỉ ra vị trí xảy ra lỗi
- Hồi phục lỗi: bỏ qua lỗi và dịch tiếp để bắt hết các lỗi từ vựng
IV. Nộp bài tập
Sinh viên cần nộp các tài liệu sau
- Chương trình
- Tài liệu: khoảng 2 trang A4
o Giới thiệu nhóm
o Tóm tắt giải pháp
o Nêu các khó khăn và cách giải quyết
1. Xét ngôn ngữ sử dụng các thẻ (tags) được mô tả như sau:
Ký hiệu kết thúc: { < , > , / , = , word }
Mỗi thẻ bắt đầu bằng < và kết thúc bằng >
Có hai loại thẻ: thẻ mở và thẻ đóng
Thẻ mở có dạng <word word = word … >, tức là bắt đầu bằng word, tiếp
theo là các cặp word được nối với nhau bằng dấu =, thể hiện các thuộc tính
của thẻ.
Thẻ đóng có dạng </word>
Mỗi thẻ mở phải có một thẻ đóng tương ứng phía sau. Giữa cặp thẻ mở và
đóng đó có thể có dãy các word dài tuỳ ý.
Ví dụ: xâu <word word=word word=word><word>word word
word</word><word></word></word> thuộc ngôn ngữ trên.
a, Hãy viết văn phạm phi ngữ cảnh cho ngôn ngữ trên .
b, Tìm các kí hiệu có thể triệt tiêu được.
c, Tính các tập FIRST, FOLLOW cho văn phạm trên.
d, Lập bảng phân tích LL(1), chỉ ra những vị trí xung đột trên bảng.
e, Hãy chỉ ra nguyên nhân khiến văn phạm này không phải là LL(1).
2. Xét văn phạm sau
E E op E | (E) | num
op + | * | ^
Văn phạm này thể hiện ngôn ngữ gồm các công thức sử dụng phép cộng, nhân và
hàm mũ. Tuy nhiên, văn phạm này bị nhập nhằng. Ta muốn có một văn phạm không
nhập nhằng với phép mũ (^) được ưu tiên cao nhất, sau đó đến phép nhân (*) rồi đến
phép cộng (+).
a, Viết một văn phạm thuộc lớp LL(1) cho ngôn ngữ trên, cho phép tạo ra cây suy dẫn
theo thứ tự ưu tiên các phép toán như mong muốn. Hãy chứng minh văn phạm của
bạn là văn phạm thuộc lớp LL(1).
b, Viết cây suy dẫn của biểu thức 2 ^ 3 + 4 * 5 sử dụng văn phạm của phần a).
c, Viết một văn phạm thuộc lớp LR(1) cuả ngôn ngữ này, sử dụng thứ tự ưu tiên các
phép toán như trên và bắt buộc các phép toán kết hợp về bên trái.
3. Java hoặc C++ cho phép gán được sử dụng nhiều lần trong cùng một biểu thức.
Ví dụ: a = b = c, a = b = c + d.
Phép gán kiểu này có tính kết hợp về bên phải, tức là a = b = c tương đương với
a = (b = c). Văn phạm sau thể hiện ngôn ngữ này
S A
A id = R
R A | E
E E + T | T
T id | (A)
a, Xây dựng bảng phân tích LR(0) cho văn phạm này.
b, Văn phạm này thuộc lớp LR(0) hay không? Cho lý do.
c, Văn phạm này thuộc lớp SLR hay không? Cho lý do.
d, Văn phạm này thuộc lớp LR(1) hay không? Cho lý do.
4. Hai kỹ thuật phân tích LL(1) và LALR(1) là hai kỹ thuật được sử dụng rộng rãi
hiện nay. Mỗi kỹ thuật đều có điểm mạnh riêng. Hãy so sánh hai kỹ thuật phân
tích này trong khoảng nửa trang giấy (A4).
Gợi ý: thử đánh giá trên các tiêu chí: tính đơn giản (của bộ phân tích và văn phạm),
khả năng phân tích (lớp ngôn ngữ), kích thước bảng phân tích, v.v… và các tiêu chí
khác mà bạn nghĩ ra.
Bài tập về nhà 1
(nộp bài vào ngày có buổi học của tuần thứ 2)
1. Viết biểu thức chính quy cho các URL của phương thức HTTP, biết rằng mỗi
URL gồm 4 phần: phương thức (http://), DNS name (coltech.vnu.edu.vn) hoặc địa
chỉ IP (203.162.0.181), cổng (:8080) – có thể có hoặc không, và đường dẫn tới
file. Để đơn giản, quy ước như sau:
• DNS name: gồm các xâu chữ cái tiếng Anh khác rỗng phân cách bởi dấu
chấm.
• Địa chỉ IP: gồm 4 số nguyên dương phân cách bởi dấu chấm.
• Cổng: là một số nguyên dương đi sau dấu hai chấm (“:”).
• Đường dẫn: là một đường dẫn hợp lệ theo kiểu Unix, bao gồm các chữ cái,
chữ số, dấu chấm và dấu sổ chéo (“/”). Không cho phép 2 dấu sổ chéo đi
liền nhau - tức là không được phép có thư mục không có tên. Đường dẫn
phải bắt đầu bằng dấu sổ chéo và có thể kết thúc bằng dấu sổ chéo.
2. Ghi chú trong ngôn ngữ C được bắt đầu bằng “/*”, tiếp đó là nội dung ghi chú và
kết thúc bằng “*/”. Nội dung ghi chú không được phép có “*/” đi liền nhau, tuy
nhiên vẫn cho phép “*” và “/” nếu chúng không đứng cạnh nhau. Hãy viết biểu
thức chính quy cho các trường hợp sau, hoặc giải thích lí do không tồn tại biểu
thức chính quy tương ứng.
• Ghi chú trong ngôn ngữ C.
VD: /* C-style comment */
• Ghi chú trong ngôn ngữ C, tuy nhiên cho phép “*/” nếu chúng được đặt
trong cặp nháy kép “”.
VD: /* C-style comment with “*/” extension */
• Ghi chú trong ngôn ngữ C, tuy nhiên cho phép các ghi chú lồng nhau
VD: /* C-style comment with /* nested comment */ extension */