Xây dựng một trình biên dịch hoàn chỉnh là một công việc đòi hỏi có nhiều đầu
tư về thời gian, nhân lực, cũng như một khối lượng kiến thức lớn. Do đó, khuôn khổ
khóa luận tập trung chủ yếu vào việc thu thập và tích lũy các thông tin từ chương trình
nguồn để tạo ra một dạng biễu diễn trung gian (mã 3-địa chỉ) tương đương. Với định
hướng đó, nhóm sinh viên đã phần nào hoàn thành việc :
- Nghiên cứu các kỹ thuật xây dựng trình biên dịch, đặc biệt là chuyến trước
của trình biên dịch.
- Khảo sát 2 công cụ hỗ trợ đắc lực cho việc phát sinh bộ phân tích từ vựng
(FLEX) và bộ phân tích cú pháp (BISON).
140 trang |
Chia sẻ: lylyngoc | Lượt xem: 2505 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Khảo sát và xây dựng thử nghiệm chuyến trước của trình biên dịch dành cho ngôn ngữ ANSI C giản lược, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
a = c;
Theo cây phân tích cú pháp (hình 4.6), inclusive_or_expr sẽ tiếp tục
dẫn ra một nhánh khác để phát sinh biểu thức so sánh. Kết quả của các biểu thức so
sánh đó (true hoặc false) sẽ dược lưu trữ trong các thuộc tính và lan truyền
tổng hợp lên các nút trên. Theo thứ tự duyệt cây (trái trước), ta có thể thấy được :
- op1 chính là kết quả của phép so sánh a>b
- op2 chính là kết quả của phép so sánh b>c
- op3 chính là kết quả của phép so sánh a>c
- op12 là kết quả của a>b && b>c hay op1 && op2
- op123 là kết quả của (a>b && b>c || a>c) hay op12||op3
Để xác định giá trị của op123, ta chỉ cần tính lần lượt các giá trị op1,
op2, op12, op3. Nhưng thực tế, chỉ cần op1 là false thì op12 chắc chắn là
false, bất chấp giá trị của op2; op3 là true thì op123 chắc chắn là true, bất
chấp giá trị của op12. Vì vậy, ta có thể tối ưu quá trình tính toán bằng cách đưa vào
các luồng điều khiển, các chỉ thị rẽ nhánh như đã trình bày ở trên.
Ứng với mỗi hành vi rút gọn, một hành động ngữ nghĩa được thực thi. Cây
cú pháp duyệt theo thứ tự trái trước nên các thứ tự các hành vi được thực hiện theo
thứ tự ACT01ACT02ACT03…ACT14. Bảng 4.4 mô tả chi tiết và kết quả
phát sinh mã ba địa chỉ của các hành vi ngữ nghĩa.
83
Hình 4.16. Cây phân tích cú pháp của cấu trúc điều khiển Ví dụ 4.16
8
3
Chương 4 – Xây dựng chuyến trước của trình biên dịch
84
Thứ tự Hành vi ngữ nghĩa Mã 3 địa chỉ Chú thích
ACT01 static int label = 0;
genLabel(L_TEST, $$ = ++label);
TST1: Thuộc tính yyint của test
được gán bằng 1.
ACT02 STACK_PUSH(AndOrStack, 0); Push 0 và AndOrStack
AndOrStack : 0
ACT03 label = STACK_ITEM(AndOrStack,0) =
tf_label();
if( $1 )
{
falseLab = newLabel(L_FALSE, label);
geniCodeIfx($1, NULL, falseLab);
}
IFFALSE op1 GOTO F1
Label = 1
TOP(AndOrStack)=1
AndOrStack : 1
ACT04 label = STACK_ITEM(AndOrStack,0);
falseLab = newLabel(L_FALSE, label);
geniCodeIfx($4, NULL, falseLab);
IFFALSE op2 GOTO F1 label=TOP(AndOrStack)
label = 1
ACT05 if( label = STACK_POP(AndOrStack))
{
genGoto(L_TRUE, label);
$$ = gen_false_true(label, NULL);
}
else
$$ = $1;
GOTO T1
F1:
op12 = 0
GOTO E1
T1:
op12 = 1
E1:
AndOrStack : NULL
label = 1
op12 được khởi tạo và xác
định giá trị từ giá trị của
op1 và op2.
ACT06 STACK_PUSH(AndOrStack, 0);
Push 0 vào AndOrStack.
AndOrStack : 0
ACT07 label = STACK_ITEM(AndOrStack,0) =
tf_label();
if( $1 )
{
trueLab = newLabel(L_TRUE, label);
geniCodeIfx($1, trueLab, NULL);
}
IFTRUE op12 GOTO T2
label = 2 (vì tf_label() được
gọi lần thứ 2)
TOP(AndOrStack)=2
AndOrStack : 2
Bảng 4.4. Mô tả các hành vi ngữ nghĩa và phát sinh mã ba địa chỉ của lệnh if
8
4
Chương 4 – Xây dựng chuyến trước của trình biên dịch
85
ACT08 STACK_PUSH(AndOrStack, 0); Push 0 vào AndOrStack.
AndOrStack : 0 2
ACT09 if( label = STACK_POP(AndOrStack))
{
genGoto(L_TRUE, label);
$$ = gen_false_true(label, NULL);
}
else
$$ = $1;
AndOrStack : 2
label = 0 không phát
sinh mã trung gian mà chỉ
lan truyền op3
ACT10 label = STACK_ITEM(AndOrStack,0)
trueLab = newLabel(L_TRUE, label);
geniCodeIfx($4, trueLab, NULL);
IFTRUE op3 GOTO T2
label = 2
ACT11 if(label = STACK_POP(AndOrStack))
{
$$ = gen_false_true(label, NULL);
}
else
$$ = $1;
F2:
op123 = 0
GOTO E2
T2:
op123 = 1
E2:
label = 2
AndOrStack : NULL
op123 được khởi tạo và
xác định giá trị từ giá
trị của op12 và op3.
ACT12 $$ = $1;
//Lan truyền thuộc tính
op123 đã được tính toán
hoàn chỉnh là lan truyền
lên.
ACT13 $$ = $1;
falseLab = newLabel(L_NEXT, $$);
geniCodeIfx($2, NULL, falseLab);
IFFALSE op123 GOTO
EXIT1
ACT14 genLabel(L_NEXT, $3); EXIT1:
Bảng 4.4. (tiếp theo)
8
5
86
Như vậy, sau quá trình duyệt cây phân tích cú pháp cũng như thực hiện các hành
vi ngữ nghĩa, ta nhận được bộ mã 3-địa chỉ:
op1 = a > b //Tính toán qua inclusive_or_expr
TST1:
IFFALSE op1 GOTO F1
op2 = b > c //Tính toán qua inclusive_or_expr
IFFALSE op2 GOTO F1
GOTO T1
F1:
op12 = 0
GOTO E1
T1:
op12 = 1
E1:
IFTRUE op12 GOTO T2
op3 = a > c //Tính toán qua inclusive_or_expr
IFTRUE op3 GOTO T2
F2:
op123 = 0
GOTO E2
T2:
op123 = 1
E2:
IFFALSE op123 GOTO EXIT1
a = c //Phát sinh mã qua statement
EXIT1:
Dịch lệnh switch-case:
Câu lệnh switch được dùng để thay thế cho lệnh if trong trường hợp có quá
nhiều điều kiện để chọn. Cú pháp :
Chương 4 – Xây dựng chuyến trước của trình biên dịch
87
switch (E) {
case V1: S1
case V2: S2
…
case Vn-1: Sn-1
default: Sn
}
Công việc của trình biên dịch cần làm là phát sinh mã để:
– Đánh giá biểu thức E.
– Xác định giá trị Vj trong các trường hợp (case) sao cho Vj bằng giá trị
biểu thức đã được đánh giá. Nếu không tìm thấy giá trị Vj nào thỏa mãn,
biểu thức sẽ rơi vào trường hợp default (mặc định).
– Thực thi những chỉ thị (Sj) kết hợp với giá trị được xác định.
Mã trung gian cho trường hợp tổng quát theo đề nghị của Alho [1, 2]:
Mã đánh giá giá trị biểu thức.
goto test
L1 : mã cho S1
goto next
L2 : mã cho S2
goto next
...
Ln-1: mã cho Sn-1
goto next
Ln : mã cho Sn
goto next
test:
if E = V1 goto L1
if E = V2 goto L2
...
if E = Vn-1 goto Ln-1
goto Ln
next:
Cách biểu diễn 1
Mã đánh giá giá trị biểu thức.
if E != V1 goto L1
mã cho S1
goto next
L1 : if E != V2 goto L2
mã cho S2
goto next
L2 : ...
Ln-2: if E = Vn-1 goto Ln-1
mã cho Sn-1
goto next
Ln-1: mã cho Sn
next:
Cách biểu diễn 2
Chương 4 – Xây dựng chuyến trước của trình biên dịch
88
Nhưng thực tế trong một chương trình C, những mã ngắt (goto next) sau khi
thực thi lệnh thích hợp chỉ được sử dụng khi người dùng gọi tường minh lệnh ngắt
(break).
Ta sẽ sử dụng cách biểu diễn thứ nhất để phát sinh mã cho trường hợp lệnh
switch và mã phát sinh sẽ theo đúng như một chương trình C chuẩn. Một số các luật
sinh cùng luật ngữ nghĩa :
1. selection_statement SWITCH '(' expr ')'
{
STACK_PUSH(SwitchStack, new_stab($3,
++Case_label));
genGoto(L_SWITCH, Case_label);
STACK_PUSH(BreakStack, ++Case_label);
STACK_PUSH(BreakLabelStack, L_SWITCH);
} compound_statement
{
gen_stab(STACK_POP(SwitchStack));
STACK_POP(BreakStack);
STACK_POP(BreakLabelStack);
}
2. statementlabeled_statement | jump_statement
3. compound_statement‟{„ statement_list „}‟
4. statement_liststatement | statement_list statement
5. jump_statementBREAK „;‟
{
genGoto(STACK_ITEM(BreakLabelStack,0),
STACK_ITEM(BreakStack, 0);
}
Chương 4 – Xây dựng chuyến trước của trình biên dịch
89
6. labeled_statementCASE constant_expr ':'
{
add_case(STACK_ITEM(SwitchStack,0),$2,
++Case_label);
genLabel(L_SWITCH, Case_label);
}
7. labeled_statementDEFAULT ':'
{
add_default_case(STACK_ITEM(SwitchStack, 0),
++Case_label);
genLabel(L_SWITCH, Case_label);
}
8. constant_expr conditional_expr
Ví dụ 4.17: Dịch cấu trúc lệnh switch sau sang chỉ thị mã ba địa chỉ :
switch(x)
{
case 1:
y = 0;
break;
case 2:
y = 1;
default:
y = x;
}
Ta xây dựng được cây phân tích cú pháp :
90
Hình 4.17. Cây phân tích cú pháp cho cấu trúc lệnh switch
9
0
91
Ta sẽ phát sinh mã kiểm tra giá trị biểu thức so với các trường hợp đưa ra ở
cuối bộ mã (ACT06) vì khi đó, ta mới thu thập đủ thông tin về các nhãn, cũng như
những giá trị hằng số cần cho việc so sánh. Những thông tin về các case sẽ được lưu
trữ trong quá trình duyệt cây phân tích cú pháp. Ta có 2 cấu trúc chính như sau:
– case_val :
Trong đó, on_this là toán hạng lưu trữ thông tin của giá trị hằng số, go_here
là thông tin về nhãn của trường hợp này.
– stab (switch table):
Trong đó :
o table : bảng lưu trữ các trường hợp trong khi dịch (case_val)
o cur : con trỏ tới các trường hợp.
o op : toán hạng lưu trữ thông tin của biểu thức đã được tính toán.
o def_label : nhãn cho trường hợp default.
o stab_label : nhãn ở cuối và đầu và cuối lệnh switch ta đang xét.
table
cur
1
3
2
4
x
def_label = 5 stab_label = 1
on_this
go_here
Hình 4.18. Mô tả cấu trúc một case_val
Hình 4.19. Mô tả cấu trúc một switch table
92
Thứ tự Hành vi ngữ nghĩa Mã 3 địa chỉ Chú thích
ACT01 STACK_PUSH(SwitchStack,new_stab($3,
++Case_label));
genGoto(L_SWITCH, Case_label);
STACK_PUSH(BreakStack, ++Case_label);
STACK_PUSH(BreakLabelStack, L_SWITCH);
GOTO SW1 Case_label: biến toàn
cục, khởi tạo là 0.
BreakStack : 2
BreakLabelStack : SW
Case_label = 2
ACT02 add_case(STACK_ITEM(SwitchStack,0),$2,
++Case_label);
genLabel(L_SWITCH, Case_label);
SW3:
//Lệnh gán y = 0
Thủ tục add_case sẽ
bổ sung vào stab
(switch table) thông
tin của case hiện tại
Case_label = 3
ACT03 genGoto(STACK_ITEM(BreakLabelStack,0),
STACK_ITEM(BreakStack, 0);
GOTO SW2 Phát sinh mã cho lệnh
break.
Sử dụng thông tin lưu
trữ đã lưu trữ trước đó
trong BreakStack và
BreakLabelStack.
Bảng 4.5. Mô tả các hành vi ngữ nghĩa và phát sinh mã ba địa chỉ của lệnh switch
9
2
Chương 4 – Xây dựng chuyến trước của trình biên dịch
93
ACT04 add_case(STACK_ITEM(SwitchStack,0),$2,
++Case_label);
genLabel(L_SWITCH, Case_label);
SW4:
//Lệnh gán y = 1
Bổ sung thông tin
case hiện tại vào stab
Case_label = 4
ACT05 add_default_case(STACK_ITEM(SwitchStack, 0),
++Case_label);
genLabel(L_SWITCH, Case_label);
SW5:
//Lệnh gán y = x
Bổ sung thông tin về
trường hợp default khi
đánh giá biểu thức.
Case_label = 5
ACT06 gen_stab(STACK_POP(SwitchStack));
STACK_POP(BreakStack);
STACK_POP(BreakLabelStack);
GOTO SW2
SW1:
IFTRUE x=1 GOTO SW3
IFTRUE x=2 GOTO SW4
GOTO SW5
SW2:
Phát sinh mã đánh giá
giá trị biểu thức và
nhảy tới trường hợp
thích hợp với đầy đủ
các thông tin đã được
lưu trữ trong stab.
BreakStack : NULL
BreakLabelStack :
NULL
Bảng 4.5. (tiếp theo)
9
3
Chương 4 – Xây dựng chuyến trước của trình biên dịch
94
Chỉ thị ba địa chỉ kết quả sau khi dịch chương trình :
GOTO SW1
SW3:
y = 0
GOTO SW2
SW4:
y = 1
SW5:
y = x
GOTO SW2
SW1:
IFTRUE x=1 GOTO SW3
IFTRUE x=2 GOTO SW4
GOTO SW5
SW2:
Dịch lệnh while:
Trình biên dịch phải tiếp tục thực hiện những câu lệnh nằm trong vòng lặp
while trong khi biểu thức điều kiện còn chính xác (true). Vì vậy, việc đầu tiên
mà ta cần làm là đánh giá biểu thức điều kiện để phát sinh mã ngắt phù hợp.
Ví dụ 4.18: Đoạn mã nguồn sử dụng chỉ thị while:
while (i < n)
i++;
table
cur
1
3
2
4
x
def_label = 5 stab_label = 1
Hình 4.20. Switch table khi đã lưu trữ đầy đủ thông tin
để thực hiện hành vi ACT06
Chương 4 – Xây dựng chuyến trước của trình biên dịch
95
Mục đích của đoạn mã nguồn : biến i sẽ tự động tăng lên 1 đơn vị trong khi
i còn bé hơn n. Như vậy, ta phải phát sinh mã để kiểm tra biểu thức điều kiện
(i<n) . Nếu biểu thức điều kiện là true, lệnh i++ được thực hiện. Còn nếu biểu
thức điều kiện là fasle, chương trình sẽ tiếp tục bằng câu lệnh tiếp theo sau cấu
trúc while. Ta có thể mô hình hóa luồng điều khiển như sau :
Hình 4.21. Phân bố mã cho các câu lệnh while
Luật sinh:
iteration_statement WHILE '(' test ')' statement
{
genGoto(L_TEST, $3);
genLabel(L_NEXT, $3);
}
Mã trung gian được phát sinh đối với Ví dụ 4.18 (với cấu trúc được phân bố
như Hình 4.21):
TST1:
iTemp0 = (i < n)
IFFALSE(iTemp0) GOTO : EXIT1
iTemp1 = i
iTemp2 = i + 1
i = iTemp2
GOTO : TST1
EXIT1:
Chương 4 – Xây dựng chuyến trước của trình biên dịch
96
Dịch lệnh do while:
Thay vì kiểm tra biểu thức điều kiện trước khi thực hiện vòng lặp như
while, do-while làm công việc này ở cuối vòng lặp. Điều này có nghĩa là vòng
lặp do-while sẽ thực hiện ít nhất một lần. Từ đó, ta có mô hình phân bố mã cho
do-while như sau:
Hình 4.22. Phân bố mã cho các câu lệnh do-while
Luật sinh cho trường hợp do-while :
iteration_statement DO
{
static int label;
genLabel(L_DOTOP, ++label);
}
statement WHILE
{
genLabel(L_DOTEST, label);
}
'(' test ')' ';'
4.4.4. Khai báo
Như đã biết, trong một chương trình, thông thường sẽ có 2 phần khai báo:
Khai báo biến (declaration)
Khai báo hàm (function_definition).
Chương 4 – Xây dựng chuyến trước của trình biên dịch
97
Hình 4.23. Cấu trúc khai báo của một chương trình
Tập luật sinh cho cấu trúc khai báo của một chương trình:
file program
| ε
program program external_definition
| external_definition
external_definition function_definition
| declaration
Từ đó, mỗi khai báo trong chương trình đã được đơn giản hóa, xem như là
một external_definition
Hình 4.24. Cây phân tích cú pháp của một chương trình đơn giản
file
program
program external_definition
external_definition function_definition
declaration
Chương 4 – Xây dựng chuyến trước của trình biên dịch
98
Hình 4.25. Sự tương quan giửa khai báo và external_definition
Dịch các khai báo bao gồm các công việc chính:
Ghi nhận thông tin khai báo về kiểu (int, short, long), dấu
(signed, unsigned), thuộc tính lưu trữ (static, extern),...
Thực hiện các hành vi ngữ nghĩa trong hệ thống luật sinh để tiến hành
tạo ra các đối tượng tương ứng với các thông tin trên, sau đó liên kết lại
và thêm vào bảng danh biểu.
Sau đây, ta sẽ tiến hành dịch từng loại khai báo cụ thể.
4.4.4.1. Khai báo biến
Các biến trong chương trình bao gồm 2 loại: biến toàn cục và biến cục
bộ (biến khai báo trong hàm).
Khai báo biến có dạng như sau:
type var_name;
Trong đó:
type: Kiểu dữ liệu của biến (int, long, char, ...), các
thuộc tính lưu trữ (static, extern),...
var_name: Tên biến.
num_ele: Số lượng phần tử nếu là khai báo mảng.
Hệ thống luật sinh để phân tích kiểu, tên biến như trong 2 bảng sau:
Chương 4 – Xây dựng chuyến trước của trình biên dịch
99
Luật sinh Luật ngữ nghĩa (mô tả vắn tắt)
declaration_specifiers
declaration_specifiers_';'
$$ = $1;
declaration_specifiers_ storage_class_specifier $$ = $1;
declaration_specifiers_ storage_class_specifier
declaration_specifiers_
Kết hợp specifier và specifier specifier
declaration_specifiers_ type_specifier $$ = $1;
declaration_specifiers_ type_specifier
declaration_specifiers_
Kết hợp specifier và specifier specifier
storage_class_specifier TYPEDEF Tạo Specifier mới, bật cờ typedef
storage_class_specifier EXTERN Tạo Specifier mới, bật cờ extern
storage_class_specifier STATIC Tạo Specifier mới, bật cờ static
type_specifier type_specifier2 $$ = $1;
type_specifier2 CHAR Tạo Specifier mới, định kiểu CHAR
type_specifier2 SHORT Tạo Specifier mới, định kiểu SHORT
type_specifier2 INT Tạo Specifier mới, định kiểu INT
type_specifier2 LONG Tạo Specifier mới, định kiểu LONG
type_specifier2 SIGNED Tạo Specifier mới, bật cờ b_signed
type_specifier2 UNSIGNED Tạo Specifier mới, bật cờ b_unsigned
type_specifier2 VOID Tạo Specifier mới, định kiểu VOID
type_specifier2 CONST Tạo Specifier mới, bật cờ b_const
type_specifier2 struct_or_union_specifier $$ = $1; Struct sẽ được nói rõ trong phần sau
type_specifier2 TYPE_NAME
TYPE_NAME là kiễu dữ liệu typedef, được nói rõ hơn
trong phần sau.
Bảng 4.6. Hệ thống luật sinh nhận kiểu
(tiếp theo)
9
9
Chương 4 – Xây dựng chuyến trước của trình biên dịch
100
Luật sinh Luật ngữ nghĩa (mô tả vắn tắt)
declaration declaration_specifiers
init_declarator_list ';'
Thêm chuỗi symlink quy định kiểu vào init_declarator_list
init_declarator_list init_declarator $$ = $1;
init_declarator_list init_declarator_list ','
init_declarator
$3->next = $1 ;
$$ = $3;
init_declarator declarator $$ = $1;
declarator declarator3 $$ = $1 ;
declarator pointer declarator3
Thêm declarator về pointer vào chuỗi symlink, truyền lên
cho $$. Pointer sẽ được nói rõ trong phần sau
declarator3 declarator2 $$ = $1 ;
declarator2 identifier $$ = $1;
identifier IDENTIFIER $$ = newSymbol($1, NestLevel);
declarator2 '(' declarator ')' $$ = $2;
declarator2 declarator3 '[' ']'
Tạo declarator dạng mảng (ARRAY) có 0 phần tử, thêm nó
vào chuỗi symlink, truyền lên cho $$
declarator2 declarator3 '[' constant_expr ']'
Tạo declarator dạng mảng (ARRAY) có
constant_expr phần tử, thêm nó vào chuỗi symlink,
truyền lên cho $$
Bảng 4.7. Hệ thống luật nhận tên biến và số lượng phần tử của mảng
1
0
0
Chương 4 – Xây dựng chuyến trước của trình biên dịch
101
Ví dụ 4.19: Khai báo toàn cục như sau:
int x;
Từ cây phân tích cú pháp, ta có sự lan truyền thuộc tính và thực thi các hành vi nhữ
nghĩa như sau:
Sơ đồ tổ chức các đối tượng lưu trữ:
noun = V_INT
noun = V_INT
noun = V_INT
noun = V_INT
name = “x”
name = “x”
name = “x”
name = “x”
name = “x”
name = “x”
init_declarator_list
init_declarator
declarator
declarator3
declarator2
indentifier
IDENTIFIER
indentifier = newSymbol(“x”)
act
act
declaration_specifiers
declaration_specifiers_
type_specifier
type_specifier2
INT
type_specifier2 = newLink(SPECIFIER)
type_specifier2.noun = V_INT;
„;‟
act
act
init_declarator_list.type = declaration_specifiers;
init_declarator_list.etype = declaration_specifiers;
declaration = reverseSyms(init_declarator_list);
file
program
external_definition
declaration act addSymChain (declaration);
Hình 4.26. Sự lan truyền thuộc tính “int” và “x”
Chương 4 – Xây dựng chuyến trước của trình biên dịch
102
4.4.4.2. Khai báo hàm
Khai báo hàm có dạng:
type function_name ()
{
}
Trong đó:
type: Kiểu trả về của khai báo hàm.
arg: Danh sách các tham số.
function_body: Phần khai báo thân hàm.
Để nhận thông tin về khai báo hàm, hệ thống luật sinh sẽ tiến hành
nhận từng phần khai báo. Hệ thống luật sinh chính gồm:
function_definition function_declarator
function_body
function_definition declaration_specifiers
function_declarator function_body
Trong đó:
declaration_specifiers phân tích kiểu và thuộc tính lưu
trữ. Hệ thống luật này đã được mô tả trong Bảng 4.6.
function_declarator phân tích tên hàm, tham số.
function_body phân tích thân hàm..
Hệ thống luật sinh được mô tả trong các bảng sau:
Symbol
Table
symbol
:
“x”
“_x”
NULL
name
rname
type
etype
next
symlink
:
SPECIFIER
NULL
_class
next
select:
noun
b_unsigned
V_INT
0
Hình 4.27. Sơ đồ tổ chức lưu trữ khai báo int x;
Chương 4 – Xây dựng chuyến trước của trình biên dịch
103
Luật sinh Luật ngữ nghĩa (mô tả vắn tắt)
function_declarator
declarator2_function_attributes
$$ = $1;
function_declarator pointer
declarator2_function_attributes
Thêm declarator về pointer vào chuỗi symlink của $2, truyền $2
lên cho $$.
declarator2_function_attributes
function_declarator2
$$ = $1;
declarator2_function_attributes
function_declarator2 function_attribute
Ghi nhận danh sách tham số và thuộc tính của hàm vào $1
function_declarator2 declarator2 '(' ')' Thêm declarator kiểu FUNCTION vào $1
function_declarator2 declarator2 '(' {ACT1}
parameter_type_list ')' {ACT2}
ACT1: level++, block++
ACT2: Thêm declarator kiểu FUNCTION vào $1, level--,
block--, ghi nhận danh sách các tham số của hàm vào $1
function_declarator2 declarator2 '('
identifier_list ')'
Báo lỗi khai báo dạng cũ và tạo symlink kiểu INT cho $1
identifier_list identifier $$ = $1;
identifier_list identifier_list ',' identifier
$3->next = $1;
$$ = $3 ;
identifier IDENTIFIER $$ = newSymbol($1, NestLevel);
parameter_type_list parameter_list $$ = $1;
parameter_list parameter_declaration $$ = $1;
parameter_list parameter_list ','
parameter_declaration
$3->next = $1 ;
$$ = $3 ;
parameter_declaration type_specifier_list
declarator
Thêm kiểu cho declarator
Thêm symbol $2 vào bảng SymbolTab
type_specifier_list type_specifier_list_ $$ = $1;
type_specifier_list_ type_specifier $$ = $1;
type_specifier_list_ type_specifier_list_
type_specifier
Kết hợp specifier và specifier specifier
Bảng 4.8. Hệ thống luật phân tích tên hàm và tham số
1
0
3
Chương 4 – Xây dựng chuyến trước của trình biên dịch
104
Luật sinh Luật ngữ nghĩa (mô tả vắn tắt)
function_body
compound_statement
$$ = $1;
compound_statement
start_block declaration_list
end_block
Ta tập trung vào declaration_list vì đây là
khai báo cục bộ trong hàm.
compound_statement
start_block declaration_list
statement_list end_block
Ta tập trung vào declaration_list vì đây là
khai báo cục bộ trong hàm.
declaration_list
declaration
Kiểm tra $1 có nằm trong bảng danh biểu hay
không, nếu có, báo lỗi trùng tên kiểu và biến.
Ngược lại, thêm $1 vào bảng danh biểu.
declaration_list
declaration_list declaration
Kiểm tra $2 có nằm trong bảng danh biểu hay
không, nếu có, báo lỗi trùng tên kiểu và biến.
Ngược lại, thêm $2 vào bảng danh biểu
Bảng 4.9. Hệ thống luật nhận các khai báo trong hàm
Nhánh luật declaration đã được trình bày trong Bảng 4.7, nhánh luật
statement_list thực hiện phân tích các câu lệnh trong thân hàm, ta sẽ không
đề cập đến trong phần này.
Ví dụ 4.20:
Với khai báo hàm như sau:
int inc(int x)
{
x++;
}
Trong phần thân hàm, không có khai báo biến cục bộ, do đó nhánh luật sinh
function_body ta sẽ không đề cập ở đây.
Từ cây phân tích cú pháp, ta có sự lan truyền thuộc tính và thực thi các hành
vi nhữ nghĩa như trong hình sau:
Chương 4 – Xây dựng chuyến trước của trình biên dịch
105
function_definition
act
declaration_specifiers
declaration_specifiers_
type_specifier
type_specifier2
INT
type_specifier2 = newLink(SPECIFIER)
type_specifier2.noun = V_INT;
noun = V_INT
noun = V_INT
noun = V_INT
noun = V_INT
indentifier = newSymbol(“x”)
act
declarator
declarator3
declarator2
indentifier
IDENTIFIER
name = “x”
name = “x”
name = “x”
name = “x”
type_specifier_list
act
type_specifier
type_specifier2
INT
type_specifier2 = newLink(SPECIFIER)
type_specifier2.noun = V_INT;
type_specifier_list_
noun = V_INT
noun = V_INT
noun = V_INT
noun = V_INT
parameter_type_list „)‟ „(‟ declarator2
indentifier
IDENTIFIER act
indentifier = newSymbol(“inc”)
name = “inc”
name=”inc”
parameter_list
parameter_declaration
function_declarator2
function_declarator
declarator2_function_attributes
function_body act
Phát sinh mã xử lý thân hàm
act
Thực hiên nối symlink $1 vào $2
Thêm danh biểu $2 vào bảng danh biểu
Thêm các biến tham số vào bảng danh biểu
Hình 4.28. Cây phân tích cú pháp và lan truyền thuộc tính cho ví dụ Ví dụ 4.20:
1
0
5
Chương 4 – Xây dựng chuyến trước của trình biên dịch
106
Sơ đồ tổ chức các đối tượng lưu trữ:
Symbol
Table
symbol:
“inc”
“_inc”
NULL
name
rname
type
etype
next
symlink:
DEClARATOR
_class
next
select:
dcl_type
func_Attrs
FUNCTION
symlink
:
SPECIFIER
NULL
_class
next
select:
noun
b_unsigned
v_struct
V_INT
0
NULL
symlink
:
SPECIFIER
NULL
_class
next
select:
noun
b_unsigned
v_struct
V_INT
0
NULL
symbol:
“x”
“_inc_PARM_1”
NULL
name
rname
type
etype
next
symbol:
“x”
“_inc_PARM_1”
NULL
name
rname
type
etype
next
symlink
:
SPECIFIER
NULL
_class
next
select:
noun
b_unsigned
v_struct
V_INT
0
NULL
Hình 4.29. Sơ đồ tổ chức lưu trữ hàm inc trong Ví dụ 4.20:
Chương 4 – Xây dựng chuyến trước của trình biên dịch
107
4.4.4.3. Struct
Cấu trúc khai báo struct:
struct tag_name
{
struct_emement_1;
...
struct_emement_n;
};
Trong đó:
struct: Từ khóa khai báo struct
tag_name: Tên struct.
[struct_emement_1... struct_emement_n]: Khai báo
các thành phần của struct.
Hệ thống luật sinh phân tích phần khai báo struct:
Luật sinh Luật ngữ nghĩa (mô tả vắn tắt)
struct_or_union_specifier
struct_or_union opt_stag {ACT1} '{'
struct_declaration_list '}' {ACT2}
ACT1: Thêm symbol mới quy định về
struct $2 vào bảng StructTab
ACT2: Tạo structdef, ghi nhận các
fields của struct vào $2, tính toàn kích
thước struct, tạo specifier symlink
struct_or_union_specifier
struct_or_union stag
Tìm symbol có tên stag trong bảng
StructTab, nếu có trả về Specifier quy
định kiểu struct tương ứng, ngược lại
báo lỗi và trả về NULL
struct_or_union STRUCT $$ = STRUCT ;
struct_or_union UNION $$ = UNION;
opt_stag stag $$ = $1;
opt_stag ε
Tạo structdef mới với tên tag do
compiler quy định
stag identifier
Tìm trong bản StructTab và trả về
structdef tương ứng. Nếu chưa có
Structdef tương ứng thì tạo mới.
identifier IDENTIFIER $$ = newSymbol($1);
Bảng 4.10. Hệ thống luật phân tích khai báo struct
Chương 4 – Xây dựng chuyến trước của trình biên dịch
108
Bảng 4.10. (tiếp theo)
Nhánh luật declarator đã được trình bày trong Bảng 4.7 sẽ tiến hành phân tích
khai báo thành phần trong struct để trả về các danh biểu tương ứng.
Ví dụ 4.21:
Với khai báo struct:
struct PS
{
int x;
};
Từ bảng luật sinh, chương trình sẽ xây dựng cây phân tích cú pháp cùng các luật
ngữ nghĩa như trong Hình 4.30
struct_declaration_list
struct_declaration
$$ = $1;
struct_declaration_list
struct_declaration_list
struct_declaration
Nối chuỗi các symbol. Truyền thuộc
tính lên trên
struct_declaration
type_specifier_list
struct_declarator_list ';'
Thêm kiểu vào danh sách các khai báo
thành phần struct
struct_declarator_list
struct_declarator
$$ = $1;
struct_declarator_list
struct_declarator_list ','
struct_declarator
$3->next = $1 ;
$$ = $3 ;
struct_declarator declarator $$ = $1;
struct_declarator ε Tạo symbol mới, truyền về cho $$
Chương 4 – Xây dựng chuyến trước của trình biên dịch
109
Hình 4.30. Cây phân tích cú pháp và quá trình lan truyền thuộc tính cho khai báo struct
struct_or_union_specifier
„;‟
„{„ struct_declaration_list „}„
name = “x”
name = “x”
name = “x”
name = “x”
name = “x”
name = “x”
struct_declarator_list
struct_declarator
declarator
declarator3
declarator2
indentifier
IDENTIFIER
indentifier = newSymbol(“x”)
act
type_specifier_list
type_specifier_list_
act
type_specifier
type_specifier2
INT
type_specifier2 = newLink(SPECIFIER)
type_specifier2.noun = V_INT;
noun = V_INT
noun = V_INT
noun = V_INT
noun = V_INT
struct_declaration
opt_stag
stag
indentifier
IDENTIFIER
indentifier = newSymbol(“PS”)
act
act
Tìm „PS‟ trong bảng StructTab. Nếu tồn
tại, trả rề structdef chứa PS, ngược lại
stag = newSymbol(“PS”)
name = “PS”
struct_or_union
STRUCT
type = STRUCT
act
type = STRUCT
act
Thêm structdef stag vào
bảng structTab
act
Thêm các thành phần vào
stag.
1
0
9
Chương 4 – Xây dựng chuyến trước của trình biên dịch
110
Sơ đồ tổ chức lưu trữ:
4.4.4.4. Con trỏ
Nhánh luật pointer là 1 phần trong hệ thống luật khai báo biến. Hệ
thống luật sinh phân tích phần khai báo con trỏ bao gồm:
Luật sinh Luật ngữ nghĩa (mô tả vắn tắt)
pointer unqualified_pointer $$ = $1;
pointer unqualified_pointer
pointer
$$ = $1 ;
$$->next = $2 ;
DCL_TYPE($2) = POINTER;
unqualified_pointer '*'
$$ = newLink(DECLARATOR);
DCL_TYPE($$) = POINTER;
Bảng 4.11. Hệ thống luật dành cho khai báo con trỏ
Ví dụ 4.22: Xây dựng cây cú pháp cho khai báo con trỏ kiểu integer:
int *x;
structdef:
“PS”
2
tag
size
fields
symbol
:
“x”
“_x”
NULL
name
rname
type
etype
next
symlink
:
SPECIFIER
NULL
_class
next
select:
noun
b_unsigned
b_long
V_INT
0
0
Struct
Table
Hình 4.31. Sơ đồ tổ chức lưu trữ cho kiểu dữ liệu struct
Chương 4 – Xây dựng chuyến trước của trình biên dịch
111
Hình 4.32. Cây phân tích cú pháp cho khai báo con trỏ
„*‟
pointer
unqualified_pointer
noun = V_INT
noun = V_INT
noun = V_INT
noun = V_INT
act
declaration_specifiers
declaration_specifiers_
type_specifier
type_specifier2
INT
type_specifier2 = newLink(SPECIFIER)
type_specifier2.noun = V_INT;
init_declarator_list
init_declarator
declarator
file
program
external_definition
declaration act addSymChain (declaration);
„;‟
act
act
init_declarator_list.type = declaration_specifiers;
init_declarator_list.etype = declaration_specifiers;
declaration = reverseSyms(init_declarator_list);
indentifier = newSymbol(“x”)
act
declarator3
declarator2
indentifier
IDENTIFIER
name = “x”
name = “x”
name = “x”
dcl_type = POINTER
act
1
1
1
Chương 4 – Xây dựng chuyến trước của trình biên dịch
112
Sơ đồ lưu trữ:
4.4.4.5. Typedef
Khai báo typedef có dạng:
typedef oldtype newtype;
Trong đó:
oldtype: Kiểu dữ liệu cơ sở (int, short, long) hoặc là struct.
newtype: Tên kiểu dữ liệu mới.
Hệ thống luật sinh phân tích typedef là một phần trong hệ thống luật
phân tích kiểu như trong Bảng 4.6.
Ví dụ 4.23:
Với định nghĩa kiểu liệu integer :
typedef int INT;
Ta sẽ hình thành cây phân tích cú pháp để lan truyền các thông tin
khai báo, phục vụ cho việc cập nhật bảng lưu trữ các thông tin
typedef:
symbol
:
“x”
“_x”
NULL
name
rname
type
etype
next
symlink
:
SPECIFIER
NULL
_class
next
select:
noun
b_unsigned
V_INT
0
symlink:
DECLARATOR _class
next
select:
dcl_type
num_elem
POINTER
0
Symbol
Table
Hình 4.33 Sơ đồ lưu trữ cho khai báo int *x;
Chương 4 – Xây dựng chuyến trước của trình biên dịch
113
Hình 4.34. Cây phân tích cú pháp cho khai báo typedef
init_declarator_list
init_declarator
declarator
declarator3
declarator2
indentifier
IDENTIFIER
indentifier = newSymbol(“x”)
act
name = “x”
name = “x”
name = “x”
name = “x”
name = “x”
name = “x”
storage_class_specifier
b_typedef = 1
declaration_specifiers_
declaration_specifiers
declaration_specifiers_
act
type_specifier
type_specifier2
INT
type_specifier2 = newLink(SPECIFIER)
type_specifier2.noun = V_INT;
noun = V_INT
noun = V_INT
noun = V_INT
TYPEDEF act
storage_class_specifier.b_typedef = 1;
file
program
external_definition
declaration act addSymChain (declaration);
„;‟
act
act
init_declarator_list.type = declaration_specifiers;
init_declarator_list.etype = declaration_specifiers;
declaration = reverseSyms(init_declarator_list);
1
1
3
Chương 4 – Xây dựng chuyến trước của trình biên dịch
114
Tổ chức lưu trữ
Khi khai báo typedef, trình biên dịch sẽ tiến hành tạo ra một danh biểu
tương ứng với kiểu dữ liệu mới và thêm vào bảng danh biểu khai báo biến
(symbol table). Đồng thời cũng tiến hành thêm vào bảng Typedef để khi
trình phân tích từ vựng cần kiểm tra xem lexeme có phải là một kiểu dữ liệu
hay không.
Symbol
Table
symbol:
“INT”
“”
NULL
name
rname
type
etype
next
symlink:
SPECIFIER _class
next
select:
noun
b_typedef
V_INT
1
Typedef
Table
symbol:
“INT”
“”
NULL
name
rname
type
etype
next
symlink:
SPECIFIER _class
next
select:
noun
b_typedef
V_INT
1
Hình 4.35. Tổ chức lưu trữ typedef
Chương 5 – Tỗng kết
115
CHƢƠNG 5: TỔNG KẾT
5.1. KẾT QUẢ
Xây dựng một trình biên dịch hoàn chỉnh là một công việc đòi hỏi có nhiều đầu
tư về thời gian, nhân lực, cũng như một khối lượng kiến thức lớn. Do đó, khuôn khổ
khóa luận tập trung chủ yếu vào việc thu thập và tích lũy các thông tin từ chương trình
nguồn để tạo ra một dạng biễu diễn trung gian (mã 3-địa chỉ) tương đương. Với định
hướng đó, nhóm sinh viên đã phần nào hoàn thành việc :
- Nghiên cứu các kỹ thuật xây dựng trình biên dịch, đặc biệt là chuyến trước
của trình biên dịch.
- Khảo sát 2 công cụ hỗ trợ đắc lực cho việc phát sinh bộ phân tích từ vựng
(FLEX) và bộ phân tích cú pháp (BISON).
- Từ những kiến thức nghiên cứu được, nhóm sinh viên đã xây dựng thử
nghiệm thành công chuyến trước của trình biên dịch cho ngôn ngữ ANSI C
giản lược và hướng tới những họ vi xử lý hạn hẹp về tài nguyên. Với kết quả
là bộ mã 3-địa chỉ, chương trình đã thành công trong việc phân tích mã
nguồn một cách chi tiết, đầy đủ và chân thật nhất.
- Giải quyết các bài toán nảy sinh trong thực tế, vốn không được đề cập trong
tài liệu.
5.2. HẠN CHẾ
Mặc dù đã cố gắng để có thể tích lũy một khối lượng lớn thông tin từ chương
trình nguồn, chuyến trước của trình biên dịch mà nhóm sinh viên xây dựng vẫn chưa
đáp ứng được một số cấu trúc của chương trình C chuẩn:
- Chưa giải quyết được cấu trúc enum, union.
- Chưa hỗ trợ dấu chấm động.
- Chưa xử lý lỗi một cách chi tiết.
5.3. HƢỚNG PHÁT TRIỂN
- Giải quyết những hạn chế một cách hoàn chỉnh.
Chương 5 – Tỗng kết
116
- Tiếp tục phát triển chuyến trước để có thể thu thập nhiều thông tin hơn, hỗ
trợ đắc lực cho việc xử lý lỗi cũng như sửa lỗi.
- Từ bộ mã trung gian, ta hoàn toàn có cơ sở để tiếp tục nghiên cứu và phát
sinh ra mã đích (mã hợp ngữ) cho một hệ thống xác định.
Phụ lục
117
PHỤ LỤC
PHỤ LỤC 1: Bảng xác định độ ƣu tiên của các toán tử.
Độ ưu tiên Toán tử Mô tả Thứ tự kết hợp
1 ++ --
()
[]
.
->
Dạng hậu tố (VD : a++, b--)
Lời gọi hàm, thủ tục
Truy xuất mảng
Truy xuất cấu trúc thành phần
Truy xuất cấu trúc thành phần qua con trỏ
Trái sang phải
2 ++ --
+ -
! ~
(type)
*
&
Dạng tiền tố (VD : ++a, --b)
Toán tử đơn (VD : -a, +b)
Toán tử NOT logic và NOT bit.
Ép kiểu dữ liệu (casting)
Lấy giá trị tại địa chỉ (dereference)
Lấy địa chỉ
Phải sang trái
3 * / % Toán tử nhân, chia nguyên, chia dư Trái sang phải
4 + - Toán tử cộng, trừ
5 > Toán tử dịch trái, dịch phải
6 < <=
> >=
Toán tử so sánh lớn (nhỏ)
7 == != Toán tử so sánh bằng (không bằng)
8 & Toán tử and bit
9 ^ Toán tử xor bit
10 | Toán tử or bit
11 && Toán tử logic and
12 || Toán tử logic or
13 c?t:f Biểu thức điều kiện Phải sang trái
14 =
+= -=
*= /=
%=
<<=
>>=
&= ^=
|=
Toán tử gán
Gán bằng tổng/hiệu
Gán bằng tích/thương/phần dư
Gán bằng phép toán dịch trái, dịch phải
Gán bằng phép and, xor, or bit.
Phụ lục
118
PHỤ LỤC 2: Dịch chƣơng trình mẫu.
int a1;
unsigned int a2;
char a3;
unsigned char a4;
long a5;
unsigned long a6;
int a7[5];
int a8[10];
int a9[5][5][5][5][5];
char a10[5][5][5];
typedef struct tagLienPhanSo
{
int ts;
int msn;
struct {
int dum1,dum2,dum3;
struct{
long dum4,dum5;
}dumstruct;
}dumdumstruct;
struct tagLienPhanSo *mslps;
} LienPhanSo;
typedef LienPhanSo LPS;
int Fibonacci(int n)
{
if (n==0 || n==1)
return 1;
return Fibonacci(n-1) + Fibonacci(n-2);
}
void TestScope()
{
char *add;
{
int add;
}
{
int add;
}
{
add[3] = 1;
}
}
Phụ lục
119
int IsJustAPrototype(int dummy);
int GetValue(int *p)
{
IsJustAPrototype((int)('c'));
return p?*p:0;
}
char Calculation(int a1,long a2, char a3, short a4, unsigned int a5,
unsigned long a6, unsigned char a7, unsigned
short a8)
{
unsigned long sum;
int a9, a10;
{
int a9, a10;
a10 = (a1 + a2)>>a3;
a9 = (a10>0) && (a10<100);
sum += a9;
}
{
a10 = 5;
}
sum -= a4 + (a5++)*(--a6)/a7;
return sum;
}
void TestArrayPointer()
{
int *p1, *p2, *p3;
int a1[10], a2[10][10], a3[5];
p3 = p1 - p2++;
a1[3] = a2[1][1+a3[5]];
a8[1] = 8;
a9[0][1][0][1][0] = 9;
a5 = a8[0] + a9[0][1][0][1][0];
}
void TestStruct()
{
LPS a;
LienPhanSo b;
struct tagLienPhanSo c;
a.ts = b.msn;
b.msn = c.mslps->ts;
a.mslps->mslps->mslps->ts = 10;
}
Phụ lục
120
void TestSwitch()
{
int x;
switch(x)
{
case 1:
x = 2;
case 2:
x = 3;
break;
default:
x = 0;
}
}
void main(char **argv, int argc)
{
int i, j;
int n[100];
for (i = 0; i<100;i++)
for (j = i+1; j<100;j++)
if ((n[i] < n[j]) && (GetValue(0) == 0))
{
n[(i+j) % 100] = 'a';
}
}
Mã 3-địa chỉ :
BEGIN FUNCTION : Fibonacci
n = RECEIVE(Fibonacci)
TST1:
iTemp0 = (n == 0)
IFTRUE(iTemp0)
GOTO : T1
iTemp1 = (n == 1)
IFTRUE(iTemp1)
GOTO : T1
F1:
iTemp2 = 0
GOTO : E1
T1:
iTemp2 = 1
Phụ lục
121
E1:
IFFALSE(iTemp2)
GOTO : EXIT1
RETURN 1
EXIT1:
iTemp3 = CAST(1)
iTemp4 = n - iTemp3
SEND : iTemp4
iTemp5 = CALL(Fibonacci)
iTemp6 = CAST(2)
iTemp7 = n - iTemp6
SEND : iTemp7
iTemp8 = CALL(Fibonacci)
iTemp9 = iTemp5 + iTemp8
RETURN iTemp9
END FUNCTION
BEGIN FUNCTION : TestScope
iTemp10 = add + 3
iTemp10 = 1
END FUNCTION
BEGIN FUNCTION : GetValue
p = RECEIVE(GetValue)
iTemp11 = CAST(99)
SEND : iTemp11
iTemp12 = CALL(IsJustAPrototype)
IFFALSE(p)
GOTO : QF1
iTemp13 = *(p)
GOTO : QE1
QF1:
iTemp13 = 0
QE1:
RETURN iTemp13
END FUNCTION
Phụ lục
122
BEGIN FUNCTION : Calculation
a1 = RECEIVE(Calculation)
a2 = RECEIVE(Calculation)
a3 = RECEIVE(Calculation)
a4 = RECEIVE(Calculation)
a5 = RECEIVE(Calculation)
a6 = RECEIVE(Calculation)
a7 = RECEIVE(Calculation)
a8 = RECEIVE(Calculation)
iTemp14 = CAST(a1)
iTemp15 = iTemp14 + a2
iTemp16 = iTemp15 >> a3
a10 = iTemp16
iTemp17 = (a10 > 0)
IFFALSE(iTemp17)
GOTO : F2
iTemp18 = (a10 < 100)
IFFALSE(iTemp18)
GOTO : F2
GOTO : T2
F2:
iTemp19 = 0
GOTO : E2
T2:
iTemp19 = 1
E2:
a9 = iTemp19
iTemp20 = CAST(a9)
iTemp21 = sum + iTemp20
sum = iTemp21
a10 = 5
iTemp22 = a5
iTemp23 = a5 + 1
a5 = iTemp23
iTemp24 = a6 - 1
a6 = iTemp24
iTemp25 = CAST(iTemp22)
iTemp26 = iTemp25 * a6
Phụ lục
123
iTemp27 = CAST(a7)
iTemp28 = iTemp26 / iTemp27
iTemp29 = CAST(a4)
iTemp30 = iTemp29 + iTemp28
iTemp31 = sum - iTemp30
sum = iTemp31
RETURN sum
END FUNCTION
BEGIN FUNCTION : TestArrayPointer
iTemp32 = p2
iTemp33 = p2 + 2
p2 = iTemp33
iTemp34 = p1 - iTemp32
iTemp35 = CAST(2)
iTemp36 = iTemp34 / iTemp35
p3 = iTemp36
iTemp37 = &(a1)
iTemp38 = iTemp37 + 6
iTemp39 = &(a2)
iTemp40 = iTemp39 + 20
iTemp41 = &(a3)
iTemp42 = iTemp41 + 10
iTemp43 = *(iTemp42)
iTemp44 = CAST(1)
iTemp45 = iTemp44 + iTemp43
iTemp46 = CAST(2)
iTemp47 = iTemp46 * iTemp45
iTemp48 = iTemp40 + iTemp47
iTemp49 = *(iTemp38)
iTemp50 = *(iTemp48)
iTemp49 = iTemp50
iTemp51 = &(a8)
iTemp52 = iTemp51 + 2
iTemp53 = *(iTemp52)
iTemp53 = 8
iTemp54 = &(a9)
iTemp55 = iTemp54 + 250
Phụ lục
124
iTemp56 = iTemp55 + 10
iTemp57 = *(iTemp56)
iTemp57 = 9
iTemp58 = &(a8)
iTemp59 = &(a9)
iTemp60 = iTemp59 + 250
iTemp61 = iTemp60 + 10
iTemp62 = *(iTemp58)
iTemp63 = *(iTemp61)
iTemp64 = iTemp62 + iTemp63
a5 = iTemp64
END FUNCTION
BEGIN FUNCTION : TestStruct
iTemp65 = &(a)
iTemp66 = iTemp65 + 0
iTemp67 = &(b)
iTemp68 = iTemp67 + 2
iTemp69 = *(iTemp66)
iTemp70 = *(iTemp68)
iTemp69 = iTemp70
iTemp71 = &(b)
iTemp72 = iTemp71 + 2
iTemp73 = &(c)
iTemp74 = iTemp73 + 18
iTemp75 = iTemp74 + 0
iTemp76 = *(iTemp72)
iTemp77 = *(iTemp75)
iTemp76 = iTemp77
iTemp78 = &(a)
iTemp79 = iTemp78 + 18
iTemp80 = iTemp79 + 18
iTemp81 = iTemp80 + 18
iTemp82 = iTemp81 + 0
iTemp83 = *(iTemp82)
iTemp83 = 10
END FUNCTION
Phụ lục
125
BEGIN FUNCTION : TestSwitch
GOTO : SW1
SW3:
x = 2
SW4:
x = 3
GOTO : SW2
SW5:
x = 0
GOTO : SW2
SW1:
iTemp84 = (x == 1)
IFTRUE(iTemp84)
GOTO : SW3
iTemp85 = (x == 2)
IFTRUE(iTemp85)
GOTO : SW4
GOTO : SW5
SW2:
END FUNCTION
BEGIN FUNCTION : main
argv = RECEIVE(main)
argc = RECEIVE(main)
i = 0
TST2:
iTemp86 = (i < 100)
IFFALSE(iTemp86)
GOTO : EXIT2
GOTO : BDY2
INC2:
iTemp87 = i
iTemp88 = i + 1
i = iTemp88
GOTO : TST2
BDY2:
iTemp89 = CAST(1)
iTemp90 = i + iTemp89
Phụ lục
126
j = iTemp90
TST3:
iTemp91 = (j < 100)
IFFALSE(iTemp91)
GOTO : EXIT3
GOTO : BDY3
INC3:
iTemp92 = j
iTemp93 = j + 1
j = iTemp93
GOTO : TST3
BDY3:
TST4:
iTemp94 = &(n)
iTemp95 = CAST(2)
iTemp96 = iTemp95 * i
iTemp97 = iTemp94 + iTemp96
iTemp98 = &(n)
iTemp99 = CAST(2)
iTemp100 = iTemp99 * j
iTemp101 = iTemp98 + iTemp100
iTemp102 = *(iTemp97)
iTemp103 = *(iTemp101)
iTemp104 = (iTemp102 < iTemp103)
IFFALSE(iTemp104)
GOTO : F3
SEND : 0
iTemp105 = CALL(GetValue)
iTemp106 = (iTemp105 == 0)
IFFALSE(iTemp106)
GOTO : F3
GOTO : T3
F3:
iTemp107 = 0
GOTO : E3
T3:
iTemp107 = 1
E3:
IFFALSE(iTemp107)
Phụ lục
127
GOTO : EXIT4
iTemp108 = &(n)
iTemp109 = i + j
iTemp110 = CAST(100)
iTemp111 = iTemp109 MOD iTemp110
iTemp112 = CAST(2)
iTemp113 = iTemp112 * iTemp111
iTemp114 = iTemp108 + iTemp113
iTemp115 = *(iTemp114)
iTemp115 = 97
EXIT4:
GOTO : INC3
EXIT3:
GOTO : INC2
EXIT2:
END FUNCTION
Thông tin bảng danh biểu:
Symbol table
Hash key 18
- Sym 00591F20, name 'TestSwitch', level 0 block 0
Hash key 29
- Sym 0055CF10, name 'GetValue', level 0 block 0
Hash key 37
- Sym 00583180, name 'TestStruct', level 0 block 0
Hash key 41
- Sym 0055C808, name 'add', level 2 block 3, local of
'TestScope'
- Sym 0055C6A0, name 'add', level 2 block 2, local of
'TestScope'
- Sym 0055C538, name 'add', level 1 block 1, local of
'TestScope'
Hash key 44
- Sym 0055CDA8, name 'dummy', level 1 block 1, param of
function 'IsJustAPrototype'
Hash key 85
- Sym 00563FC8, name 'sum', level 1 block 1, local of
'Calculation'
Phụ lục
128
Hash key 97
- Sym 005832E8, name 'a', level 1 block 1, local of
'TestStruct'
Hash key 98
- Sym 00583450, name 'b', level 1 block 1, local of
'TestStruct'
Hash key 99
- Sym 00583888, name 'c', level 1 block 1, local of
'TestStruct'
Hash key 105
- Sym 00595760, name 'i', level 1 block 1, local of 'main'
Hash key 106
- Sym 005958C8, name 'j', level 1 block 1, local of 'main'
Hash key 110
- Sym 00595A30, name 'n', level 1 block 1, local of 'main'
- Sym 00557E30, name 'n', level 1 block 1, param of function
'Fibonacci'
Hash key 111
- Sym 00563320, name 'Calculation', level 0 block 0
Hash key 112
- Sym 005623A8, name 'p', level 1 block 1, param of function
'GetValue'
Hash key 120
- Sym 00592088, name 'x', level 1 block 1, local of
'TestSwitch'
Hash key 121
- Sym 0055CC40, name 'IsJustAPrototype', level 0 block 0
Hash key 126
- Sym 00557CC8, name 'Fibonacci', level 0 block 0
Hash key 128
- Sym 00576BA8, name 'TestArrayPointer', level 0 block 0
Hash key 146
- Sym 00577148, name 'a1', level 1 block 1, local of
'TestArrayPointer'
- Sym 00563488, name 'a1', level 1 block 1, param of function
'Calculation'
- Sym 00208158, name 'a1', level 0 block 0
Hash key 147
- Sym 005772B0, name 'a2', level 1 block 1, local of
'TestArrayPointer'
- Sym 005635F0, name 'a2', level 1 block 1, param of function
'Calculation'
- Sym 002086E8, name 'a2', level 0 block 0
Phụ lục
129
Hash key 148
- Sym 00577418, name 'a3', level 1 block 1, local of
'TestArrayPointer'
- Sym 00563758, name 'a3', level 1 block 1, param of function
'Calculation'
- Sym 00208C78, name 'a3', level 0 block 0
Hash key 149
- Sym 005638C0, name 'a4', level 1 block 1, param of function
'Calculation'
- Sym 002092A0, name 'a4', level 0 block 0
Hash key 150
- Sym 00563A28, name 'a5', level 1 block 1, param of function
'Calculation'
- Sym 00209868, name 'a5', level 0 block 0
Hash key 151
- Sym 00563B90, name 'a6', level 1 block 1, param of function
'Calculation'
- Sym 005517F8, name 'a6', level 0 block 0
Hash key 152
- Sym 00563CF8, name 'a7', level 1 block 1, param of function
'Calculation'
- Sym 00551CC8, name 'a7', level 0 block 0
Hash key 153
- Sym 00563E60, name 'a8', level 1 block 1, param of function
'Calculation'
- Sym 0020E330, name 'a8', level 0 block 0
Hash key 154
- Sym 0056BD10, name 'a9', level 2 block 2, local of
'Calculation'
- Sym 00564130, name 'a9', level 1 block 1, local of
'Calculation'
- Sym 0055C3D0, name 'TestScope', level 0 block 0
- Sym 0020E908, name 'a9', level 0 block 0
Hash key 157
- Sym 005955F8, name 'argc', level 1 block 1, param of
function 'main'
Hash key 161
- Sym 00576D10, name 'p1', level 1 block 1, local of
'TestArrayPointer'
Hash key 162
- Sym 00576E78, name 'p2', level 1 block 1, local of
'TestArrayPointer'
Hash key 163
Phụ lục
130
- Sym 00576FE0, name 'p3', level 1 block 1, local of
'TestArrayPointer'
Hash key 165
- Sym 00595328, name 'main', level 0 block 0
Hash key 176
- Sym 00595490, name 'argv', level 1 block 1, param of
function 'main'
Hash key 194
- Sym 0056BE78, name 'a10', level 2 block 2, local of
'Calculation'
- Sym 0056BBA8, name 'a10', level 1 block 1, local of
'Calculation'
- Sym 00554220, name 'a10', level 0 block 0
Hash key 209
- Sym 005579F8, name 'LienPhanSo', level 0 block 0
Hash key 239
- Sym 00557B60, name 'LPS', level 0 block 0
Typedef table
Hash key 209
- Sym 005579F8, name 'LienPhanSo', level 0 block 0
Hash key 239
- Sym 00557B60, name 'LPS', level 0 block 0
StructTab table
Hash key 13
- Sym 005565F8, name 'tagLienPhanSo', level 0 block 0
Hash key 64
- Sym 005569C8, name '__00020000', level 2 block 0
Hash key 66
- Sym 00556F00, name '__00030001', level 3 block 0
Quản lý bộ nhớ :
Segment: data
Item:
- 'a1' type: int
- 'a2' type: unsigned int
- 'a3' type: char
- 'a4' type: unsigned char
- 'a5' type: long
Phụ lục
131
- 'a6' type: unsigned long
- 'a7' type: int [5]
- 'a8' type: int [10]
- 'a9' type: int [5] [5] [5] [5] [5]
- 'a10' type: char [5] [5] [5]
- 'Fibonacci' type: int function
- 'TestScope' type: void function
- 'IsJustAPrototype' type: int function
- 'GetValue' type: int function
- 'Calculation' type: char function
- 'TestArrayPointer' type: void function
- 'TestStruct' type: void function
- 'TestSwitch' type: void function
- 'main' type: void function
Segment: code
Item:
- 'Fibonacci' type: int function
- 'TestScope' type: void function
- 'IsJustAPrototype' type: int function
- 'GetValue' type: int function
- 'Calculation' type: char function
- 'TestArrayPointer' type: void function
- 'TestStruct' type: void function
- 'TestSwitch' type: void function
- 'main' type: void function
Segment: stack
Item:
- 'n', type: int , on func 'Fibonacci', stack offset 0
- 'add', type: char * , on func 'TestScope', stack offset 0
- 'add', type: int , on func 'TestScope', stack offset 2
- 'add', type: int , on func 'TestScope', stack offset 4
- 'p', type: int * , on func 'GetValue', stack offset 0
- 'a1', type: int , on func 'Calculation', stack offset 0
- 'a2', type: long , on func 'Calculation', stack offset 2
- 'a3', type: char , on func 'Calculation', stack offset 6
- 'a4', type: int , on func 'Calculation', stack offset 7
- 'a5', type: unsigned int , on func 'Calculation', stack
offset 9
- 'a6', type: unsigned long , on func 'Calculation', stack
offset 11
Phụ lục
132
- 'a7', type: unsigned char , on func 'Calculation', stack
offset 15
- 'a8', type: unsigned int , on func 'Calculation', stack
offset 16
- 'sum', type: unsigned long , on func 'Calculation', stack
offset 18
- 'a9', type: int , on func 'Calculation', stack offset 22
- 'a10', type: int , on func 'Calculation', stack offset 24
- 'a9', type: int , on func 'Calculation', stack offset 26
- 'a10', type: int , on func 'Calculation', stack offset 28
- 'p1', type: int * , on func 'TestArrayPointer', stack
offset 0
- 'p2', type: int * , on func 'TestArrayPointer', stack
offset 2
- 'p3', type: int * , on func 'TestArrayPointer', stack
offset 4
- 'a1', type: int [10] , on func 'TestArrayPointer', stack
offset 6
- 'a2', type: int [10] [10] , on func 'TestArrayPointer',
stack offset 26
- 'a3', type: int [5] , on func 'TestArrayPointer', stack
offset 226
- 'a', type: struct , on func 'TestStruct', stack offset 0
- 'b', type: struct , on func 'TestStruct', stack offset 20
- 'c', type: struct , on func 'TestStruct', stack offset 40
- 'x', type: int , on func 'TestSwitch', stack offset 0
- 'argv', type: char * * , on func 'main', stack offset 0
- 'argc', type: int , on func 'main', stack offset 2
- 'i', type: int , on func 'main', stack offset 4
- 'j', type: int , on func 'main', stack offset 6
- 'n', type: int [100] , on func 'main', stack offset 8
Tham khảo
133
THAM KHẢO
[1] Alfred. V. Aho, Monica S. Lam, Ravi Sethi, Jeffrey D. Ullman, Compilers:
Principles, Techniques and Tools, 2
nd
ed., Addison Wesley, 2007.
[2] Alfred. V. Aho, Ravi Sethi, Jeffrey D. Ullman, Compilers: Principles,
Techniques and Tools, 1st ed., Addison Wesley, 1986.
[3] Allen I.Hollub, Compiler Design In C, Addison Wesley, 1990.
[4] John E. Hopcroft, Rajeev Motwani, Jeffrey D. Ullman, Introduction to
Automata Theory, Languages, and Computation, 2nd ed., Addison Wesley,
2001.
[5] John R. Levine, Flex & Bison, 1st ed., O‟Reilly Media, Inc., 2009.
[6] Niklaus Wirth, Compiler Construction, Addision Wesley, 1996.
[7] Charles Donnelly, Richard Stallman, Bison – The Yacc-compatible Parser
Generator, Free Software Foundation, 2009.
[8] Muchnick, Steven, Advanced Compiler Design and Implementation, Morgan
Kaufmann Publishers, 1997
[9]
Các file đính kèm theo tài liệu này:
- mkdgfklfd_6993.pdf