ParserErr生成"索引越界异常"

时间:2018-05-08 07:35:11

标签: parsing ocaml menhir

我正在创建一个编译器,并试图从解析器中提取行信息。我希望将它作为元数据附加到AST节点,以便可以轻松报告以后的任何错误。我成功地使用以下方法提取了Lexer中的行信息:

exception LexErr of string
exception ParseErr of string

let error msg start finish  = 
    Printf.sprintf "(line %d: char %d..%d): %s" start.pos_lnum 
      (start.pos_cnum -start.pos_bol) (finish.pos_cnum - finish.pos_bol) msg

let lex_error lexbuf = 
    raise ( LexErr (error (lexeme lexbuf) (lexeme_start_p lexbuf) (lexeme_end_p lexbuf)))

在以这种方式使用它之后,这将完美地生成Lexer的行号,字符编号:

rule read = parse
(* Lexing tokens *)
| _ { lex_error lexbuf }

对于解析器,我使用的是这个方法:

exception LexErr of string
exception ParseErr of string

let error msg start finish = 
    Printf.sprintf "(line %d: char %d..%d): %s" start.pos_lnum 
      (start.pos_cnum -start.pos_bol) (finish.pos_cnum - finish.pos_bol) msg

let parse_error msg nterm =
    raise (ParseErr (error msg (rhs_start_pos nterm) (rhs_end_pos nterm)))

我的解析器看起来像这样:

%start <Ast.stmt> program

%%

program:
  | s = stmt; EOF { s }
  ;

stmt:
  | TINT; e = expr { Decl(e) }
  | e1 = expr; EQUALS; e2 = expr { Assign(e1,e2) }
  | error             { parse_error "wsorword" 1 }
  ;

expr:
  | i = INT; { Const i }
  | x = ID { Var x }
  | e1 = expr; b = binop; e2 = expr; { Binop(e1,b,e2) }
  ;

binop:
  | SUM { Sum }
  | SUB { Sub }
  | MUL { Mul }
  | DIV { Div }
  ;

运行此命令时,如果检测到解析器错误,则会抛出invalid_argument&#34; Index out of bounds&#34;例外。这是在raise (ParseErr (error msg (rhs_start_pos nterm) (rhs_end_pos nterm)))行检测到的。我最终想创建一个AST节点,它包含这个解析器行信息作为它的元数据但不能通过这个例外。我不确定我的实施方法是否错误,或者我是否犯了其他错误。会对此有所帮助。

1 个答案:

答案 0 :(得分:1)

函数rhs_start_pos nth不能与menhir解析器一起使用;在这种情况下,您应该使用$symbolstartpos$startpos

同样,e = expr对ocamlyacc无效。

因此,我不确定您尝试使用哪个解析器生成器。