2010-04-19 19 views
8

Tôi đang sử dụng GNU Bison 2.4.2 để viết một ngữ pháp cho một ngôn ngữ mới mà tôi đang làm việc và tôi có một câu hỏi. Khi tôi xác định một quy tắc, chúng ta hãy nói:Bison: Mã thông báo tùy chọn trong một quy tắc duy nhất

statement : T_CLASS T_IDENT '{' T_CLASS_MEMBERS '}' { 
      // create a node for the statement ... 
} 

Nếu tôi có một sự thay đổi trên quy tắc, ví dụ

statement : T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST '{' T_CLASS_MEMBERS '}' { 
      // create a node for the statement ... 
} 

đâu (từ quy tắc quét flex):

"class"      return T_CLASS; 
"extends"     return T_EXTENDS; 
[a-zA-Z\_][a-zA-Z0-9\_]* return T_IDENT; 

(và T_IDENT_LIST là quy tắc cho số nhận dạng được phân tách bằng dấu phẩy).

Có cách nào để chỉ định tất cả điều này chỉ trong một quy tắc, đặt bằng cách nào đó "T_EXTENDS T_IDENT_LIST" làm tùy chọn không? Tôi đã thử với

T_CLASS T_IDENT (T_EXTENDS T_IDENT_LIST)? '{' T_CLASS_MEMBERS '}' { 
    // create a node for the statement ... 
} 

Nhưng Bison đã cho tôi một lỗi.

Cảm ơn

Trả lời

9

Để tạo một câu chuyện dài, ngắn gọn. Bison chỉ đề cập đến LALR (1) ngữ pháp, có nghĩa là nó chỉ sử dụng một biểu tượng của lookahead. Những gì bạn cần là một cái gì đó như thế này:

statement: T_CLASS T_IDENT extension_list '{' ... 

extension_list: 
       | T_EXTENDS T_IDENT_LIST 
       ; 

Có các trình tạo trình phân tích cú pháp khác hoạt động với nhiều ngữ pháp chung hơn. Nếu bộ nhớ phục vụ, một số trong số chúng hỗ trợ các phần tử tùy chọn tương đối trực tiếp như bạn đang yêu cầu.

+0

Đó là giải pháp để viết chỉ một quy tắc mà không có | :) Cảm ơn! –

+0

Nó không liên quan gì đến nó là LALR (1), vì cả hai đều là LALR (1). Bởi vì cú pháp đầu vào là BNF chứ không phải EBNF. –

+1

@ChrisDodd: Xin lỗi, nhưng sai. Vấn đề ở đây là khi anh ta viết nó, trình phân tích cú pháp của anh ta sẽ phải xem xét trước ba ký hiệu, trên T_CLASS và T_IDENT để xem biểu tượng tiếp theo là '{' hay T_EXTENDS để xem biến thể 'statement' nào sử dụng. Đó là vi phạm LALR (1). EBNF trông giống như một cá trích đỏ hoàn toàn đối với tôi - tôi chẳng thấy gì giống với EBNF ở bất kỳ đâu trong câu hỏi. –

0

Tôi nghĩ rằng hầu hết các bạn có thể làm là

statement : T_CLASS T_IDENT '{' T_CLASS_MEMBERS '}' 
    | T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST '{' T_CLASS_MEMBERS '}' { 
} 
0

Tại sao bạn không chỉ cần tách chúng bằng cách sử dụng lựa chọn (|) điều hành?

statement: 
    T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST '{' T_CLASS_MEMBERS '}' 
    | T_CLASS T_IDENT '{' T_CLASS_MEMBERS '}' 

Tôi không nghĩ rằng bạn có thể làm điều đó chỉ vì đây là một LALR (1) phân tích cú pháp từ dưới lên, bạn sẽ cần một cái gì đó khác nhau như một LL (k) (ANTLR?) Để làm những gì bạn muốn để làm ..

Các vấn đề liên quan