1. Trang chủ
  2. » Thể loại khác

Giáo trình biên dịch hữu ích và hay nhất

157 562 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 157
Dung lượng 1,62 MB

Nội dung

Ebook miễn phí xin giới thiệu chương trình dịch (compiler) là một chương trình làm nhiệm vụ đọc một chương trình được viết bằng một ngôn ngữ ngôn ngữ nguồn (source language) rồi dịch nó thành một chương trình tương đương ở một ngôn ngữ khác ngôn ngữ đích (target languague). Ebook miễn phí xin giới thiệu một phần quan trọng trong quá trình dịch là ghi nhận lại các lỗi có trong chương trình nguồn để thông báo lại cho người viết chương trình Ebook miễn phí giúp giúp người dùng tạo ra một chương trình đích có khả năng thực thi (excutable) thì ngoài trình biên dịch ta phải có thêm một số chương trình khác nữa. Ebook miễn phí xin giới thiệu sơ đồ sau mô tả ngữ cảnh của một trình biên dịch trong một hệ thống xử lí ngôn ngữ (languageprocessing system) Ebook miễn phí tổng hợp quá trình biên dịch được chia thành nhiều giai đoạn • Qua mỗi giai đoạn chương trình nguồn được chuyển đổi từ dạng biểu này sang một dạng biểu diễn khác • Trong thục tế xây dựng trình biên dịch, đôi khi các giai đoạn này được nhóm lại với nhau • Giai đoạn phân tích từ vựng sẽ đọc chương trình nguồn từ trái sang phải (linear analysisscanning) để tách ra thành các mã thông báo (token) • Trong quá trình phân tích từ vựng các khoảng trắng (blank) sẽ bị bỏ qua. Ebook miễn phí cũng tổng hợp giai đoạn phân tích cú pháp thực hiện công việc nhóm các token của chương trình nguồn thành các cụm từ văn phạm (grammatical phrase) Thông thường các cụm từ văn phạm này được biểu diễn bằng cây phân tích cú pháp (parse tree) với : Ngôn ngữ được định nghĩa bởi các luật sinh (production) Phân tích cú pháp dựa vào luật sinh để xây dựng cây phân tích cú pháp.

Trang 1

CHƯƠNG 1 Giới thiệu về chương trình dịch

Mục tiêu: Giới thiệu các khái niệm cơ bản, các

giai đoạn chính khi biên dịch chương trình

Trang 2

Khái niệm chương trình dịch

• Chương trình dịch (compiler) là một chương trình làm nhiệm vụ đọc một chương trình được viết bằng một ngôn ngữ - ngôn ngữ nguồn (source language) - rồi dịch nó thành một chương trình tương đương ở một ngôn ngữ khác - ngôn ngữ đích (target languague)

• Chương trình dịch ta còn gọi là trình biên dịch

• Một phần quan trọng trong quá trình dịch là ghi nhận lại các lỗi có trong chương trình nguồn để thông báo lại cho người viết chương trình

Trang 3

Chương trình nguồn

(Source program)

Trình biên dịch (Compiler)

Chương trình đích (Target program)

Thông báo lỗi (Error messages )

Trang 4

Ngữ cảnh của một trình biên dịch

• Để tạo tra một chương trình đích có khả năng thực thi (excutable) thì ngoài trình biên dịch ta phải có thêm một số chương trình khác nữa

• Sơ đồ sau mô tả ngữ cảnh của một trình biên dịch trong một hệ thống xử lí ngôn ngữ

(language-processing system)

Trang 5

Chương trình nguồn khung (Skeletal source program)

Thư viện/tập tin đối tượng

Bộ tiền xử lí (Preprocessor)

Chương trình nguồn (Source program)

Chương trình hợp ngữ đích (Target assembly program)

Trình dịch hợp ngữ (Assembler)

Mã máy tái khả định (Relocatable machine code)

Trình tải/liên kết (Loader/link-editor)

Trình biên dịch (Compiler)

Trang 6

Các giai đoạn biên dịch chương trình

• Quá trình biên dịch được chia thành nhiều giai

đoạn

• Qua mỗi giai đoạn chương trình nguồn được

chuyển đổi từ dạng biểu này sang một dạng

biểu diễn khác

• Trong thục tế xây dựng trình biên dịch, đôi khi

các giai đoạn này được nhóm lại với nhau

• Các giai doạn biên dịch được minh hoạ trong

hình vẽ dưới đây

Trang 7

Chương trình nguồn (Source program)

Quản lí lỗi (Error handler)

Phân tích từ vựng (Lexical analyzer)

Phân tích cú pháp (Syntax analyzer)

Sinh mã trung gian (Intermediate code generator)

Tối ưu mã (Code optimizer)

Sinh mã

Phân tích ngữ nghĩa (Semantic analyzer) Quản lí bảng kí tự

(Symbol-table manager)

Trang 8

1 Phân tích từ vựng (Lexical Analysis)

• Giai đoạn phân tích từ vựng sẽ đọc chương trình

nguồn từ trái sang phải (linear analysis/scanning) để tách ra thành các mã thông báo (token)

• Trong quá trình phân tích từ vựng các khoảng trắng (blank) sẽ bị bỏ qua

Trang 9

Ví dụ : Quá trình phân tích từ vựng cho câu lệnh

gán position := initial + rate * 60 sẽ tách thành

các token như sau:

1 Định danh (identifier) position

Trang 10

2 Phân tích cú pháp (Syntax Analysis)

• Giai đoạn phân tích cú pháp thực hiện công việc nhóm các token của chương trình nguồn thành các cụm từ văn phạm (grammatical phrase)

• Thông thường các cụm từ văn phạm này được biểu diễn bằng cây phân tích cú pháp (parse

Trang 11

• Ví dụ: Giả sử ngôn ngữ định nghĩa câu lệnh gán bởi các luật sinh sau :

assig stmt  id := expr

expr  expr + expr | expr * expr | (expr) | id | number

• Lệnh gán position := initial + rate * 60 được biểu diễn bằng parse tree như sau:

Trang 12

position := initial + rate * 60

Expr

| Number

| 60

assig stmt

| :=

Expr

| +

Expr

| id

| initial

| rate

Trang 13

• Cấu trúc phân cấp của một chương trình thường được diễn tả bởi quy luật đệ qui

Ví dụ: Định nghĩa đệ qui một biểu thức số học như

Trang 14

Ví dụ: Nhiều ngôn ngữ lập trình định nghĩa các

câu lệnh (statement) theo cách như sau :

1) Nếu id1 là một định danh và expr2 là một biểu thức thì id1 := expr2 là một lệnh (stmt)

2) Nếu expr1 là một biểu thức và stmt2 là một lệnh thì

while (expr1) do stmt2

If (expr1) then stmt2đều là các lệnh

Trang 15

3 Phân tích ngữ nghĩa (Semantic Analysis)

• Giai đoạn phân tích ngữ nghĩa sẽ thực hiện việc kiểm tra xem chương trình nguồn có chứa lỗi về ngữ nghĩa hay không

• Tập hợp thông tin về các kiểu dữ liệu cho giai

đoạn sinh mã về sau

• Sử dụng cấu trúc phân cấp của giai đoạn phân

tích cú pháp để xác định các toán tử, toán hạng của các biểu thức và câu lệnh

• Một phần quan trọng trong giai đoạn phân tích

Trang 16

Ví dụ: Trong câu lệnh position := initial + rate * 60

Giả sử các biến rate, initial và position được khai báo

là real, 60 là số integer vì vậy trình biên dịch sẽ đổi số

Trang 17

4 Sinh mã trung gian (Intermediate Code

Generator)

• Sau khi phân tích cấu trúc và ngữ nghĩa, một số trình biên dịch sẽ tạo ra một dạng biểu diễn

trung gian của chương trình nguồn

• Mã trung gian có 2 đặc tính quan trọng: Dễ tạo

và dễ dàng chuyển đổi thành chương trình đích

• Mã trung gian có cách biểu diễn Thông thường người ta sử dụng dạng "mã máy 3 địa chỉ"

(three-address code), tương tự như dạng hợp

ngữ cho một máy mà trong đó mỗi vị trí bộ nhớ

Trang 18

Ví dụ: Lệnh position := initial + rate * 60 khi chuyển

sang dạng mã trung gian three-address code có dạng:

temp1 := inttoreal (60)

temp2 := id3 * temp1

temp3 := id2 + temp2id1 := temp3

 Ta dùng id1, id2, id3 thay thế cho position, initial và

rate để nhấn mạnh rằng tên của một nhận dạng sẽ

bị thay đổi khi ta biên dịch chương trình

Trang 19

5 Tối ưu mã (Code Optimizer)

• Giai đoạn tối ưu mã cố gắng tối ưu mã trung gian

để thu được mã máy thực hiện nhanh hơn

Ví dụ: Mã trung gian nêu trên có thể tối ưu thành:

temp1 := id3 * 60.0

id1 := id2 + temp1

Trang 20

6 Sinh mã (Code generation)

• Giai đoạn cuối cùng của biên dịch là sinh mã đích, thường là mã máy hoặc mã hợp ngữ

• Vị trí các vùng nhớ gán cho các biến được chương trình sử dụng

• Sau đó, các lệnh trung gian được dịch lần lượt

thành chuỗi các chỉ thị mã máy Vấn đề quyết định

là việc gán các biến cho các thanh ghi

Trang 21

Ví dụ: Sử dụng các thanh ghi (chẳng hạn R1, R2) cho việc sinh mã đích như sau:

Trang 22

Quản lí bảng kí tự

• Một nhiệm vụ quan trọng của trình biên dịch là ghi lại các định danh được sử dụng trong chương trình

nguồn và thu thập các thông tin về các thuộc tính

khác nhau của mỗi định danh

• Các thuộc tính cung cấp thông tin về vị trí bộ nhớ được cấp phát cho một định danh, kiểu và phạm vi của định danh

• Nếu định danh là tên của một thủ tục thì thuộc tính

là các thông tin về số lượng và kiểu của các đối số, phương pháp truyền đối số và kiểu trả về của thủ tục (nếu có)

Trang 23

• Bảng ký hiệu (symbol table) là một cấu trúc dữ liệu mà mỗi phần tử là một bản ghi dùng để lưu trữ một định danh, các trường là các thuộc tính của định danh

• Trong quá trình phân tích từ vựng, tên các định danh được tìm thấy và nó được đưa vào bảng

ký hiệu nhưng thường thì các thuộc tính của nó chưa xác định được trong giai đoạn này

• Các thuộc tính khác của các định danh sẽ được

bổ sung trong các giai đoạn biên dịch tiếp theo

Trang 24

Ví dụ: Trong Pascal câu lệnh khai báo biến

Var position, initial, rate: real;

Sau khi phân tích từ vựng bảng quản lí kí tự có dạng như sau:

Trang 25

Xử lí lỗi

• Mỗi giai đoạn biên dịch có thể gặp nhiều lỗi, ví dụ:

 Giai đoạn phân tích từ vựng gặp lỗi khi các ký tự

không thể ghép thành một token

 Giai đoạn phân tích cú pháp gặp lỗi khi các token

không thể kết hợp với nhau theo đúng cấu trúc ngôn ngữ

 Giai đoạn phân tích ngữ nghĩa gặp lỗi khi các toán hạng có kiểu không đúng yêu cầu của phép toán

• Sau khi phát hiện ra lỗi, tùy thuộc vào trình biên dịch

Trang 26

Ví dụ: Biên dịch 1 câu lệnh gán

position := initial + rate * 60

Phân tích từ vựng

Phân tích cú pháp :=

60

+ id2

id1

* id3

id1 := id2 + id3 * 60

Trang 27

Sinh mã trung gian

temp1 := inttoreal (60)

temp2 := id3 * temp1

temp3 := id2 + temp2

id1

* id3

60

Trang 29

CHƯƠNG II Phân tích từ vựng

Mục tiêu: Nắm được vai trò của giai đoạn phân tích từ vựng, sử dụng các khái niệm biểu thức chính qui (regular expression) và ô- tô- mát

hứu hạn (finite automata) trong việc biểu diễn

và nhận biết ngôn ngữ

Trang 30

Vai trò của phân tích từ vựng

• Đây là giai đoạn đầu tiên của quá trình biên dịch

• Nhiệm vụ chính: Đọc từng kí tự vào (input

characters) từ chương trình nguồn và nhóm lại

thành các token phục vụ cho giai đoạn phân tích cú pháp sau đó

Source

program

Lexical analyzer

Get next token

Token

Parser

Symbol table

Trang 31

• Phân tích từ vựng giúp cho các giai đoạn biên dịch tiếp theo dễ dàng hơn, ví dụ: Giai đoạn

phân tích cú pháp không phải quan tâm đến các khoảng trắng cũng như các lời chú trích vì nó đã được loại bỏ khi khi phân tích từ vựng

• Giảm đáng kể thời gian đọc chương trình nguồn

và nhóm thành các token nhờ một số chương

trình xử lí chuyên dụng

Trang 32

Một số khái niệm

• Token: Một token là một tập hợp các xâu kí tự

có một nghĩa xác định, ví dụ identifier token là tập hợp tất cả các identifier Token chính là các

kí hiệu kết thúc (terminal) trong định nghĩa văn phạm của một ngôn ngữ, ví dụ: Các từ khoá,

định danh, toán tử, hằng, xâu kí tự, dấu ngoặc đơn, dấu phẩy, dấu chấm phẩy

• Pattern: Pattern của một token là các qui tắc kết hợp các kí tự để tạo lên token đó

• Lexeme: Là một chuỗi các kí tự thoả mãn

pattern của một token

Trang 33

• Bảng sau đưa ra các ví dụ về token, pattern và lexeme

Token Lexeme Thông tin mô tả của pattern

<, <=, >, >=, =, <>

pi, count, d2 3.1416, 0, 6.02E2

"computer"

const if

< hoặc <= hoặc > hoặc >= hoặc = hoặc <> một kí tự, tiếp theo là các kí tự hoặc chữ số bất kì hằng số nào

các kí tự nằm giữa " và " ngoại trừ "

Trang 35

• Các phép toán trên ngôn ngữ: Giả sử L và M là hai ngôn ngữ khi đó

Hợp (union)của L và M: LM={s|s  L hoặc s  M }

Ghép (concatenation) của L và M: LM = { st | s  L và t  M }

Bao đóng Kleen (kleene closure) L: L* = i=0 L i

(Ghép của 0 hoặc nhiều L)

Bao đóng dương (positive closure) của L: L+ = i=1 L i

(Ghép của 1 hoặc nhiều L)

Trang 36

một chữ cái theo sau là chữ cái hay chữ số

6 D + là tập hợp tất cả các xâu gồm một hoặc nhiều

chữ số

Trang 37

Biểu thức chính qui (regular expression)

• Mỗi biểu thức chính qui (BTCQ) r dùng để đặc tả một ngôn ngữ L(r)

Ví dụ: Trong pascal mọi identifier được đặc tả

bởi biểu thức chính qui letter(letter|digit)*

• Hai BTCQ r và s được gọi là tương đương (kí

hiệu r=s) nếu chúng đặc tả chung một ngôn ngữ

Ví dụ: (a|b)=(b|a)

Trang 38

• Sau đây là các luật định nghĩa các BTCQ trên một bảng chữ cái 

1  là một BTCQ đặc tả {} (tập hợp chứa xâu rỗng)

2 Nếu a  thì a là BTCQ đặc tả {a}

3 Giả sử r và s là các BTCQ đặc tả các ngôn

ngữ L(r) và L(s), khi đó:

a) (r)|(s) là một BTCQ đặc tả L(r)L(s) b) (r)(s) là một BTCQ đặc tả L(r)L(s) c) (r) * là một BTCQ đặc tả (L(r)) *

d) (r) là một BTCQ đặc tả L(r)

Trang 39

5. BTCQ a | a* b đặc tả {a, b, ab, aab, }

Trang 40

Định nghĩa chính qui (regular definition)

• Để thuận tiện về mặt kí hiệu, ta dùng định nghĩa chính qui (ĐNCQ) để đặt tên cho các BTCQ

• Một ĐNCQ là một dãy các định nghĩa có dạng

d1  r1

d2  r2

dn  rnTrong đó di là các tên, ri là các BTCQ trên tập

các kí hiệu {d1, d2, di-1}

Trang 41

Ví dụ: ĐNCQ của các định danh trong pascal là

letter  A | B | | Z | a | b | | z digit  0 | 1 | | 9

id  letter (letter | digit)*

Ví dụ: ĐNCQ của các số không dấu trong pascal

như 3254, 23.243E5,16.264E-3 là

digit  0 | 1 | | 9 digits  digit digit*

optional_fraction  digits | e optional_exponent  ( E ( + | - | e ) digits) | e num  digits optional_fraction optional_exponent

Trang 42

• Các kí hiệu tắt được sử dụng trong các BTCQ

• Sử dụng các tập kí tự [abc]=a | b | c, [a-z]=a | b | z

ta có thể đặc tả các định danh bởi BTCQ

[A - Z a - z] [A - Z a - z 0 - 9]*

Trang 44

• Trong đó các kí hiệu kết thúc (token) if, then,

else, relop, id sinh ra tập các xâu kí tự theo các ĐNCQ sau:

Trang 45

• Mục đích của lexical analyzer tạo ra output là

Trang 46

• Sơ đồ chuyển tiếp (transition diagram): Là bước trung gian minh hoạ tiến trình chuyển đổi trạng thái khi bộ phân tích từ vựng đọc lần lượt từng

kí tự

• Ta phải xây dựng các sơ đồ chuyển tiếp để

nhận biết từng loại token

• Một sơ đồ chuyển tiếp bao gồm các trạng thái (states) được vẽ bằng hình tròn, có 1 trạng thái bắt đầu (start state) Các trạng thái được nối với nhau bởi các mũi tên ta gọi là các cạnh (edges)

• Trạng thái được biểu diễn bởi vòng tròn kép là trạng thái được chấp nhận (accepting state)

thông báo 1 token đã được nhận dạng

Trang 47

Ví dụ: Sơ đồ chuyển tiếp cho token các toán tử

quan hệ relop

0

7 6

5

4 3

2

return (relop, NE)

return (relop, LT) return (relop, EQ)

return (relop, GE)

Trang 48

Ví dụ: Sơ đồ chuyển tiếp cho token các identifier và

keyword

• Chú ý:

- Các từ khoá là các từ được bảo vệ và được lưu trữ sẵn trong symbol-table

- Thủ tục gettoken() tra cứu lexeme trong symbol-table

nếu là 1 keyword thì token tương ứng được trả về còn

ngược lại token id được trả về

- Thủ tục install_id() tra cứu lexeme trong symbol-table

nếu là 1 keyword thì trả lại giá trị 0, nếu là một biến đã có thì trả lại một con trỏ tới vị trí trong symbol-table Nếu

lexeme không có thì tạo một phần tử mới trong

symbol-table và trả về con trỏ tới thành phần mới vừa được tạo

9 letter 10 11 return (gettoken(), install_id())

start

letter or digit

other *

Trang 49

Ví dụ: Sơ đồ chuyển tiếp cho token các unsigned

numbers trong pascal

digit

Trang 50

Ví dụ: Sơ đồ chuyển tiếp cho token các ws

Trang 51

Công cụ phân tích từ vựng Lex

• Một số công cụ có sẵn cho phép xây dựng một

bộ phân tích từ vựng dựa trên các biểu thức

Trang 52

Lex source

program lex.l

Lex compiler Lex.yy.c

Trang 53

Ô- tô- mát hữu hạn (finite automata)

• Một bộ nhận dạng ngôn ngữ (recognizer for a language) là một chương trình nhận đầu vào là một xâu kí tự x, trả lời "Yes" nếu x thuộc ngôn ngữ và trả lời "No" nếu ngược lại

• Ô- tô- mát hữu hạn là một sơ đồ chuyển tiếp

được khái quát hoá, đóng vai trò là recognizer cho các biểu thức chính qui

• Một Ô- tô- mát hữu hạn có thể là deterministic finite automata (DFA) hoặc nondeterministic

Trang 54

• "Nondeterministic" nghĩa là khi một kí tự được đọc vào thì sơ đồ chuyển tiếp có thể chuyển đến nhiều hơn một trạng thái tiếp theo

• Cả hai DFA và NFA đều có khả năng nhận dạng các biểu thức chính qui

• DFA có thể nhận dạng nhanh hơn nhưng cũng

có kích thước lớn hơn NFA tương đương

Trang 55

- Một tập hợp kí tự vào của bảng chữ cái 

- Một hàm chuyển đổi trạng thái move: S x ({})S

(Một phép chuyển đổi (sk, )  sj nghĩa là chuyển từ sksang sj mặc dù không có kí tự nào được đọc vào)

• NFA được biểu diễn trực tiếp bằng sơ đồ

Trang 56

Ví dụ: NFA nhận biết BTCQ (a|b)*abb được mô tả dưới đây trong đó tập S={0, 1, 2, 3}, ={a, b},

Trang 57

Ví dụ: NFA nhận biết biểu thức chính qui aa* | bb*

Trang 58

• DFA là một trường hợp đặc biệt của NFA, DFA

có thêm các dặc diểm sau:

- Không có chuyển đổi trạng thái ứng với kí tự rỗng 

- Từ một trạng thái s khi có một kí tự x được đọc vào, DFA sẽ chuyển sang một trạng thái s' duy nhất

Trang 59

Ví dụ: DFA nhận biết BTCQ (a|b)*abb

0

b

start

2 1

a

b a

a

Trang 60

CHƯƠNG III Phân tích cú pháp

Mục tiêu:

pháp

grammar),cách phân tích cú pháp từ dưới

lên- từ trên xuống (top-down and bottom-up parsing)

Trang 61

Vai trò của bộ phân tích cú pháp

Rest of front end

Trang 62

• Các phương pháp phân tích cú pháp

(PTCP) chia làm hai loại: Phân tích từ trên xuống (top- down parsing) và phân tích từ dưới lên (bottom- up parsing)

lỗi trong giai đoạn PTCP do đó bộ phân

tích cú pháp phải phát hiện và thông báo lỗi chính xác cho người lập trình đồng thơi không làm chậm những chương trình được viết đúng

Trang 63

- Các kí hiệu chưa kết thúc (nonterminals): Là

các biến kí hiệu tập các xâu kí tự

- Các luật sinh (productions): Xác định cách

thức hình thành các xâu từ các kí hiệu kết thúc

Trang 64

Ví dụ 3.1: Văn phạm sau định nghĩa các

biểu thức số học đơn giản

E  E A E | (E) | -E | id

A  + | - | * | / |  Trong đó E, A là các kí tự chưa kết thúc (E còn là kí tự bắt đầu), các kí tự còn lại là

các kí tự kết thúc

Ngày đăng: 09/06/2016, 08:20

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w