2009-12-19 10 views
15

Estoy usando ocamlyacc y ocamllex. Tengo una producción de error en mi gramática que señala una excepción personalizada. Hasta el momento, puedo conseguirlo para informar de la posición del error:error de análisis de ocamlyacc: ¿qué token?

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

Pero, también quiero saber qué símbolo fue leído. Debe haber una manera --- ¿alguien sabe?

Gracias.

Respuesta

14

tokens son generados por lexer, por lo tanto, se puede utilizar el símbolo de léxico corriente cuando se produce un error:

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 es lo que necesita. Otras partes no son necesarias pero útiles. ruleTail convertirá todos los tokens restantes en cadenas para que el usuario localice fácilmente la posición de error. lexbuf.Lexing.lex_curr_p debe actualizarse en el lector para que contenga las posiciones correctas. (source)

+0

Gran respuesta. Sin embargo, tengo una pregunta: ¿por qué tenemos que usar 'lexbuf.Lexing.lex_curr_p' en lugar de' lexbuf.lex_curr_p'? – GiantSquid

+0

Porque 'lex_curr_p' pertenece al módulo' Lexing'. O ábralo o espere hasta que OCaml se vuelva más inteligente y comprenda referencias de campo de registro no calificadas. – ygrek

+2

¿Dónde encuentras Sql_lexer? y error? –

2

Creo que, al igual que yacc, los tokens se almacenan en las variables correspondientes a los símbolos en su regla de gramática. Aquí ya que hay un símbolo (error), puede simplemente generar $ 1 usando printf, etc.

Editar: responder al comentario.

¿Por qué utiliza un terminal de error? Estoy leyendo un tutorial ocamlyacc que dice que se llama a una rutina especial de manejo de errores cuando ocurre un error de análisis. De este modo:

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 

Bueno, parece que sólo recibe "error de sintaxis" con esa función sin embargo. Estén atentos para más información.

+1

Por desgracia, que no funciona: Archivo "parser.mly", línea 372: $ 1 se refiere al terminal ' error ', que no tiene argumento –

+1

¿Puede mostrarme el código para toda la función? Es posible que pueda ofrecer más información a continuación. – danben

19

La mejor manera de depurar su ocamlyacc analizador es establecer el parámetro OCAMLRUNPARAM para incluir el carácter p - esto hará que el analizador de impresión todos los estados que se aprueba, y cada desplazamiento/reducción se lleva a cabo.

Si está utilizando bash, puede hacerlo con el siguiente comando:

$ export OCAMLRUNPARAM='p' 
Cuestiones relacionadas