2009-12-19 42 views
15

Tôi đang sử dụng ocamlyacc và ocamllex. Tôi có một lỗi sản xuất trong ngữ pháp của tôi báo hiệu một ngoại lệ tùy chỉnh. Cho đến nay, tôi có thể báo cáo vị trí lỗi:lỗi phân tích cú pháp ocamlyacc: mã thông báo nào?

| error { raise (Parse_failure (string_of_position (symbol_start_pos()))) } 

Nhưng, tôi cũng muốn biết mã thông báo nào đã được đọc. Phải có cách nào đó --- có ai biết không?

Cảm ơn.

Trả lời

14

Tokens được tạo ra bởi lexer, do đó bạn có thể sử dụng thẻ lexer hiện khi lỗi xảy ra:

let parse_buf_exn lexbuf = 
    try 
     T.input T.rule lexbuf 
    with exn -> 
     begin 
     let curr = lexbuf.Lexing.lex_curr_p in 
     let line = curr.Lexing.pos_lnum in 
     let cnum = curr.Lexing.pos_cnum - curr.Lexing.pos_bol in 
     let tok = Lexing.lexeme lexbuf in 
     let tail = Sql_lexer.ruleTail "" lexbuf in 
     raise (Error (exn,(line,cnum,tok,tail))) 
     end 

Lexing.lexeme lexbuf là những gì bạn cần. Các phần khác không cần thiết nhưng hữu ích. ruleTail sẽ đồng bộ tất cả các mã còn lại thành chuỗi để người dùng dễ dàng định vị vị trí lỗi. lexbuf.Lexing.lex_curr_p phải được cập nhật trong lexer để chứa các vị trí chính xác. (source)

+0

Câu trả lời hay. Tôi có một câu hỏi, mặc dù: tại sao chúng ta phải sử dụng 'lexbuf.Lexing.lex_curr_p' thay vì' lexbuf.lex_curr_p'? – GiantSquid

+0

Vì 'lex_curr_p' thuộc về mô-đun 'Lexing'. Hoặc mở nó hoặc chờ cho đến khi OCaml trở nên khôn ngoan hơn và hiểu được các tham chiếu trường không đủ tiêu chuẩn. – ygrek

+2

Nơi nào bạn tìm thấy Sql_lexer. và Lỗi? –

2

Tôi nghĩ rằng, tương tự như yacc, các mã thông báo được lưu trữ trong các biến tương ứng với các ký hiệu trong quy tắc ngữ pháp của bạn. Ở đây vì có một biểu tượng (lỗi), bạn có thể chỉ cần đầu ra $ 1 bằng cách sử dụng printf, v.v.

Chỉnh sửa: trả lời nhận xét.

Tại sao bạn sử dụng thiết bị đầu cuối lỗi? Tôi đang đọc một hướng dẫn ocamlyacc nói rằng một thói quen xử lý lỗi đặc biệt được gọi khi một lỗi phân tích cú pháp xảy ra. Cũng giống như vậy:

3.1.5. The Error Reporting Routine

When ther parser function detects a syntax error, it calls a function named parse_error with the string "syntax error" as argument. The default parse_error function does nothing and returns, thus initiating error recovery (see Error Recovery). The user can define a customized parse_error function in the header section of the grammar file such as:

let parse_error s = (* Called by the parser function on error *) 
    print_endline s; 
    flush stdout 

Vâng, có vẻ như bạn chỉ nhận được "lỗi cú pháp" với chức năng mặc dù. Hãy theo dõi để biết thêm.

+1

Thật không may, điều đó không làm việc: File "parser.mly", dòng 372: $ 1 đề cập đến thiết bị đầu cuối ' lỗi ', không có đối số –

+1

Bạn có thể chỉ cho tôi mã cho toàn bộ chức năng không? Tôi có thể cung cấp cái nhìn sâu sắc hơn sau đó. – danben

19

Cách tốt nhất để gỡ lỗi ocamlyacc phân tích cú pháp của bạn là để thiết lập các OCAMLRUNPARAM param để bao gồm các nhân vật p - điều này sẽ làm cho in phân tích cú pháp tất cả các bang mà nó đi qua, và mỗi ca/​​giảm nó thực hiện.

Nếu bạn đang sử dụng bash, bạn có thể làm điều này với lệnh sau:

$ export OCAMLRUNPARAM='p' 
Các vấn đề liên quan