2011-03-27 22 views
5

我在這裏結束了我的繩索。我無法在ocamllex中獲得任何工作,並且這讓我瘋狂。這是我的.mll文件:OCaml lex:根本不工作,無論如何

{ 

open Parser 

} 

rule next = parse 
    | (['a'-'z'] ['a'-'z']*) as id { Identifier id } 
    | '=' { EqualsSign } 
    | ';' { Semicolon } 
    | '\n' | ' ' { next lexbuf } 
    | eof { EOF } 

下面是我通過在輸入該文件的內容:

a=b; 

然而,當我編譯和運行的東西,我就非常得到一個錯誤第一個字符,說這是無效的。我真的不知道發生了什麼事情,而Google根本沒有幫助我。這怎麼可能呢?正如你所看到的,我真的很難過。

編輯:

我工作了這麼久,我放棄瞭解析器。現在這是我的主文件中的相關代碼:

let parse_file filename = 
    let l = Lexing.from_channel (open_in filename) in 
    try 
     Lexer.next l;() 
    with 
     | Failure msg -> 
     printf "line: %d, col: %d\n" l.lex_curr_p.pos_lnum l.lex_curr_p.pos_cnum 

打印出「line:1,col:1」。

+0

你能否提供你定義構造函數如標識符的ML文件?另外,你能否確認ocamllex和ocamlc在編譯時沒有投訴? – Surikator 2011-03-27 14:34:12

+0

它們在parser.mly中被定義爲標準,並且都沒有抱怨。 – marsolk 2011-03-27 17:29:10

+1

@marsolk:我很好奇 - 你有沒有想過這個?有什麼問題? – lebowski 2017-02-17 17:11:34

回答

10

沒有相應的ocamlyacc解析器,沒有人能夠找到你的代碼的問題,因爲你的詞法分析器工作得很好!

我冒昧地編寫了構造一系列標識符對的例如下面的小解析器(parser.mly),例如,輸入「a = b;」應該給單身人士名單[(「a」,「b」)]。

%{%} 

%token <string> Identifier 
%token EqualsSign 
%token Semicolon 
%token EOF 

%start start 
%type <(string * string) list> start 

%% 

start: 
| EOF {[]} 
| Identifier EqualsSign Identifier Semicolon start {($1, $3) :: $5} 
; 

%% 

爲了測試解析器是否做什麼,我答應了,我們創建另一個文件(main.ml),其解析字符串「A = B」;並打印結果。

let print_list = List.iter (fun (a, b) -> Printf.printf "%s = %s;\n" a b) 
let() = print_list (Parser.start Lexer.next (Lexing.from_string "a=b;")) 

代碼應編譯(例如ocamlbuild main.byte),不含任何投訴和程序應輸出 「A = B;」按照承諾。


針對最新編輯:

一般情況下,我不相信捕標準庫例外是爲了表明故障或誤操作(如Invalid_argument或失敗)是一個好主意。原因在於它們在整個庫中無處不在,因此通常無法確定哪個函數會引發異常,以及它爲什麼會這樣做。

此外,你扔掉唯一有用的信息:錯誤信息!錯誤消息應該告訴你問題的根源是什麼(我最好猜測是與IO相關的問題)。因此,您應該打印錯誤消息或讓異常傳播到頂層。就個人而言,我更喜歡後者的選擇。

但是,您可能仍然想要以優雅的方式處理語法錯誤的輸入。爲此,您可以在詞法分析器中定義一個新的異常並添加一個捕獲無效令牌的默認情況。現在

{ 
    exception Unexpected_token 
} 
... 
| _ {raise Unexpected_token} 

,你可以趕上新定義的例外在主文件,不像以前,例外是特定於語法上是無效的投入。因此,你知道異常的來源和原因,讓你有機會做比以前更有意義的事情。如果您在啓用了調試信息的情況下編譯程序,將環境變量OCAMLRUNPARAM設置爲「b」(例如,導出OCAMLRUNPARAM = b)將爲未捕獲的異常啓用堆棧跟蹤!

+1

我想我應該提到,經過這麼長時間,我現在只是在沒有解析器的情況下測試它,它仍然給我這個錯誤。我將使用我的主文件中的代碼編輯帖子。 – marsolk 2011-03-27 17:22:44

+0

通常情況下,我不會;在這種情況下,我得到了'失敗(「lexing:空令牌」)',我擡頭看它意味着它看到的字符與詞法分析器中的任何內容都不相符。最後,我提出另一個規則:'| _ as c {Printf.printf「無法識別的字符:%c \ n」c; raise(Failure「」)}' ,現在它打印「無法識別的字符:a」。但是,我會嘗試使用調試信息來查看發生了什麼。 – marsolk 2011-03-27 18:50:55

6

btw。 ocamllex也可以爲正則表達式「一個或多個」做+運營商,所以這

['a'-'z']+ 

相當於你

['a'-'z']['a'-'z']* 
1

我只是用同樣的事情掙扎(這是我如何發現這個問題),直到最終意識到我錯誤地指定了輸入文件的路徑爲Sys.argv.(0)而不是Sys.argv.(1)! LOL

我真的希望它有幫助! :)

-1

它看起來像在標識符的正則表達式中有一個空格。這可以防止詞法分析器識別a = b,儘管它仍然可以識別a = b;