2010-03-24 48 views
3

我正在做一個在ocaml中編寫玩具編譯器的實驗。目前,我正在嘗試爲我的詞法分析器實現offside rule。不過,我在ocaml語法方面遇到了一些麻煩(編譯器錯誤非常無法提供信息)。下面的代碼(它的33行)會導致第34行的錯誤超出源代碼的末尾。我不確定是什麼導致了這個錯誤。程序結束後的語法錯誤

open Printf 

let s = (Stack.create():int Stack.t); 

let rec check x = 
    (
     if Stack.is_empty s then 
      Stack.push x s 
     else if Stack.top s < x then 
      (
       Stack.push x s; 
       printf "INDENT\n"; 
      ) 
     else if Stack.top s > x then 
      (
       printf "DEDENT\n"; 
       Stack.pop s; 
       check x; 
      ) 
     else 
      printf "MATCHED\n"; 
    ); 

let main() = 
    (
     check 0; 
     check 4; 
     check 6; 
     check 8; 
     check 5; 
    ); 

let _ = Printexc.print main() 

ocaml的輸出:

File "lexer.ml", line 34, characters 0-0: 
Error: Syntax error 

有人可以幫助我的工作出了什麼錯誤是由引起的,幫助我對我的方式來修復它?

回答

9

尾隨;主要定義,檢查s是錯誤的。

代替這3次出現;;如下:

let s = (Stack.create():int Stack.t);; 

let rec check x = 
    (
     (* ...sequence of imperative statements... *) 
);; 

let main() = 
    (
     (* ...sequence of imperative statements... *) 
);; 


;是在下列情況下使用:

  • 測序命令語句
  • 作爲
  • 作爲
  • 作爲記錄字段之間的隔板陣列元件之間的隔板的列表元素之間的隔板


一些例子:

let hello_world1() = 
    print_endline "Hello"; 
    print_endline "World !" 
;; 

let hello_world2() = 
    begin 
    print_endline "Hello"; 
    print_endline "World !" 
    end 
;; 

let hello_world3() = 
    (
    print_endline "Hello"; 
    print_endline "World !"; 
) 
;; 

let some_list = 
    [1; 2; 3] 
;; 

let some_array = 
    [| 'a'; 'b'; 'c' |] 
;; 

type my_process = 
    { 
    pid: int; 
    executable_path: string; 
    } 
;; 

let p1 = { pid = 142; executable_path = "./my_exec" };; 
+0

感謝的是,也爲清理對我來說,我應該/不應該使用單一的半-結腸。 –

+3

雖然在這種情況下,所有這些雙分號都是可選的,因爲您的文件全是定義。只有當你在頂層有一個裸露的聲明時,你是否需要在它之前有一個雙分號 – newacct

+1

我仍然喜歡使用double-semis作爲noob示例,否則它可能會令人困惑。 OCaml的分號規則很容易成爲IMO語言中最混亂的部分,其次是slashdot操作符。 – Chuck

2

剛取出;作品:

open Printf 

let (s:int Stack.t) = Stack.create() 

let rec check x = 
    (
     if Stack.is_empty s then 
      Stack.push x s 
     else if Stack.top s < x then 
      (
       Stack.push x s; 
       printf "INDENT\n"; 
      ) 
     else if Stack.top s > x then 
      (
       printf "DEDENT\n"; 
       Stack.pop s; 
       check x; 
      ) 
     else 
      printf "MATCHED\n"; 
    ) 

let main() = 
    (
     check 0; 
     check 4; 
     check 6; 
     check 8; 
     check 5; 
    ) 

let _ = 
    Printexc.print main() 

運行它:

[email protected]:~/Projects/TestCase$ ./lexer 
INDENT 
INDENT 
INDENT 
DEDENT 
DEDENT 
INDENT 
+0

你怎麼能不提你的博客文章的主題? (我肯定是迴應這個,不是嗎?)http://gaiustech.wordpress.com/2010/09/20/ocaml-compiler-errors/ – nlucaroni

+0

其實我在研究那篇文章時發現了這個問題:-) – Gaius