2009-12-19 48 views
15

我正在使用ocamlyacc和ocamllex。我的語法錯誤生成了一個自定義異常。到目前爲止,我可以得到它報告的錯誤位置:ocamlyacc解析錯誤:什麼標記?

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

但是,我也想知道哪個令牌被讀取。必須有一種方法---任何人都知道?

謝謝。

回答

14

令牌是由詞法分析器生成的,因此,當發生錯誤時,你可以使用目前的詞法記號:

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是你所需要的。其他部分不是必需的,但有用。 ruleTail會將所有剩餘的令牌連接成字符串,以便用戶輕鬆找到錯誤位置。應在詞法分析器中更新lexbuf.Lexing.lex_curr_p以包含正確的位置。 (source

+0

很棒的回答。但我有一個問題:爲什麼我們必須使用'lexbuf.Lexing.lex_curr_p'而不是'lexbuf.lex_curr_p'? – GiantSquid 2014-03-13 11:37:50

+0

因爲'lex_curr_p'屬於'Lexing'模塊。要麼打開它,要麼等到OCaml變得明智並理解不合格的記錄字段引用。 – ygrek 2014-03-14 10:17:36

+2

你在哪裏找到Sql_lexer。和錯誤? – 2014-06-24 03:49:36

2

我認爲,與yacc類似,令牌存儲在與語法規則中的符號相對應的變量中。由於有一個符號(錯誤),因此您可以使用printf等簡單輸出$ 1。

編輯:回覆評論。

爲什麼使用錯誤終端?我正在閱讀一個ocamlyacc教程,它說當發生解析錯誤時會調用一個特殊的錯誤處理例程。像這樣:

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 

嗯,貌似你只與功能得到「語法錯誤」雖然。敬請期待更多的信息。

+1

不幸的是,這並不工作: 文件 「parser.mly」,行372:$ 1指的是終端'

如果你正在使用bash,你可以用下面的命令來執行此錯誤',它沒有參數 – 2009-12-19 15:45:49

+1

你能告訴我整個函數的代碼嗎?那麼我可能會提供更多的見解。 – danben 2009-12-19 16:28:10

19

調試你的ocamlyacc解析器,最好的辦法是設置OCAMLRUNPARAM參數去包含字符p - 這會讓解析器打印所有的州,它經歷,和每個班次/減少它執行。

$ export OCAMLRUNPARAM='p' 
相關問題