2013-05-11 37 views
9

Cách khớp với bất kỳ văn bản nào trong ANTLRv4? Tôi có nghĩa là văn bản, đó là không rõ tại thời điểm viết văn phạm?Kết hợp văn bản tùy ý (cả biểu tượng và dấu cách) với ANTLR?

ngữ pháp của tôi là sau:

grammar Anytext; 

line : 
    comment; 

comment : '#' anytext; 

anytext: ANY*; 

WS : [ \t\r\n]+; 

ANY : .; 

Và mã của tôi là sau:

String line = "# This_is_a_comment"; 

    ANTLRInputStream input = new ANTLRInputStream(line); 

    AnytextLexer lexer = new AnytextLexer(input); 

    CommonTokenStream tokens = new CommonTokenStream(lexer); 

    AnytextParser parser = new AnytextParser(tokens); 

    ParseTree tree = parser.comment(); 

    System.out.println(tree.toStringTree(parser)); // print LISP-style tree 

Output sau:

line 1:1 extraneous input ' ' expecting {<EOF>, ANY} 
(comment # (anytext T h i s _ i s _ a _ c o m m e n t)) 

Nếu tôi thay đổi ANY quy tắc

ANY : [ \t\r\n.]; 

nó dừng nhận ra bất kỳ biểu tượng nào cả.

UPDATE1

tôi không có ký tự dòng cuối ở cuối.

UPDATE 2

Vì vậy, tôi đã hiểu, rằng không thể để phù hợp với bất kỳ văn bản với lexer từ lexer không thể cho phép nhiều lớp. Nếu tôi xác định quy tắc lexer cho bất kỳ biểu tượng nào, nó sẽ ẩn tất cả các quy tắc khác hoặc không hoạt động.

Nhưng câu hỏi vẫn tồn tại.

Làm thế nào để khớp tất cả các biểu tượng ở cấp trình phân tích cú pháp?

Giả sử tôi có dữ liệu hình bảng và tôi không thể xử lý một số trường và bỏ qua các trường khác. Nếu tôi có anytext quy tắc, tôi sẽ viết

infoline : 
    (codepoint WS 'field1' WS field1Value) | 
    (codepoint WS 'field2' WS field2Value) | 
    (codepoint WS anytext); 

hàng ở đây tôi đang phân tích nếu cột thứ 2 chứa field1field2 giá trị và bỏ qua hàng khác.

Làm cách nào để thực hiện phương pháp này?

Trả lời

1

Sử dụng quy tắc sau đây để lấy ý kiến ​​dòng:

LINE_COMMENT 
    : '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 
    ; 

Nó phù hợp với '#' và biểu tượng bất kỳ cho đến khi nó được cho là cuối dòng (phá vỡ unix/cửa sổ dòng).

Sửa bởi 280Z28: đây là giống quy tắc chính xác trong ANTLR 4 cú pháp:

LINE_COMMENT 
    : '#' ~[\r\n]* '\r'? '\n' -> channel(HIDDEN) 
    ; 
+0

Tôi đã chỉnh sửa bài đăng của bạn để cung cấp chính xác quy tắc tương tự trong cú pháp ANTLR 4. Trên một ghi chú riêng biệt, tôi khuyên * không * bao gồm cả '' \ r '? '\ n'' dòng terminator như là một phần của quy tắc 'LINE_COMMENT' chính nó (làm cho nó tiêu thụ ký tự lên đến, nhưng không bao gồm hết dòng). Có một vài lý do tôi khuyên bạn nên điều này, nhưng lớn nhất là một thực tế là trong hình thức hiện tại 'LINE_COMMENT' sẽ không phù hợp với một bình luận trên dòng cuối cùng của một tập tin nếu nó không được theo sau bởi một terminator dòng rõ ràng. –

+0

vâng, đó là dành cho ANTLR 3, cảm ơn bạn đã chỉnh sửa – hoaz

+0

Tại sao quá phức tạp? Có thể viết đơn giản hơn không? Tại sao quy tắc của tôi không hoạt động? –

7

Điều quan trọng là phải nhớ rằng ANTLR sẽ chia tay đầu vào hoàn chỉnh của bạn vào thẻ trước khi phân tích cú pháp bao giờ nhìn thấy các dấu hiệu đầu tiên (tại ít nhất nó hoạt động theo cách này). Ngữ pháp lexer của bạn trông giống như sau.

T__0 : '#'; // implicit token created due to the use of '#' in parser rule comment 

WS : [ \t\r\n]+; 

ANY : .; 

Đối với đầu vào của bạn, các thẻ như sau:

  1. # (loại T__0)
  2. [không gian] (loại WS)
  3. T (loại ANY)
  4. h (loại ANY)
  5. i (loại ANY)
  6. s (loại ANY)
  7. _ (loại ANY)
  8. i (loại ANY)
  9. s (loại ANY)
  10. _ (loại ANY)
  11. a (loại ANY)
  12. _ (loại ANY)
  13. c (loại ANY)
  14. o (loại ANY)
  15. m (loại ANY)
  16. m (loại ANY)
  17. e (loại ANY)
  18. n (loại ANY)
  19. t (loại ANY)

ngữ pháp hiện tại của bạn thất bại trong việc phân tích vì token WS không được phép trong quy tắc comment. Nó sẽ phân tích đầu vào này (nhưng có thể chạy vào các vấn đề như bạn mở rộng ngữ pháp của bạn) nếu bạn sử dụng này:

// remember that '#' is its own token 
anytext: (ANY | WS | '#')*; 

gì bạn có thể làm là thay đổi comment trở thành một quy tắc lexer, trong đó tiêu thụ nhân vật # cùng với bất kỳ điều gì sau (trong trường hợp này, đến cuối dòng):

grammar Anytext; 

line : COMMENT; 

COMMENT : '#' ~[\r\n]*; 

WS : [ \t\r\n]+; 

ANY : .; 
+0

Tôi không hiểu, tại sao bạn viết '[dấu cách] (loại WS)'. Theo quan điểm của tôi, nó cũng là 'BẤT K''? Tại sao không? –

+2

@SuzanCioc ANTLR không bao giờ gán nhiều loại cho một mã thông báo. Ký tự khoảng trắng khớp với quy tắc 'WS' và' BẤT K' '. Để giải quyết sự mơ hồ, vì 'WS' xuất hiện trước' ANY' trong ngữ pháp, mã thông báo được gán kiểu 'WS'. Sự mơ hồ được giải quyết và loại mã thông báo được chỉ định trước khi trình phân tích cú pháp nhìn thấy mã thông báo, do đó trình phân tích cú pháp sẽ không bao giờ thấy mã thông báo ký tự khoảng trắng với loại 'ANY'. –

+0

Còn cây thì sao? Họ cũng bị cấm trong lexer? Nếu tôi viết 'WS: [\ t \ r \ n]; BẤT K:: WS | .; '? Không gian sẽ được đánh dấu bằng 'ANY' và 'WS'? –

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