2009-12-19 5 views
15

ocamlyacc 및 ocamllex를 사용하고 있습니다. 내 문법에 오류 생성이있어 사용자 지정 예외가 발생했습니다. 지금까지 오류 위치를보고 할 수 있습니다.ocamlyacc 구문 분석 오류 : 어떤 토큰입니까?

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

그러나 어떤 토큰을 읽었는지 알고 싶습니다. 방법이 있어야합니다 --- 누구든지 알고 있습니까?

감사합니다.

답변

14

토큰은 에러가 발생했을 경우에 따라서는 현재 렉서 토큰을 사용할 수 있습니다, 렉서에 의해 생성됩니다

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 당신이 필요합니다. 다른 부분은 필요하지 않지만 유용합니다. ruleTail은 나머지 모든 토큰을 문자열로 연결하여 사용자가 오류 위치를 쉽게 찾을 수있게합니다. lexbuf.Lexing.lex_curr_p은 올바른 위치를 포함하도록 렉서에서 업데이트되어야합니다. 이 그것을 통과하는 파서 인쇄 모든 상태를 만들 것이다, 각 이동은 /는 수행 감소 - (source)

+0

좋은 답변입니다. 나는 하나의 질문을 가지고있다 : 왜 우리는'lexbuf.lex_curr_p' 대신에'lexbuf.Lexing.lex_curr_p'를 사용해야합니까? – GiantSquid

+0

'lex_curr_p'는'Lexing' 모듈에 속하기 때문에. OCaml을 열거 나 OCaml이 현명해질 때까지 기다리거나 부적합한 레코드 필드 참조를 이해하십시오. – ygrek

+2

Sql_lexer는 어디서 찾을 수 있습니까? 및 오류? –

2

yacc와 마찬가지로 토큰은 문법 규칙의 기호에 해당하는 변수에 저장되어 있다고 생각합니다. 여기에는 하나의 기호 (오류)가 있기 때문에 printf 등을 사용하여 $ 1을 출력 할 수 있습니다.

편집 : 댓글에 응답.

왜 오류 터미널을 사용합니까? 구문 오류가 발생할 때 특별한 오류 처리 루틴이 호출된다고 말하는 ocamlyacc 자습서를 읽었습니다. 그래서 같이 :

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 

글쎄, 당신은 비록 그 기능을 "구문 오류"를 얻을 것 같습니다. 더 많은 정보를 위해 계속 지켜봐주십시오.

+1

작동하지 않습니다 : 당신이 떠들썩한 파티를 사용하는 경우

, 당신은 다음 명령을 사용하여이 작업을 수행 할 수 있습니다 오류 ', 인수가 없음 –

+1

전체 기능 코드를 보여줄 수 있습니까? 그러면 더 많은 통찰력을 제공 할 수있을 것입니다. – danben

19

당신의 ocamlyacc 파서를 디버깅하는 가장 좋은 방법은 문자 p을 포함하도록 OCAMLRUNPARAM PARAM을 설정하는 것입니다. $ (1)`단자에 의미 : 라인 372은 "parser.mly" 파일 : 불행하게도

$ export OCAMLRUNPARAM='p'