2010-03-24 7 views
3

J'expérimente l'écriture d'un compilateur de jouets en ocaml. Actuellement, j'essaye d'implémenter le offside rule pour mon lexer. Cependant, j'ai quelques problèmes avec la syntaxe ocaml (les erreurs du compilateur sont extrêmement informatives). Le code ci-dessous (33 lignes) provoque une erreur sur la ligne 34, au-delà de la fin du code source. Je ne suis pas sûr de ce qui cause cette erreur.Erreur de syntaxe au-delà de la fin du programme

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() 

sortie Ocaml:

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

quelqu'un peut me aider travailler à ce que l'erreur est causée par et me aider sur le chemin de la fixer?

Répondre

9

La fin ; après les définitions des principale, contrôle et s sont erronés.

Remplacez ces 3 occurrences par ;; comme suit:

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

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

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


; est utilisé dans les cas suivants:

  • à la séquence des états impératives
  • comme séparateur entre les éléments de la liste
  • comme séparateur entre les éléments de réseau
  • comme séparateur entre les champs d'enregistrement


Quelques exemples:

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

Merci pour cela, et aussi pour éclaircir pour moi où je/ne devrais pas utiliser la seule demi -côlon. –

+3

Bien que dans ce cas particulier, tous ces doubles-points-virgules sont facultatifs, puisque votre fichier est constitué de toutes les définitions. Seulement quand vous avez une simple déclaration au plus haut niveau, êtes-vous obligé d'avoir un double-point-virgule avant le – newacct

+1

J'aime quand même utiliser les doubles-semis pour les exemples noob car sinon cela peut être déroutant. Les règles point-virgule d'OCaml sont facilement la partie la plus confuse du langage IMO, suivi par les opérateurs slashdot. – Chuck

2

Juste enlever les ; œuvres:

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() 

Son exécution:

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

Comment ne pas mentionner votre article de blog sur le sujet? (Je suis sûr en réponse à cela, non?) Http://gaiustech.wordpress.com/2010/09/20/ocaml-compiler-errors/ – nlucaroni

+0

En fait, j'ai trouvé cette question en recherchant ce post :-) – Gaius