e0/lib/parse.ml
Michael Zhang 4ea1071ca1
a
2022-03-23 01:12:37 -05:00

40 lines
1.4 KiB
OCaml

open Util
module I = Parser.MenhirInterpreter
let get_parse_error env =
match I.stack env with
| (lazy Nil) -> "Invalid syntax"
| (lazy (Cons (I.Element (state, _, _, _), _))) -> (
try Parser_messages.message (I.number state)
with Not_found -> "invalid syntax (no specific message for this eror)")
let rec parse lexbuf (checkpoint : Ast.program I.checkpoint) =
match checkpoint with
| I.InputNeeded _env ->
let token = Lexer.f lexbuf in
let startp = lexbuf.lex_start_p and endp = lexbuf.lex_curr_p in
let checkpoint = I.offer checkpoint (token, startp, endp) in
parse lexbuf checkpoint
| I.Shifting _ | I.AboutToReduce _ ->
let checkpoint = I.resume checkpoint in
parse lexbuf checkpoint
| I.HandlingError _env ->
let line, pos = Util.get_lexing_position lexbuf in
let err = get_parse_error _env in
raise (Syntax_error (Some (line, pos), err))
| I.Accepted v -> v
| I.Rejected ->
raise (Syntax_error (None, "invalid syntax (parser rejected the input)"))
let try_parse lexbuf =
try
let program = parse lexbuf (Parser.Incremental.program lexbuf.lex_curr_p) in
Ok program
with Util.Syntax_error (pos, err) -> (
match pos with
| Some (line, pos) ->
Error
(Printf.sprintf "Syntax error on line %d, character %d: %s" line pos
err)
| None -> Error (Printf.sprintf "Syntax error: %s" err))