Tìm hiểu Chương trình dịch, bộ
công cụ Flex & Bison
Giảng viên hướng dẫn: TS. Phạm Đăng Hải
Học viên thực hiện:
1
2
Lớp:
3
NỘI DUNG TÌM HIỂU
TỔNG QUAN VỀ CHƯƠNG TRÌNH DỊCH
THIẾT KẾ CHƯƠNG TRÌNH DỊCH
BỘ CÔNG CỤ FLEX VÀ BISON
DEMO
Là một chương trình máy tính làm công việc dịch
một chuỗi các câu lệnh được viết bằng một ngôn
ngữ lập trình (mã nguồn), thành một chương trình
tương đương nhưng ở dưới dạng một ngôn ngữ mới
(gọi là ngôn ngữ đích hay mã đích) và thường là
ngôn ngữ ở cấp thấp hơn, như ngôn ngữ máy
Cấu trúc của trình biên dịch
Quá trình thực hiện
1. Giai đoạn tiền xử lý:
o Phân tích từ vựng (Lexical Analysis), phân tích cú pháp (Syntax
Analysis), phân tích ngữ nghĩa
o Tiền xử lí (Pre-processing): nhận mã nguồn và xoá bỏ các chú thích
2. Giai đoạn dịch:
o Sinh mã: chuyển mã nguồn sang dạng mã Assemly, sau đó dịch sang
mã máy
o Tối ưu mã
3. Giai đoạn liên kết (link):
o Trong giai đoạn này mã máy của một chương trình dịch từ nhiều nguồn
khác nhau được liên kết lại với nhau để tạo thành chương trình đích duy
nhất (executable hay .exe)
Quá trình dịch ngôn ngữ C
Phân tích từ vựng
Là công việc đọc chương trình nguồn từ trái sang phải
(hay được gọi là quá trình quét nguyên liệu) để tách ra
thành các thẻ (token).
Phân tích từ vựng
Token
Mô tả
CONSTANT
Các hằng số với các kiểu dữ liệu (số nguyên, số thực,…)
STRING_VALUE
Chuỗi hằng (ví dụ “hello world”)
IDENTIFIER
Các danh biểu trong chương trình, bao gồm tên biến, tên hàm (bắt đầu là chữ cái, theo
sau là chữ hoặc số)
IF
Lệnh if
ELSE
Lệnh else
WHILE
Lệnh while
RIGHT_OP
Toán tử shift right
LEFT_OP
Toán tử shift left
INC_OP
Toán tử ++
Bảng: Một số token của ngôn ngữ C
Phân tích cú pháp
Trình phân tích cú pháp (parser) nhận chuỗi các token từ
trình phân tích từ vựng và xác định rằng chuỗi này có
hợp lệ hay không bằng cách tạo ra cây phân tích cú pháp
từ văn phạm của ngôn ngữ nguồn.
ngôn ngữ
nguồn
cây phân
tích cú pháp
token
Trình phân tích
từ vựng
Trình phân tích
cú pháp
yêu cầu
token
Bảng danh biểu
Phần còn lại của
chuyến trước
biểu diễn
trung gian
Phân tích cú pháp
Phân tích cú pháp từ trên xuống (Top-Down Parsing)
hay phân tích cú pháp dự đoán (Predictive Parser): Bắt
đầu từ nút gốc
Phân tích cú pháp từ dưới lên (Bottom-Up Parsing): Bắt
đầu từ chuỗi token và cố gắng tìm kiếm luật sinh thích
hợp để có thể dẫn về ký tự bắt đầu của văn phạm
Tổ chức bảng ký hiệu
Bảng ký hiệu là một cấu trúc dữ liệu mà mỗi phần tử là
một mẫu tin dùng để lưu trữ một token được bộ phân
tích từ vựng nhận biết và các thông tin của token đó
Các thủ tục trên bảng ký hiệu chủ yếu liên quan đến việc
lưu trữ và truy xuất các trị từ vựng. Khi một trị từ vựng
được lưu trữ thì token kết hợp với nó cũng được lưu. Hai
thao tác sau được thực hiện trên bảng ký hiệu.
o
o
Insert (s, t): Trả về chỉ mục của một ô mới cho chuỗi s, token t.
Lookup (s): Trả về chỉ mục của ô cho chuỗi s hoặc 0 nếu chuỗi s
không tồn tại.
Tổ chức bảng ký hiệu
Thông thường, một bảng ký hiệu gồm hai mảng :
1. Mảng lexemes (trị từ vựng) dùng để lưu trữ các chuỗi ký tự tạo ra
một danh biểu, các chuỗi này ngăn cách nhau bởi các ký tự EOS (end of - string).
2. Mảng symtable với mỗi phần tử là một mẩu tin (record) bao gồm hai
trường, trường con trỏ lexptr trỏ tới đầu trị từ vựng và trường token.
Bảng ký hiệu và mảng để lưu các chuỗi
BISON: Bộ phát sinh ra trình phân tích cú pháp
(Bắt nguồn từ Yacc (Yet Another Compiler
Compiler), Stephen C. Johnson, Bell Lab, 1970)
FLEX: Bộ phát sinh trình phân tích từ vựng – để
hỗ trợ Bison trong việc xác định các token từ chuỗi
nhập (Bắt nguồn từ lex, Mike Lesk và Eric
Schmidt).
FLEX: Bộ phát sinh trình phân
tích từ vựng – để hỗ trợ Bison
trong việc xác định các token từ
chuỗi nhập (Bắt nguồn từ lex,
Mike Lesk và Eric Schmidt).
BISON: Bộ phát sinh ra trình
phân tích cú pháp (Bắt nguồn
từ Yacc (Yet Another Compiler
Compiler), Stephen C. Johnson,
Bell Lab, 1970)
FLEX
Là 1 open-source tool cho Bộ phát sinh từ vựng
Flex đọc user-specified input files
• Nếu không có file => Đọc standard file
Flex INPUT file:
• Là một mô tả của bộ scanner sinh mã
• Miêu tả là các cặp Biểu thức Regular Expressions và C
Code gọi là RULES
FLEX
Flex Source
File
(sample.l)
Flex
Compiler
(Flex)
Lexical Analyzer
Code (lex.yy.c)
C Compiler
Input Text
File
Lexical Analyzer
executable
Output: Tokens
Parser
FLEX & BISON
.lex
Flex file format
Definitions >> rules >> user-defined routines
%{
Declaration Section
%}
%%
Rules Section
%%
User routines Section
Flex Source
Rules
o Format
o <regular-expression>
{<actions>}
o When a Lexical Analyzer is run (or the scanning routine yylex() is
called) it analyzes the input for the occurrences of text patterns that
match the regular expressions. When ever it finds one it executes the
corresponding action.
o Flex stores the matched text in a global string variable called yytext.
[0-9]+
{ printf(“An integer %s \n”, yytext); }
[a-z][a-z0-9]* { printf(“An identifier %s \n”,
if | then | begin | end | function { printf(“A
yytext);}
Keyword %s \n”, yytext); }
Ví dụ Flex: vidu1.l
Nhiệm vụ:
Nhận input đầu vào,
scan các ký tự cho đến
khi nhận được ký tự kết
thúc input (\r), trả về
các token tương ứng
EVEN
ODD
Vidu1.l
%{ /* Phần khai báo (định nghĩa, khai báo biến,
prototype)*/
#include <stdlib.h>
#include "y.tab.h"
%}
%% /*Phần luật*/
[0-9]*[02468]"\n"
{ return EVEN; }
[0-9]*[13579]"\n"
{ return ODD; }
%%
int main(void){ /**/
yyparse();
return 0;
}
BISON
Là bộ phát sinh ra trình phân tích cú pháp có nhiệm vụ
chuyển đổi một văn bản chưa có cú pháp thành một
deterministic [LR or generalized LR (GLR)] parser.
Có thể phát triển trên nhiều ngôn ngữ lập trinh khác
nhau.
Tương thích với YACC
Dựa trên C\C++ và chạy được trên Java
BISON
Tương tự Flex; Đầu vào: tệp bao gồm các đặc tả của một ngôn ngữ *.y
-> biên dịch ra bộ phân tích cú pháp mã C
Cấu trúc của tệp đặc tả ngôn ngữ gồm ba phần:
o
o
o
Phần khai báo
Phần luật dịch
Các thủ tục
BISON
Bas.y (Parser Input):
o Y.tab.h (Parser Output): là file header, định nghĩa các token
như NUM, OPA, etc., và biến yylval để truyền sang bison
code các giá trị của tokens
o Y.tab.c (Parser Output): chứa mã C\C++ cho bộ phân tích
(là function có tên yyparse())
Bas.l (Lexica Analyzer Input):
o Sử dụng các định nghĩa trong (Y.tab.h) để thực thi yylex()
function và truyền các thông tin trả lại.
o Lex.yy.c (Lexica Analyzer Output): generated by FLEX
that contains, among other things, the definition of the
yylex() function
Ví dụ BISON: Vidu1.y
Vidu1.y
/* Phần khai báo: Chứa các token được định nghĩa */
%token EVEN ODD
/* Phần mô tả tập luật sinh */
%%
input:
EVEN { printf("EVEN NUMBER\n"); return 0; }
|ODD { printf("ODD NUMBER\n"); return 0; }
IV. DEMO (1/7)
Ví dụ 1:
Xin chào và
tạm biệt
File Flex:
Hello.l
Hello.l
%{
#include "y.tab.h"
int yyerror(char *errormsg);
%}
%%
("xin chao"|"hi"|"hello")"\n"
{ return HI; }
("tam biet"|"bye"|"goodbye"|"bye bye")"\n" { return BYE; }
.
{ yyerror("Unknown char"); }
%%
int main(void){
yyparse();
return 0;
}
int yywrap(void){
return 0;
}
int yyerror(char *errormsg){
fprintf(stderr, "%s\n", errormsg);
exit(1);
}