Ví dụ về phân chia khối trong thân hàm

Một phần của tài liệu (LUẬN văn THẠC sĩ) ứng dụng mô hình ngôn ngữ ngữ nghĩa thống kê trong gợi ý mã cho ngôn ngữ c (Trang 27 - 30)

Hình 3.1 biểu diễn một hàm test, có một đối số có kiểu dữ liệu int là b. Trong thân hàm gồm một vòng lặp for, một câu lệnh điều kiện if, và hai vòng lặp while. Các thông tin liên quan đến phạm vi được chỉ ra trong bảng 3.3. Chúng ta có thể thấy các biến b và a thuộc khối function. Khối function có khối cha là FILE và định danh là 1. Khối for có định danh là 2, khối cha là function và chứa khai báo biến i. Khối if có định danh là 3, khối cha là for và không chứa khai báo biến. Tương tự, khối while có định danh là 4, khối cha là if và không chứa khai báo biến. Cuối cùng, khối while có định danh là 5, khối cha là while và chứa một khai báo biến ch.

Bảng 3. 3. Thông tin khối

Định danh Khối cha Loại khối Danh sách biến được khai báo

1 FILE function b, a

2 function for i

3 for if

4 if while

5 while while ch

3.2 Cách thức xây dựng chương trình mô phỏng

Để xây dựng chương trình mô phỏng áp dụng SLAMC trong gợi ý mã cho ngôn

ngữ C, chúng ta cần tìm hiểu cách chuyển đổi mã nguồn C sang cây cú pháp trừu tượng. Sau đó, duyệt cây cú pháp này nhằm trích xuất các thông tin cần thiết của các từ tố để biểu diễn dưới dạng nghĩa vị, xây dựng cây tiền tố dựa trên các n-gram và thực hiện huấn luyện dữ liệu (n-gram chủ đề, cặp giá trị). Tiếp theo, tìm kiếm các từ tố liên quan trên cây tiền tố, kết hợp với cặp giá trị và n-gram chủ đề để tính điểm liên quan. Cuối cùng, xác định sự phù hợp ngữ cảnh, phạm vi và biến đổi từ dạng ngữ nghĩa sang

từ vựng nhằm đưa ra danh sách gợi ý mã. Ta sẽ đi vào chi tiết các phần trong các mục tiếp theo.

3.2.1Cây cú pháp trừu tượng (AST)

Cây cú pháp trừu tượng là một cây có giới hạn, có nhãn và có hướng. Đây là cấu trúc cây mà các nút gốc của cây được gán nhãn bằng các toán tử và các nút lá của cây là các toán hạng. Tuy vậy, các lá cũng có khi là các giá trị NULL hoặc là các biến. Trong các công đoạn của chương trình dịch, cây AST được dùng trong bộ phân tích cú pháp như là một trung gian giữa cây phân tích cú pháp và cấu trúc dữ liệu [6].

Cài đặt SLAMC cho C, chúng ta có thể sử dụng một số công cụ giúp cho việc

chuyển đổi mã nguồn sang cây cú pháp trừu tượng như Clang, và Eclipse CDT parser. Clang là một lựa chọn tốt bởi vì công cụ này có tài liệu mô tả tốt hơn Eclipse CDT parser, nhưng Clang được viết trong C++ [3]. Ngôn ngữ xây dựng chương trình mô phỏng là Java, vì vậy luận văn đã lựa chọn áp dụng Eclipse CDT parser để chuyển đổi mã nguồn C sang cây cú pháp trừu tượng.

Để sử dụng Eclipse CDT parser, chúng ta phải tải về một gói jar có tên là “org.eclipse.cdt.core_5.3.1.201109151620.jar” và thêm vào chương trình như một thư viện của Java. Hình 3.2 chỉ ra danh sách các lớp cần thiết để thực thi chuyển đổi mã nguồn C sang cây cú pháp trừu tượng. Hình 3.3 đưa ra các bước để gọi Eclipse CDT parser. Hình 3.4 trình bày một ví dụ chuyển đổi mã nguồn C sang cây cú pháp trừu tượng. import java.util.*; import org.eclipse.cdt.core.dom.ast.*; import org.eclipse.cdt.core.dom.ast.gnu.c.GCCLanguage; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.parser.*;

Hình 3. 2. Danh sách cần import để gọi CDT parser [3]

Hình 3.2 trình bày danh sách các lớp cần import để thực hiện chương trình. Nhiều lớp được sử dụng, nhưng lớp GCCLanguage là lớp được quan tâm nhất bởi vì lớp này trực tiếp thực hiện việc chuyển đổi mã nguồn C sang cây cú pháp trừu tượng.

private static IASTTranslationUnit parse(char[] code) throws Exception { FileContent fc = FileContent.create("", code);

Map<String, String> macroDefinitions = new HashMap<String, String>(); String[] includeSearchPaths = new String[0];

IScannerInfo si = new ScannerInfo(macroDefinitions, includeSearchPaths); IncludeFileContentProvider ifcp = IncludeFileContentProvider

.getEmptyFilesProvider(); IIndex idx = null;

int options = ILanguage.OPTION_IS_SOURCE_UNIT; IParserLogService log = new DefaultLogService();

return GCCLanguage.getDefault().getASTTranslationUnit(fc, si, ifcp, idx, options, log);

}

Hình 3. 3. Gọi Eclipse CDT parser [3]

public static void main(String[] args) throws Exception { String code = "void testBooks(int c, char b){}";

IASTTranslationUnit translationUnit = parse(code.toCharArray()); ASTVisitor visitor = new ASTVisitor() {

@Override

public int visit(IASTName name) {

System.out.print(name.toString() + " "); return ASTVisitor.PROCESS_CONTINUE; } }; visitor.shouldVisitNames = true; translationUnit.accept(visitor); }

Hình 3. 4. Chuyển đổi đoạn mã “void testBooks(int c, char b){}”

CDT parser trả về một cây cú pháp trừu tượng như là kết quả của việc chuyển đổi mã nguồn. Cây AST này bao gồm nhiều nút. Mỗi nút tương ứng với một cú pháp của mã. Ví dụ: định nghĩa một hàm, một phát biểu if, một vòng lặp for, hoặc một biến.

3.2.2Duyệt cây cú pháp trừu tượng

Sau khi có cây cú pháp trừu tượng được trả về như trong mục 3.2.1, chúng ta phải thực hiện một bước quan trọng là duyệt cây này để lấy ra các thông tin cần thiết nhằm thực hiện việc biểu diễn nghĩa vị cũng như các tính toán quan trọng khác. Ở đây,

ta chỉ xét các nút lưu trữ thông tin cần thiết và bỏ qua các nút lưu trữ các từ tố không cần thiết khi biểu diễn nghĩa vị và tính toán về sau như dấu phảy, dấu ngoặc đơn, … Khi duyệt một tệp mã nguồn C, chúng ta có thể phân chia thành ba trường hợp đó là các nút lưu trữ thông tin khai báo toàn cục được đặt bên ngoài tất cả các hàm, các nút lưu trữ thông tin về hàm, và các nút bị coi như có vấn đề có thể do sai cú pháp, ngữ nghĩa hoặc chưa hoàn chỉnh. Chi tiết của từng trường hợp sẽ được trình bày ở các mục dưới đây.

3.2.2.1 Nút lưu trữ thông tin khai báo toàn cục

Trong C, các nút lưu trữ thông tin khai báo toàn cục có thể bao gồm khai báo biến, struct, union và typedef, vì vậy khi duyệt qua các nút này chúng ta nên phân chia để duyệt từng loại nhằm tránh sự trùng lặp dữ liệu. Để hiểu rõ các thông tin cần lấy khi duyệt, chúng ta xem xét các ví dụ như dưới đây.

Ví dụ 1: Duyệt một khai báo biến đơn giản “int a = 0”. Duyệt khai báo biến này, chúng ta có thể lấy được các thông tin như kiểu dữ liệu int, tên biến a, phép gán “=”, và giá trị của biến a là 0. Sau khi lấy được các thông tin này, chúng ta có thể biểu diễn nghĩa vị của từng thông tin, cũng như lưu trữ vào một danh sách. Các nghĩa vị thu được là: TYPE[int], VAR[int, var], OP(ass_equal), LIT(int).

Ví dụ 2: Duyệt một định nghĩa struct

struct Books2 { char title[50]; char author[50]; char subject[100]; int book_id; } book;

Một phần của tài liệu (LUẬN văn THẠC sĩ) ứng dụng mô hình ngôn ngữ ngữ nghĩa thống kê trong gợi ý mã cho ngôn ngữ c (Trang 27 - 30)

Tải bản đầy đủ (PDF)

(61 trang)