2009-09-18 4 views
4

J'ai un analyseur et un lexer écrits en ocamlyacc et ocamllex. Si le fichier à analyser s'arrête prématurément, comme dans l'oubli d'un point-virgule à la fin d'une ligne, l'application ne déclenche pas d'erreur de syntaxe. Je me rends compte que c'est parce que je soulève et attrape EOF et que cela fait de la lexeur ignorer la règle inachevée, mais comment devrait je fais ceci pour soulever une erreur de syntaxe?Parser/Lexer ignorant les règles de grammaire incomplètes

Voici mon analyseur (simplifié),

%{ 
    let parse_error s = Printf.ksprinf failwith "ERROR: %s" s 
%} 

%token COLON 
%token SEPARATOR 
%token SEMICOLON 
%token <string> FLOAT 
%token <string> INT 
%token <string> LABEL 

%type <Conf.config> command 
%start command 
%% 
    command: 
     | label SEPARATOR data SEMICOLON { Conf.Pair ($1,$3)  } 
     | label SEPARATOR data_list   { Conf.List ($1,$3)  } 
     | label SEMICOLON     { Conf.Single ($1)  } 
    label : 
     | LABEL        { Conf.Label $1   } 
    data : 
     | label        { $1     } 
     | INT        { Conf.Integer $1  } 
     | FLOAT        { Conf.Float $1   } 
    data_list : 
     | star_data COMMA star_data data_list_ending 
              { $1 :: $3 :: $4  } 
    data_list_ending: 
     | COMMA star_data data_list_ending { $2 :: $3    } 
     | SEMICOLON       { []     } 

et lexxer (simplifié),

{ 
    open ConfParser 
    exception Eof 
} 

rule token = parse 
    | ['\t' ' ' '\n' '\010' '\013' '\012'] 
         { token lexbuf } 
    | ['0'-'9']+ ['.'] ['0'-'9']* ('e' ['-' '+']? ['0'-'9']+)? as n 
         { FLOAT n  } 
    | ['0'-'9']+ as n { INT n   } 
    | '#'    { comment lexbuf } 
    | ';'    { SEMICOLON  } 
    | ['=' ':']   { SEPARATOR  } 
    | ','    { COMMA   } 
    | ['_' 'a'-'z' 'A'-'Z']([' ']?['a'-'z' 'A'-'Z' '0'-'9' '_' '-' '.'])* as w 
         { LABEL w  } 
    | eof    { raise Eof  } 

and comment = parse 
    | ['#' '\n']  { token lexbuf } 
    | _     { comment lexbuf } 

exemple de fichier d'entrée,

one = two, three, one-hundred; 
single label; 
list : command, missing, a, semicolon 

Une solution, est d'ajouter un appel récursif dans la règle de commande à lui-même à la fin, et en ajoutant une règle vide, qui tous construisent une liste pour retourner à le programme principal. Je pense que peut-être interpréter Eof comme une attente, et la condition de fin, plutôt qu'une erreur dans le lexer, est-ce correct?

Répondre

5

ocamlyacc ne consomme pas nécessairement toute l'entrée. Si vous voulez forcer l'échec si l'entrée entière n'est pas analysable, vous devez faire correspondre EOF dans votre grammaire. Au lieu d'augmenter Eof en vous lexer, ajoutez un jeton EOF et changer votre symbole start à

%type <Conf.config list> main 

main: 
    EOF { [] } 
    | command main { $1::$2 } 
+0

Oui, c'est la solution. Je jouais avec ne pas élever un EOF et construire une liste dans ma grammaire, mais vous avez raison. Merci Chris. – nlucaroni

Questions connexes