2010-02-20 36 views
8

Tôi vừa mới bắt đầu để chơi xung quanh với máy phân tích ngữ pháp sử dụng javacc và một trong những lĩnh vực là lựa chọn một ... Tôi có một mã số như folowing:javacc tùy chọn phân tích cú pháp lookahead, Java

options 
{ 
    LOOKAHEAD=1; 
} 
PARSER_BEGIN(Calculator) 

public class Calculator 
{ 
... 
} 
PARSER_END(Calculator) 

gì chính xác nó có nghĩa là tùy chọn LOOKAHEAD? Cảm ơn

Trả lời

7

Xem http://en.wikipedia.org/wiki/Lookahead#Lookahead_in_parsing

Thông thường, các phân tích cú pháp chỉ nhìn vào dấu hiệu tiếp theo để xác định những quy tắc sản xuất để áp dụng. Tuy nhiên, trong một số trường hợp không đủ để đưa ra lựa chọn. Ví dụ, đưa ra hai quy tắc sản xuất:

p0: foo -> identifier "=" expr 
p1: bar -> identifier "(" arglist ")" 

Nếu mã thông báo tiếp theo là loại identifier sau đó phân tích cú pháp không thể xác định xem nó nên sử dụng các sản foo hoặc bar. JavaCC sau đó sẽ đưa ra một lỗi, nói rằng nó cần phải sử dụng nhiều hơn nhìn về phía trước. Thay đổi nhìn về phía trước thành 2 có nghĩa là trình phân tích cú pháp được phép xem xét hai mã thông báo tiếp theo, trong trường hợp này là đủ để lựa chọn giữa các sản phẩm.

Như Steve đã chỉ ra, đây là trong các tài liệu javacc: https://javacc.org/tutorials/lookahead

2

Giá trị lookahead kể phân tích cú pháp được tạo ra bao nhiêu chưa qua chế biến (ví dụ, trong tương lai) mã thông báo sử dụng để quyết định những gì nhà nước để chuyển đổi sang. Trong một ngôn ngữ ràng buộc chặt chẽ, chỉ cần một mã thông báo tra cứu. Ngôn ngữ càng mơ hồ thì càng cần nhiều mã thông báo để xác định chuyển tiếp trạng thái nào cần thực hiện.

Tôi nghĩ điều này được đề cập trong hướng dẫn javacc (1).

8

JavaCC tạo trình phân tích cú pháp gốc đệ quy. Loại trình phân tích cú pháp này hoạt động bằng cách xem biểu tượng tiếp theo để quyết định chọn quy tắc nào. Theo mặc định, nó chỉ nhìn vào biểu tượng tiếp theo (lookahead = 1). Nhưng bạn có thể cấu hình trình phân tích cú pháp để xem không chỉ ở bước tiếp theo mà còn là các ký hiệu N tiếp theo. Nếu bạn đặt lookahead thành 2, trình phân tích cú pháp được tạo sẽ xem xét hai biểu tượng tiếp theo để quyết định chọn quy tắc nào. Bằng cách này, bạn có thể xác định ngữ pháp của mình tự nhiên hơn, nhưng với chi phí hiệu suất. The lookahead càng lớn thì trình phân tích cú pháp càng phải làm.

Nếu bạn đặt con trỏ chung thành số lớn hơn, trình phân tích cú pháp của bạn sẽ chậm hơn cho tất cả các đầu vào (cho các ngữ pháp không tầm thường). Bạn có thể sử dụng lookahead cục bộ nếu bạn muốn cho phép trình phân tích cú pháp bằng lookahead = 1 theo mặc định và chỉ sử dụng một lookahead lớn hơn trong các tình huống cụ thể.

http://www.engr.mun.ca/~theo/JavaCC-FAQ/javacc-faq-moz.htm#tth_sEc4.5

Ví dụ, một phân tích cú pháp với lookahead = 1 không thể quyết định các quy tắc (1 hoặc 2) để có, nhưng với lookahead = 2 nó có thể:

void rule0() : {} { 
    <ID> rule1() 
| <ID> rule2() 
} 

Bạn có thể thay đổi định nghĩa ngữ pháp để có kết quả tương tự nhưng sử dụng lookahead = 1:

void rule0() : {} { 
    <ID> (rule1() | rule2()) 
} 
Các vấn đề liên quan