2011-06-27 26 views

Trả lời

72

Một đoạn có phần giống như một hàm nội tuyến: Nó làm cho ngữ pháp dễ đọc hơn và dễ bảo trì hơn.

Một đoạn sẽ không bao giờ được tính là mã thông báo, nó chỉ phục vụ để đơn giản hóa ngữ pháp.

xem xét:

NUMBER: DIGITS | OCTAL_DIGITS | HEX_DIGITS; 
fragment DIGITS: '1'..'9' '0'..'9'*; 
fragment OCTAL_DIGITS: '0' '0'..'7'+; 
fragment HEX_DIGITS: '0x' ('0'..'9' | 'a'..'f' | 'A'..'F')+; 

Trong ví dụ này, phù hợp với một số sẽ luôn luôn trả về một số để lexer, bất kể nếu nó phù hợp với "1234", "0xab12", hoặc "0777".

See item 3

+26

Bạn đang đúng về những gì 'fragment' có nghĩa là trong ANTLR. Nhưng ví dụ bạn đưa ra là một ví dụ nghèo nàn: bạn không muốn một lexer tạo ra một mã thông báo 'NUMBER' có thể là một số thập phân, thập phân hoặc bát phân. Điều đó có nghĩa là bạn cần kiểm tra mã thông báo 'NUMBER' trong quy tắc sản xuất (quy tắc phân tích cú pháp). Bạn tốt hơn có thể để lexer tạo ra các thẻ 'INT',' OCT' và 'HEX' và tạo ra một quy tắc sản xuất:' number: INT | OCT | HEX; '. Trong ví dụ này, một 'DIGIT' có thể là một mảnh sẽ được sử dụng bởi các thẻ' INT' và 'HEX'. –

+5

Lưu ý rằng "người nghèo" nghe có vẻ hơi khắc nghiệt, nhưng tôi không thể tìm thấy một từ tốt hơn cho nó ... Xin lỗi! :) –

+1

Bạn không nghe có vẻ gay gắt .. bạn đã đúng và thẳng! – asyncwait

8

Theo Definitive Antlr4 tài liệu tham khảo cuốn sách:

Rules bắt đầu bằng đoạn có thể được gọi là chỉ từ quy tắc lexer khác; chúng không phải là mã thông báo theo cách riêng của chúng.

thực sự chúng sẽ cải thiện khả năng đọc của các ngữ pháp của bạn.

xem ví dụ này:

STRING : '"' (ESC | ~["\\])* '"' ; 
fragment ESC : '\\' (["\\/bfnrt] | UNICODE) ; 
fragment UNICODE : 'u' HEX HEX HEX HEX ; 
fragment HEX : [0-9a-fA-F] ; 

STRING là một lexer sử dụng quy tắc mảnh như ESC .Unicode được sử dụng trong quy tắc Esc và Hex được sử dụng trong quy tắc mảnh Unicode. Các quy tắc ESC và UNICODE và HEX không thể sử dụng một cách rõ ràng.

4

blog post này có một ví dụ rất rõ ràng nơi fragment làm cho một sự khác biệt đáng kể:

grammar number; 

number: INT; 
DIGIT : '0'..'9'; 
INT : DIGIT+; 

Ngữ pháp sẽ nhận ra '42' nhưng không '7'. Bạn có thể sửa chữa nó bằng cách làm cho chữ số một mảnh (hoặc di chuyển DIGIT sau INT).