Merge branch 'rinderknecht-dev' into 'dev'

Adding to the infrastructure for using the incremental API of Menhir

See merge request ligolang/ligo!277
This commit is contained in:
Christian Rinderknecht 2020-01-04 17:35:53 +00:00
commit 357d83283f
34 changed files with 2464 additions and 482 deletions

13
src/passes/1-parser/cameligo/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
_build/*
*/_build
*~
.merlin
*/.merlin
*.install
/Version.ml
/dune-project
/Parser.mli
/Parser.ml
/Lexer.ml
/LexToken.ml
/Tests

View File

@ -201,7 +201,7 @@ let to_lexeme = function
| Int i | Int i
| Nat i | Nat i
| Mutez i -> fst i.Region.value | Mutez i -> fst i.Region.value
| String s -> s.Region.value | String s -> String.escaped s.Region.value
| Bytes b -> fst b.Region.value | Bytes b -> fst b.Region.value
| Begin _ -> "begin" | Begin _ -> "begin"

View File

@ -0,0 +1,416 @@
(* This file was auto-generated based on "Parser.msg". *)
(* Please note that the function [message] can raise [Not_found]. *)
let message =
fun s ->
match s with
| 0 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 1 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 2 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 3 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 4 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 5 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 7 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 49 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 51 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 52 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 53 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 18 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 8 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 9 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 10 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 42 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 43 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 46 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 47 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 33 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 460 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 27 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 31 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 28 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 35 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 12 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 16 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 6 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 13 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 61 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 133 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 373 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 375 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 134 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 136 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 137 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 153 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 374 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 63 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 142 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 143 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 128 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 145 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 72 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 94 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 106 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 95 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 108 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 109 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 110 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 73 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 91 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 93 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 92 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 90 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 77 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 78 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 65 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 66 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 67 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 120 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 121 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 124 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 125 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 147 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 148 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 149 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 157 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 156 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 463 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 465 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 217 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 242 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 219 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 221 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 215 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 226 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 255 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 256 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 243 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 264 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 228 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 257 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 258 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 266 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 268 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 270 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 272 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 274 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 192 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 259 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 285 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 288 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 245 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 293 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 262 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 160 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 164 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 429 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 332 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 313 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 431 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 315 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 316 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 317 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 432 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 445 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 446 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 433 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 434 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 435 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 436 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 437 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 438 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 440 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 328 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 330 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 334 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 331 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 329 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 340 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 341 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 342 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 343 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 344 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 345 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 367 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 346 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 348 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 441 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 443 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 447 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 430 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 312 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 428 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 165 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 167 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 168 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 169 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 163 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 448 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 450 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 451 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 166 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 235 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 236 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 239 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 240 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 425 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 170 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 171 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 172 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 418 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 419 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 422 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 423 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 174 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 304 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 305 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 405 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 412 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 404 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 306 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 308 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 320 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 321 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 322 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 323 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 324 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 325 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 326 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 327 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 378 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 379 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 381 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 335 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 310 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 307 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 395 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 396 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 397 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 398 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 399 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 400 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 408 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 401 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 403 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 175 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 176 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 179 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 180 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 183 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 302 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 300 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 185 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 187 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 188 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 189 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 190 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 195 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 214 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 194 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 210 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| _ ->
raise Not_found

View File

@ -566,6 +566,7 @@ core_expr:
"<int>" { EArith (Int $1) } "<int>" { EArith (Int $1) }
| "<mutez>" { EArith (Mutez $1) } | "<mutez>" { EArith (Mutez $1) }
| "<nat>" { EArith (Nat $1) } | "<nat>" { EArith (Nat $1) }
| "<bytes>" { EBytes $1 }
| "<ident>" | module_field { EVar $1 } | "<ident>" | module_field { EVar $1 }
| projection { EProj $1 } | projection { EProj $1 }
| "<string>" { EString (String $1) } | "<string>" { EString (String $1) }

View File

@ -1,57 +1,82 @@
(** Generic parser for LIGO *) (* Generic parser for LIGO *)
module type PARSER = (* Main functor *)
sig
(* The type of tokens *) module Make (Lexer: Lexer.S with module Token := LexToken)
(Parser: module type of Parser)
type token (ParErr: sig val message : int -> string end) =
struct
(* This exception is raised by the monolithic API functions *) module I = Parser.MenhirInterpreter
module S = MenhirLib.General (* Streams *)
exception Error
(* The call [stack checkpoint] extracts the parser's stack out of
(* The monolithic API *) a checkpoint. *)
val contract : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> AST.t let stack = function
I.HandlingError env -> I.stack env
(* The incremental API *) | _ -> assert false
module MenhirInterpreter : (* The call [state checkpoint] extracts the number of the current
sig state out of a parser checkpoint. *)
include MenhirLib.IncrementalEngine.INCREMENTAL_ENGINE
with type token = token let state checkpoint : int =
end match Lazy.force (stack checkpoint) with
S.Nil -> 0 (* WARNING: Hack. The first state should be 0. *)
module Incremental : | S.Cons (I.Element (s,_,_,_),_) -> I.number s
sig
val contract : Lexing.position -> AST.t MenhirInterpreter.checkpoint (* The parser has successfully produced a semantic value. *)
end
end let success v = v
(* Main functor *) (* The parser has suspended itself because of a syntax error. Stop. *)
module Make (Lexer: Lexer.S) type message = string
(Parser: PARSER with type token = Lexer.Token.token) = type valid = Lexer.token
struct type invalid = Lexer.token
type error = message * valid option * invalid
module I = Parser.MenhirInterpreter
exception Point of error
(* The parser has successfully produced a semantic value. *)
let failure get_win checkpoint =
let success v = v let message = ParErr.message (state checkpoint) in
match get_win () with
(* The parser has suspended itself because of a syntax error. Stop. *) Lexer.Nil -> assert false
| Lexer.One invalid ->
let fail _checkpoint = raise Parser.Error raise (Point (message, None, invalid))
| Lexer.Two (invalid, valid) ->
(* The generic parsing function *) raise (Point (message, Some valid, invalid))
let incr_contract Lexer.{read; buffer; close; _} : AST.t = (* The two Menhir APIs are called from the following two functions. *)
let supplier = I.lexer_lexbuf_to_supplier read buffer in
let parser = Parser.Incremental.contract buffer.Lexing.lex_curr_p in let incr_contract Lexer.{read; buffer; get_win; close; _} : AST.t =
let ast = I.loop_handle success fail supplier parser let supplier = I.lexer_lexbuf_to_supplier read buffer
in close (); ast and failure = failure get_win in
let parser = Parser.Incremental.contract buffer.Lexing.lex_curr_p in
let mono_contract = Parser.contract let ast = I.loop_handle success failure supplier parser
in close (); ast
end
let mono_contract = Parser.contract
(* Errors *)
let format_error ?(offsets=true) mode (msg, valid_opt, invalid) =
let invalid_region = LexToken.to_region invalid in
let header =
"Parse error " ^ invalid_region#to_string ~offsets mode in
let trailer =
match valid_opt with
None ->
if LexToken.is_eof invalid then ""
else let invalid_lexeme = LexToken.to_lexeme invalid in
Printf.sprintf ", before \"%s\"" invalid_lexeme
| Some valid ->
let valid_lexeme = LexToken.to_lexeme valid in
let s = Printf.sprintf ", after \"%s\"" valid_lexeme in
if LexToken.is_eof invalid then s
else
let invalid_lexeme = LexToken.to_lexeme invalid in
Printf.sprintf "%s and before \"%s\"" s invalid_lexeme in
let header = header ^ trailer in
header ^ (if msg = "" then ".\n" else ":\n" ^ msg)
end

View File

@ -1,39 +1,22 @@
(** Generic parser API for LIGO *) (** Generic parser API for LIGO *)
module type PARSER = module Make (Lexer: Lexer.S with module Token := LexToken)
(Parser: module type of Parser)
(ParErr: sig val message: int -> string end) :
sig sig
(* The type of tokens *) (* Monolithic and incremental APIs of Menhir for parsing *)
type token
(* This exception is raised by the monolithic API functions *)
exception Error
(* The monolithic API *)
val contract : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> AST.t
(* The incremental API *)
module MenhirInterpreter :
sig
include MenhirLib.IncrementalEngine.INCREMENTAL_ENGINE
with type token = token
end
module Incremental :
sig
val contract : Lexing.position -> AST.t MenhirInterpreter.checkpoint
end
end
(* Main functor *)
module Make (Lexer: Lexer.S)
(Parser: PARSER with type token = Lexer.Token.token) :
sig
val mono_contract : (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> AST.t val mono_contract : (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> AST.t
val incr_contract : Lexer.instance -> AST.t val incr_contract : Lexer.instance -> AST.t
(* Error handling *)
type message = string
type valid = Lexer.token
type invalid = Lexer.token
type error = message * valid option * invalid
exception Point of error
val format_error : ?offsets:bool -> [`Byte | `Point] -> error -> string
end end

View File

@ -1,16 +1,14 @@
(** Driver for the parser of CameLIGO *) (** Driver for the CameLIGO parser *)
let extension = ".mligo" let extension = ".mligo"
let options = EvalOpt.read "CameLIGO" extension let options = EvalOpt.read "CameLIGO" extension
open Printf
(** Error printing and exception tracing (** Error printing and exception tracing
*) *)
let () = Printexc.record_backtrace true let () = Printexc.record_backtrace true
(** Auxiliary functions
*)
let sprintf = Printf.sprintf
(** Extracting the input file (** Extracting the input file
*) *)
let file = let file =
@ -23,17 +21,7 @@ let file =
let () = Printexc.record_backtrace true let () = Printexc.record_backtrace true
let external_ text = let external_ text =
Utils.highlight (Printf.sprintf "External error: %s" text); exit 1;; Utils.highlight (sprintf "External error: %s" text); exit 1;;
type error = SyntaxError
let error_to_string = function
SyntaxError -> "Syntax error.\n"
let print_error ?(offsets=true) mode Region.{region; value} ~file =
let msg = error_to_string value
and reg = region#to_string ~file ~offsets mode in
Utils.highlight (sprintf "Parse error %s:\n%s%!" reg msg)
(** {1 Preprocessing the input source and opening the input channels} *) (** {1 Preprocessing the input source and opening the input channels} *)
@ -42,7 +30,7 @@ let print_error ?(offsets=true) mode Region.{region; value} ~file =
let lib_path = let lib_path =
match options#libs with match options#libs with
[] -> "" [] -> ""
| libs -> let mk_I dir path = Printf.sprintf " -I %s%s" dir path | libs -> let mk_I dir path = sprintf " -I %s%s" dir path
in List.fold_right mk_I libs "" in List.fold_right mk_I libs ""
let prefix = let prefix =
@ -61,26 +49,26 @@ let pp_input =
let cpp_cmd = let cpp_cmd =
match options#input with match options#input with
None | Some "-" -> None | Some "-" ->
Printf.sprintf "cpp -traditional-cpp%s - > %s" sprintf "cpp -traditional-cpp%s - > %s"
lib_path pp_input lib_path pp_input
| Some file -> | Some file ->
Printf.sprintf "cpp -traditional-cpp%s %s > %s" sprintf "cpp -traditional-cpp%s %s > %s"
lib_path file pp_input lib_path file pp_input
let () = let () =
if Utils.String.Set.mem "cpp" options#verbose if Utils.String.Set.mem "cpp" options#verbose
then Printf.eprintf "%s\n%!" cpp_cmd; then eprintf "%s\n%!" cpp_cmd;
if Sys.command cpp_cmd <> 0 then if Sys.command cpp_cmd <> 0 then
external_ (Printf.sprintf "the command \"%s\" failed." cpp_cmd) external_ (sprintf "the command \"%s\" failed." cpp_cmd)
(** {1 Instanciating the lexer} *) (** {1 Instanciating the lexer} *)
module Lexer = Lexer.Make (LexToken) module Lexer = Lexer.Make (LexToken)
module Log = LexerLog.Make (Lexer) module Log = LexerLog.Make (Lexer)
module ParserFront = ParserAPI.Make (Lexer) (Parser) module ParserFront = ParserAPI.Make (Lexer) (Parser) (ParErr)
let lexer_inst = Lexer.open_token_stream (Some pp_input) let lexer_inst = Lexer.open_token_stream (Some pp_input)
let Lexer.{read; buffer; get_pos; get_last; close} = lexer_inst let Lexer.{read; buffer; get_win; get_pos; get_last; close} = lexer_inst
and cout = stdout and cout = stdout
@ -97,10 +85,10 @@ let tokeniser = read ~log
let () = let () =
try try
(* The incremental API *) let ast =
let ast = ParserFront.incr_contract lexer_inst in if options#mono
(* The monolithic API *) then ParserFront.mono_contract tokeniser buffer
(* let ast = ParserFront.mono_contract tokeniser buffer in *) else ParserFront.incr_contract lexer_inst in
if Utils.String.Set.mem "ast" options#verbose if Utils.String.Set.mem "ast" options#verbose
then let buffer = Buffer.create 131 in then let buffer = Buffer.create 131 in
let state = ParserLog.mk_state let state = ParserLog.mk_state
@ -122,14 +110,36 @@ let () =
Buffer.output_buffer stdout buffer Buffer.output_buffer stdout buffer
end end
with with
(* Lexing errors *)
Lexer.Error err -> Lexer.Error err ->
close_all (); close_all ();
Lexer.print_error ~offsets:options#offsets let msg =
options#mode err ~file Lexer.format_error ~offsets:options#offsets
| Parser.Error -> options#mode err ~file
let region = get_last () in in prerr_string msg
let error = Region.{region; value=SyntaxError} in
(* Incremental API of Menhir *)
| ParserFront.Point point ->
let () = close_all () in let () = close_all () in
print_error ~offsets:options#offsets let error =
options#mode error ~file ParserFront.format_error ~offsets:options#offsets
options#mode point
in eprintf "\027[31m%s\027[0m%!" error
(* Monolithic API of Menhir *)
| Parser.Error ->
let () = close_all () in
let invalid, valid_opt =
match get_win () with
Lexer.Nil ->
assert false (* Safe: There is always at least EOF. *)
| Lexer.One invalid -> invalid, None
| Lexer.Two (invalid, valid) -> invalid, Some valid in
let point = "", valid_opt, invalid in
let error =
ParserFront.format_error ~offsets:options#offsets
options#mode point
in eprintf "\027[31m%s\027[0m%!" error
(* I/O errors *)
| Sys_error msg -> Utils.highlight msg | Sys_error msg -> Utils.highlight msg

View File

@ -1,43 +1,43 @@
(ocamllex LexToken) (ocamllex LexToken)
(menhir (menhir
(merge_into Parser) (merge_into Parser)
(modules ParToken Parser) (modules ParToken Parser)
(flags -la 1 --table --strict --explain --external-tokens LexToken)) (flags -la 1 --table --strict --explain --external-tokens LexToken))
(library (library
(name parser_cameligo) (name parser_cameligo)
(public_name ligo.parser.cameligo) (public_name ligo.parser.cameligo)
(modules AST cameligo Parser ParserLog LexToken) (modules AST cameligo Parser ParserLog LexToken)
(libraries (libraries
menhirLib menhirLib
parser_shared parser_shared
str str
simple-utils simple-utils
tezos-utils tezos-utils
getopt ) getopt )
(preprocess (preprocess
(pps bisect_ppx --conditional) ) (pps bisect_ppx --conditional) )
(flags (:standard -open Simple_utils -open Parser_shared )) (flags (:standard -open Simple_utils -open Parser_shared)))
)
(executable (executable
(name LexerMain) (name LexerMain)
(libraries (libraries parser_cameligo)
parser_cameligo) (modules LexerMain)
(modules
LexerMain)
(preprocess (preprocess
(pps bisect_ppx --conditional)) (pps bisect_ppx --conditional))
(flags (:standard -open Parser_shared -open Parser_cameligo))) (flags (:standard -open Parser_shared -open Parser_cameligo)))
(executable (executable
(name ParserMain) (name ParserMain)
(libraries (libraries parser_cameligo)
parser_cameligo)
(modules (modules
ParserAPI ParErr ParserAPI ParserMain)
ParserMain)
(preprocess (preprocess
(pps bisect_ppx --conditional)) (pps bisect_ppx --conditional))
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo))) (flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo)))
(executable
(name Unlexer)
(libraries str)
(modules Unlexer))

View File

@ -0,0 +1,109 @@
(** Converting the textual representation of tokens produced by Menhir
into concrete syntax *)
(* See [ParToken.mly] *)
let gen_sym prefix =
let count = ref 0 in
fun () -> incr count;
prefix ^ string_of_int !count
let id_sym = gen_sym "id"
and ctor_sym = gen_sym "C"
let concrete = function
(* Keywords *)
| "Begin" -> "begin"
| "Else" -> "else"
| "End" -> "end"
| "False" -> "false"
| "Fun" -> "fun"
| "If" -> "if"
| "In" -> "in"
| "Let" -> "let"
| "Match" -> "match"
| "Mod" -> "mod"
| "Not" -> "not"
| "Of" -> "of"
| "Or" -> "or"
| "Then" -> "then"
| "True" -> "true"
| "Type" -> "type"
| "With" -> "with"
(* Data constructors *)
| "C_None" -> "None"
| "C_Some" -> "Some"
(* Symbols *)
| "MINUS" -> "-"
| "PLUS" -> "+"
| "SLASH" -> "/"
| "TIMES" -> "*"
| "LPAR" -> "("
| "RPAR" -> ")"
| "LBRACKET" -> "["
| "RBRACKET" -> "]"
| "LBRACE" -> "{"
| "RBRACE" -> "}"
| "ARROW" -> "->"
| "CONS" -> "::"
| "CAT" -> "^"
| "DOT" -> "."
| "COMMA" -> ","
| "SEMI" -> ";"
| "COLON" -> ":"
| "VBAR" -> "|"
| "WILD" -> "_"
| "EQ" -> "="
| "NE" -> "<>"
| "LT" -> "<"
| "GT" -> ">"
| "LE" -> "<="
| "GE" -> ">="
| "BOOL_OR" -> "||"
| "BOOL_AND" -> "&&"
(* Literals *)
| "String" -> "\"a string\""
| "Bytes" -> "0xAA"
| "Int" -> "1"
| "Nat" -> "1n"
| "Mutez" -> "1mutez"
| "Ident" -> id_sym ()
| "Constr" -> ctor_sym ()
(* Virtual tokens *)
| "EOF" -> ""
(* For completeness of open sum types *)
| _ -> "<Unknown>"
(* Unlexing a sentence *)
let unlex (sentence: string) : Buffer.t =
let tokens = Str.split (Str.regexp " ") sentence in
let lexemes = List.map concrete tokens in
let buffer = Buffer.create 31 in
let rec trans = function
[] -> ()
| [s] -> Buffer.add_string buffer s
| s::l -> Buffer.add_string buffer (s ^ " "); trans l
in trans lexemes; buffer
(* Reading one line from the standard input channel and unlex it. *)
let out = unlex (input_line stdin) |> Buffer.contents
let () = Printf.printf "%s\n" out

View File

@ -10,3 +10,4 @@ _build/*
/Parser.ml /Parser.ml
/Lexer.ml /Lexer.ml
/LexToken.ml /LexToken.ml
/Tests

View File

@ -224,7 +224,7 @@ let proj_token = function
let to_lexeme = function let to_lexeme = function
(* Literals *) (* Literals *)
String s -> s.Region.value String s -> String.escaped s.Region.value
| Bytes b -> fst b.Region.value | Bytes b -> fst b.Region.value
| Int i | Int i
| Nat i | Nat i

View File

@ -0,0 +1,514 @@
(* This file was auto-generated based on "Parser.msg". *)
(* Please note that the function [message] can raise [Not_found]. *)
let message =
fun s ->
match s with
| 0 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 1 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 2 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 3 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 25 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 5 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 7 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 8 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 48 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 9 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 10 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 52 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 53 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 56 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 57 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 59 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 11 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 12 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 20 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 21 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 13 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 6 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 61 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 34 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 15 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 64 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 517 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 29 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 32 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 515 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 35 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 26 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 39 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 27 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 18 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 67 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 70 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 71 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 72 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 73 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 80 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 81 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 76 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 77 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 78 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 85 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 86 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 87 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 88 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 512 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 358 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 359 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 499 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 362 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 360 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 361 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 363 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 364 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 365 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 366 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 367 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 475 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 476 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 477 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 478 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 496 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 503 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 502 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 371 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 372 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 373 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 374 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 378 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 380 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 382 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 383 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 387 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 384 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 385 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 389 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 390 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 391 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 393 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 395 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 399 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 396 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 397 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 375 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 381 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 404 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 405 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 406 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 492 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 493 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 494 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 407 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 488 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 408 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 452 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 447 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 453 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 409 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 410 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 416 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 420 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 421 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 411 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 424 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 425 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 426 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 413 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 415 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 435 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 436 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 437 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 440 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 441 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 469 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 470 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 473 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 472 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 438 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 467 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 439 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 69 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 428 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 429 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 430 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 431 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 432 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 508 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 521 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 159 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 523 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 137 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 150 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 166 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 167 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 158 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 173 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 152 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 168 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 169 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 175 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 177 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 179 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 181 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 183 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 160 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 170 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 157 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 163 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 187 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 92 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 318 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 319 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 322 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 323 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 356 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 351 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 353 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 93 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 94 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 338 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 95 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 96 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 342 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 343 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 346 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 347 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 349 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 97 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 136 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 101 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 195 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 196 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 198 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 199 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 202 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 203 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 334 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 329 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 331 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 102 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 103 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 326 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 312 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 314 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 104 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 308 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 306 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 309 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 310 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 304 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 134 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 106 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 296 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 297 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 298 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 299 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 300 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 107 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 108 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 285 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 286 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 132 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 155 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 288 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 291 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 292 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 128 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 110 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 113 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 208 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 209 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 247 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 271 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 248 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 250 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 251 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 272 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 278 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 277 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 281 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 280 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 218 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 261 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 262 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 265 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 266 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 269 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 255 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 257 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 219 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 244 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 245 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 253 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 241 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 210 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 275 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 211 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 223 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 224 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 240 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 225 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 226 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 234 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 114 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 118 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 206 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 119 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 125 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| _ ->
raise Not_found

View File

@ -1,57 +1,82 @@
(** Generic parser for LIGO *) (* Generic parser for LIGO *)
module type PARSER = (* Main functor *)
sig
(* The type of tokens *) module Make (Lexer: Lexer.S with module Token := LexToken)
(Parser: module type of Parser)
type token (ParErr: sig val message : int -> string end) =
struct
(* This exception is raised by the monolithic API functions *) module I = Parser.MenhirInterpreter
module S = MenhirLib.General (* Streams *)
exception Error
(* The call [stack checkpoint] extracts the parser's stack out of
(* The monolithic API *) a checkpoint. *)
val contract : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> AST.t let stack = function
I.HandlingError env -> I.stack env
(* The incremental API *) | _ -> assert false
module MenhirInterpreter : (* The call [state checkpoint] extracts the number of the current
sig state out of a parser checkpoint. *)
include MenhirLib.IncrementalEngine.INCREMENTAL_ENGINE
with type token = token let state checkpoint : int =
end match Lazy.force (stack checkpoint) with
S.Nil -> 0 (* WARNING: Hack. The first state should be 0. *)
module Incremental : | S.Cons (I.Element (s,_,_,_),_) -> I.number s
sig
val contract : Lexing.position -> AST.t MenhirInterpreter.checkpoint (* The parser has successfully produced a semantic value. *)
end
end let success v = v
(* Main functor *) (* The parser has suspended itself because of a syntax error. Stop. *)
module Make (Lexer: Lexer.S) type message = string
(Parser: PARSER with type token = Lexer.Token.token) = type valid = Lexer.token
struct type invalid = Lexer.token
type error = message * valid option * invalid
module I = Parser.MenhirInterpreter
exception Point of error
(* The parser has successfully produced a semantic value. *)
let failure get_win checkpoint =
let success v = v let message = ParErr.message (state checkpoint) in
match get_win () with
(* The parser has suspended itself because of a syntax error. Stop. *) Lexer.Nil -> assert false
| Lexer.One invalid ->
let fail _checkpoint = raise Parser.Error raise (Point (message, None, invalid))
| Lexer.Two (invalid, valid) ->
(* The generic parsing function *) raise (Point (message, Some valid, invalid))
let incr_contract Lexer.{read; buffer; close; _} : AST.t = (* The two Menhir APIs are called from the following two functions. *)
let supplier = I.lexer_lexbuf_to_supplier read buffer in
let parser = Parser.Incremental.contract buffer.Lexing.lex_curr_p in let incr_contract Lexer.{read; buffer; get_win; close; _} : AST.t =
let ast = I.loop_handle success fail supplier parser let supplier = I.lexer_lexbuf_to_supplier read buffer
in close (); ast and failure = failure get_win in
let parser = Parser.Incremental.contract buffer.Lexing.lex_curr_p in
let mono_contract = Parser.contract let ast = I.loop_handle success failure supplier parser
in close (); ast
end
let mono_contract = Parser.contract
(* Errors *)
let format_error ?(offsets=true) mode (msg, valid_opt, invalid) =
let invalid_region = LexToken.to_region invalid in
let header =
"Parse error " ^ invalid_region#to_string ~offsets mode in
let trailer =
match valid_opt with
None ->
if LexToken.is_eof invalid then ""
else let invalid_lexeme = LexToken.to_lexeme invalid in
Printf.sprintf ", before \"%s\"" invalid_lexeme
| Some valid ->
let valid_lexeme = LexToken.to_lexeme valid in
let s = Printf.sprintf ", after \"%s\"" valid_lexeme in
if LexToken.is_eof invalid then s
else
let invalid_lexeme = LexToken.to_lexeme invalid in
Printf.sprintf "%s and before \"%s\"" s invalid_lexeme in
let header = header ^ trailer in
header ^ (if msg = "" then ".\n" else ":\n" ^ msg)
end

View File

@ -1,39 +1,22 @@
(** Generic parser API for LIGO *) (** Generic parser API for LIGO *)
module type PARSER = module Make (Lexer: Lexer.S with module Token := LexToken)
(Parser: module type of Parser)
(ParErr: module type of ParErr) :
sig sig
(* The type of tokens *) (* Monolithic and incremental APIs of Menhir for parsing *)
type token
(* This exception is raised by the monolithic API functions *)
exception Error
(* The monolithic API *)
val contract : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> AST.t
(* The incremental API *)
module MenhirInterpreter :
sig
include MenhirLib.IncrementalEngine.INCREMENTAL_ENGINE
with type token = token
end
module Incremental :
sig
val contract : Lexing.position -> AST.t MenhirInterpreter.checkpoint
end
end
(* Main functor *)
module Make (Lexer: Lexer.S)
(Parser: PARSER with type token = Lexer.Token.token) :
sig
val mono_contract : (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> AST.t val mono_contract : (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> AST.t
val incr_contract : Lexer.instance -> AST.t val incr_contract : Lexer.instance -> AST.t
(* Error handling *)
type message = string
type valid = Lexer.token
type invalid = Lexer.token
type error = message * valid option * invalid
exception Point of error
val format_error : ?offsets:bool -> [`Byte | `Point] -> error -> string
end end

View File

@ -1,16 +1,14 @@
(** Driver for the parser of PascaLIGO *) (** Driver for the PascaLIGO parser *)
let extension = ".ligo" let extension = ".ligo"
let options = EvalOpt.read "PascaLIGO" extension let options = EvalOpt.read "PascaLIGO" extension
open Printf
(** Error printing and exception tracing (** Error printing and exception tracing
*) *)
let () = Printexc.record_backtrace true let () = Printexc.record_backtrace true
(** Auxiliary functions
*)
let sprintf = Printf.sprintf
(** Extracting the input file (** Extracting the input file
*) *)
let file = let file =
@ -23,17 +21,7 @@ let file =
let () = Printexc.record_backtrace true let () = Printexc.record_backtrace true
let external_ text = let external_ text =
Utils.highlight (Printf.sprintf "External error: %s" text); exit 1;; Utils.highlight (sprintf "External error: %s" text); exit 1;;
type error = SyntaxError
let error_to_string = function
SyntaxError -> "Syntax error.\n"
let print_error ?(offsets=true) mode Region.{region; value} ~file =
let msg = error_to_string value
and reg = region#to_string ~file ~offsets mode in
Utils.highlight (sprintf "Parse error %s:\n%s%!" reg msg)
(** {1 Preprocessing the input source and opening the input channels} *) (** {1 Preprocessing the input source and opening the input channels} *)
@ -42,7 +30,7 @@ let print_error ?(offsets=true) mode Region.{region; value} ~file =
let lib_path = let lib_path =
match options#libs with match options#libs with
[] -> "" [] -> ""
| libs -> let mk_I dir path = Printf.sprintf " -I %s%s" dir path | libs -> let mk_I dir path = sprintf " -I %s%s" dir path
in List.fold_right mk_I libs "" in List.fold_right mk_I libs ""
let prefix = let prefix =
@ -61,26 +49,26 @@ let pp_input =
let cpp_cmd = let cpp_cmd =
match options#input with match options#input with
None | Some "-" -> None | Some "-" ->
Printf.sprintf "cpp -traditional-cpp%s - > %s" sprintf "cpp -traditional-cpp%s - > %s"
lib_path pp_input lib_path pp_input
| Some file -> | Some file ->
Printf.sprintf "cpp -traditional-cpp%s %s > %s" sprintf "cpp -traditional-cpp%s %s > %s"
lib_path file pp_input lib_path file pp_input
let () = let () =
if Utils.String.Set.mem "cpp" options#verbose if Utils.String.Set.mem "cpp" options#verbose
then Printf.eprintf "%s\n%!" cpp_cmd; then eprintf "%s\n%!" cpp_cmd;
if Sys.command cpp_cmd <> 0 then if Sys.command cpp_cmd <> 0 then
external_ (Printf.sprintf "the command \"%s\" failed." cpp_cmd) external_ (sprintf "the command \"%s\" failed." cpp_cmd)
(** {1 Instanciating the lexer} *) (** {1 Instanciating the lexer} *)
module Lexer = Lexer.Make (LexToken) module Lexer = Lexer.Make (LexToken)
module Log = LexerLog.Make (Lexer) module Log = LexerLog.Make (Lexer)
module ParserFront = ParserAPI.Make (Lexer) (Parser) module ParserFront = ParserAPI.Make (Lexer) (Parser) (ParErr)
let lexer_inst = Lexer.open_token_stream (Some pp_input) let lexer_inst = Lexer.open_token_stream (Some pp_input)
let Lexer.{read; buffer; get_pos; get_last; close} = lexer_inst let Lexer.{read; buffer; get_win; get_pos; get_last; close} = lexer_inst
and cout = stdout and cout = stdout
@ -97,10 +85,10 @@ let tokeniser = read ~log
let () = let () =
try try
(* The incremental API *) let ast =
let ast = ParserFront.incr_contract lexer_inst in if options#mono
(* The monolithic API *) then ParserFront.mono_contract tokeniser buffer
(* let ast = ParserFront.mono_contract tokeniser buffer in *) else ParserFront.incr_contract lexer_inst in
if Utils.String.Set.mem "ast" options#verbose if Utils.String.Set.mem "ast" options#verbose
then let buffer = Buffer.create 131 in then let buffer = Buffer.create 131 in
let state = ParserLog.mk_state let state = ParserLog.mk_state
@ -122,14 +110,36 @@ let () =
Buffer.output_buffer stdout buffer Buffer.output_buffer stdout buffer
end end
with with
(* Lexing errors *)
Lexer.Error err -> Lexer.Error err ->
close_all (); close_all ();
Lexer.print_error ~offsets:options#offsets let msg =
options#mode err ~file Lexer.format_error ~offsets:options#offsets
| Parser.Error -> options#mode err ~file
let region = get_last () in in prerr_string msg
let error = Region.{region; value=SyntaxError} in
(* Incremental API of Menhir *)
| ParserFront.Point point ->
let () = close_all () in let () = close_all () in
print_error ~offsets:options#offsets let error =
options#mode error ~file ParserFront.format_error ~offsets:options#offsets
options#mode point
in eprintf "\027[31m%s\027[0m%!" error
(* Monolithic API of Menhir *)
| Parser.Error ->
let () = close_all () in
let invalid, valid_opt =
match get_win () with
Lexer.Nil ->
assert false (* Safe: There is always at least EOF. *)
| Lexer.One invalid -> invalid, None
| Lexer.Two (invalid, valid) -> invalid, Some valid in
let point = "", valid_opt, invalid in
let error =
ParserFront.format_error ~offsets:options#offsets
options#mode point
in eprintf "\027[31m%s\027[0m%!" error
(* I/O errors *)
| Sys_error msg -> Utils.highlight msg | Sys_error msg -> Utils.highlight msg

View File

@ -18,34 +18,29 @@
) )
(preprocess (preprocess
(pps bisect_ppx --conditional)) (pps bisect_ppx --conditional))
(flags (:standard -open Parser_shared -open Simple_utils)) (flags (:standard -open Parser_shared -open Simple_utils)))
)
(executable (executable
(name LexerMain) (name LexerMain)
(libraries (libraries
hex hex simple-utils tezos-utils parser_pascaligo)
simple-utils (modules LexerMain)
tezos-utils
parser_pascaligo)
(modules
LexerMain)
(preprocess (preprocess
(pps bisect_ppx --conditional)) (pps bisect_ppx --conditional))
(flags (:standard -open Parser_shared -open Parser_pascaligo)) (flags (:standard -open Parser_shared -open Parser_pascaligo)))
)
(executable (executable
(name ParserMain) (name ParserMain)
(libraries (libraries parser_pascaligo)
parser_pascaligo) (modules
(modules ParserMain) ParErr ParserAPI ParserMain)
(preprocess (preprocess
(pps bisect_ppx --conditional)) (pps bisect_ppx --conditional))
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_pascaligo))) (flags (:standard -open Simple_utils -open Parser_shared -open Parser_pascaligo)))
(executable (executable
(name Unlexer) (name Unlexer)
(libraries str)
(preprocess (preprocess
(pps bisect_ppx --conditional)) (pps bisect_ppx --conditional))
(modules Unlexer)) (modules Unlexer))

View File

@ -0,0 +1,13 @@
_build/*
*/_build
*~
.merlin
*/.merlin
*.install
/Version.ml
/dune-project
/Parser.mli
/Parser.ml
/Lexer.ml
/LexToken.ml
/Tests

View File

@ -65,7 +65,7 @@ type t =
(* Comparisons *) (* Comparisons *)
| EQ of Region.t (* "=" *) | EQ of Region.t (* "=" *)
| EQEQ of Region.t (* "=" *) | EQEQ of Region.t (* "==" *)
| NE of Region.t (* "!=" *) | NE of Region.t (* "!=" *)
| LT of Region.t (* "<" *) | LT of Region.t (* "<" *)
| GT of Region.t (* ">" *) | GT of Region.t (* ">" *)

View File

@ -0,0 +1,510 @@
(* This file was auto-generated based on "Parser.msg". *)
(* Please note that the function [message] can raise [Not_found]. *)
let message =
fun s ->
match s with
| 0 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 1 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 2 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 3 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 4 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 5 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 55 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 6 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 52 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 54 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 7 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 38 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 8 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 9 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 32 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 36 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 35 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 10 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 31 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 11 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 509 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 503 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 48 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 12 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 19 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 20 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 43 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 46 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 49 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 13 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 14 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 60 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 65 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 505 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 145 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 146 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 144 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 329 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 331 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 330 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 61 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 64 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 59 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 143 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 338 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 340 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 339 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 151 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 152 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 78 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 325 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 327 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 326 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 92 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 155 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 118 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 125 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 87 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 105 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 107 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 108 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 106 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 88 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 93 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 80 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 81 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 82 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 132 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 334 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 336 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 335 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 133 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 136 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 137 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 157 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 159 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 158 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 512 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 218 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 514 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 216 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 250 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 248 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 249 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 230 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 235 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 252 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 254 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 255 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 258 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 219 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 226 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 227 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 260 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 262 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 264 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 266 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 194 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 195 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 206 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 215 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 199 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 207 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 208 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 196 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 197 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 198 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 256 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 257 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 277 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 233 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 279 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 67 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 463 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 464 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 387 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 121 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 122 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 120 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 466 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 467 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 483 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 492 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 469 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 470 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 468 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 471 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 472 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 473 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 475 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 476 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 477 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 478 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 487 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 488 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 474 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 499 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 497 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 465 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 321 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 315 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 316 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 318 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 317 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 314 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 71 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 410 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 298 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 304 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 305 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 308 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 309 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 300 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 178 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 73 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 75 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 419 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 420 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 77 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 160 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 412 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 413 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 415 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 416 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 193 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 229 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 74 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 447 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 448 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 456 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 457 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 459 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 460 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 449 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 450 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 76 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 440 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 441 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 425 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 422 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 428 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 429 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 434 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 438 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 437 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 433 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 423 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 427 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 162 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 163 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 290 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 295 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 296 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 357 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 400 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 401 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 402 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 403 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 404 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 405 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 399 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 297 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 311 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 312 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 322 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 323 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 377 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 384 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 342 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 343 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 324 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 344 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 345 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 346 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 370 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 371 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 372 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 373 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 379 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 380 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 369 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 393 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 391 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 313 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 348 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 349 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 347 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 350 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 351 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 352 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 359 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 360 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 361 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 362 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 364 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 363 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 358 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 292 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 293 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 164 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 165 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 166 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 167 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 168 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 169 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 174 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 175 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 176 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 188 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 237 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| _ ->
raise Not_found

View File

@ -1,57 +1,82 @@
(** Generic parser for LIGO *) (* Generic parser for LIGO *)
module type PARSER = (* Main functor *)
sig
(* The type of tokens *) module Make (Lexer: Lexer.S with module Token := LexToken)
(Parser: module type of Parser)
type token (ParErr: sig val message : int -> string end) =
struct
(* This exception is raised by the monolithic API functions *) module I = Parser.MenhirInterpreter
module S = MenhirLib.General (* Streams *)
exception Error
(* The call [stack checkpoint] extracts the parser's stack out of
(* The monolithic API *) a checkpoint. *)
val contract : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> AST.t let stack = function
I.HandlingError env -> I.stack env
(* The incremental API *) | _ -> assert false
module MenhirInterpreter : (* The call [state checkpoint] extracts the number of the current
sig state out of a parser checkpoint. *)
include MenhirLib.IncrementalEngine.INCREMENTAL_ENGINE
with type token = token let state checkpoint : int =
end match Lazy.force (stack checkpoint) with
S.Nil -> 0 (* WARNING: Hack. The first state should be 0. *)
module Incremental : | S.Cons (I.Element (s,_,_,_),_) -> I.number s
sig
val contract : Lexing.position -> AST.t MenhirInterpreter.checkpoint (* The parser has successfully produced a semantic value. *)
end
end let success v = v
(* Main functor *) (* The parser has suspended itself because of a syntax error. Stop. *)
module Make (Lexer: Lexer.S) type message = string
(Parser: PARSER with type token = Lexer.Token.token) = type valid = Lexer.token
struct type invalid = Lexer.token
type error = message * valid option * invalid
module I = Parser.MenhirInterpreter
exception Point of error
(* The parser has successfully produced a semantic value. *)
let failure get_win checkpoint =
let success v = v let message = ParErr.message (state checkpoint) in
match get_win () with
(* The parser has suspended itself because of a syntax error. Stop. *) Lexer.Nil -> assert false
| Lexer.One invalid ->
let fail _checkpoint = raise Parser.Error raise (Point (message, None, invalid))
| Lexer.Two (invalid, valid) ->
(* The generic parsing function *) raise (Point (message, Some valid, invalid))
let incr_contract Lexer.{read; buffer; close; _} : AST.t = (* The two Menhir APIs are called from the following two functions. *)
let supplier = I.lexer_lexbuf_to_supplier read buffer in
let parser = Parser.Incremental.contract buffer.Lexing.lex_curr_p in let incr_contract Lexer.{read; buffer; get_win; close; _} : AST.t =
let ast = I.loop_handle success fail supplier parser let supplier = I.lexer_lexbuf_to_supplier read buffer
in close (); ast and failure = failure get_win in
let parser = Parser.Incremental.contract buffer.Lexing.lex_curr_p in
let mono_contract = Parser.contract let ast = I.loop_handle success failure supplier parser
in close (); ast
end
let mono_contract = Parser.contract
(* Errors *)
let format_error ?(offsets=true) mode (msg, valid_opt, invalid) =
let invalid_region = LexToken.to_region invalid in
let header =
"Parse error " ^ invalid_region#to_string ~offsets mode in
let trailer =
match valid_opt with
None ->
if LexToken.is_eof invalid then ""
else let invalid_lexeme = LexToken.to_lexeme invalid in
Printf.sprintf ", before \"%s\"" invalid_lexeme
| Some valid ->
let valid_lexeme = LexToken.to_lexeme valid in
let s = Printf.sprintf ", after \"%s\"" valid_lexeme in
if LexToken.is_eof invalid then s
else
let invalid_lexeme = LexToken.to_lexeme invalid in
Printf.sprintf "%s and before \"%s\"" s invalid_lexeme in
let header = header ^ trailer in
header ^ (if msg = "" then ".\n" else ":\n" ^ msg)
end

View File

@ -1,39 +1,22 @@
(** Generic parser API for LIGO *) (** Generic parser API for LIGO *)
module type PARSER = module Make (Lexer: Lexer.S with module Token := LexToken)
(Parser: module type of Parser)
(ParErr: sig val message: int -> string end) :
sig sig
(* The type of tokens *) (* Monolithic and incremental APIs of Menhir for parsing *)
type token
(* This exception is raised by the monolithic API functions *)
exception Error
(* The monolithic API *)
val contract : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> AST.t
(* The incremental API *)
module MenhirInterpreter :
sig
include MenhirLib.IncrementalEngine.INCREMENTAL_ENGINE
with type token = token
end
module Incremental :
sig
val contract : Lexing.position -> AST.t MenhirInterpreter.checkpoint
end
end
(* Main functor *)
module Make (Lexer: Lexer.S)
(Parser: PARSER with type token = Lexer.Token.token) :
sig
val mono_contract : (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> AST.t val mono_contract : (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> AST.t
val incr_contract : Lexer.instance -> AST.t val incr_contract : Lexer.instance -> AST.t
(* Error handling *)
type message = string
type valid = Lexer.token
type invalid = Lexer.token
type error = message * valid option * invalid
exception Point of error
val format_error : ?offsets:bool -> [`Byte | `Point] -> error -> string
end end

View File

@ -1,16 +1,14 @@
(** Driver for the LIGO parser *) (** Driver for the Reason LIGO parser *)
let extension = ".religo" let extension = ".religo"
let options = EvalOpt.read "ReasonLIGO" extension let options = EvalOpt.read "ReasonLIGO" extension
open Printf
(** Error printing and exception tracing (** Error printing and exception tracing
*) *)
let () = Printexc.record_backtrace true let () = Printexc.record_backtrace true
(** Auxiliary functions
*)
let sprintf = Printf.sprintf
(** Extracting the input file (** Extracting the input file
*) *)
let file = let file =
@ -23,17 +21,7 @@ let file =
let () = Printexc.record_backtrace true let () = Printexc.record_backtrace true
let external_ text = let external_ text =
Utils.highlight (Printf.sprintf "External error: %s" text); exit 1;; Utils.highlight (sprintf "External error: %s" text); exit 1;;
type error = SyntaxError
let error_to_string = function
SyntaxError -> "Syntax error.\n"
let print_error ?(offsets=true) mode Region.{region; value} ~file =
let msg = error_to_string value
and reg = region#to_string ~file ~offsets mode in
Utils.highlight (sprintf "Parse error %s:\n%s%!" reg msg)
(** {1 Preprocessing the input source and opening the input channels} *) (** {1 Preprocessing the input source and opening the input channels} *)
@ -42,7 +30,7 @@ let print_error ?(offsets=true) mode Region.{region; value} ~file =
let lib_path = let lib_path =
match options#libs with match options#libs with
[] -> "" [] -> ""
| libs -> let mk_I dir path = Printf.sprintf " -I %s%s" dir path | libs -> let mk_I dir path = sprintf " -I %s%s" dir path
in List.fold_right mk_I libs "" in List.fold_right mk_I libs ""
let prefix = let prefix =
@ -61,26 +49,26 @@ let pp_input =
let cpp_cmd = let cpp_cmd =
match options#input with match options#input with
None | Some "-" -> None | Some "-" ->
Printf.sprintf "cpp -traditional-cpp%s - > %s" sprintf "cpp -traditional-cpp%s - > %s"
lib_path pp_input lib_path pp_input
| Some file -> | Some file ->
Printf.sprintf "cpp -traditional-cpp%s %s > %s" sprintf "cpp -traditional-cpp%s %s > %s"
lib_path file pp_input lib_path file pp_input
let () = let () =
if Utils.String.Set.mem "cpp" options#verbose if Utils.String.Set.mem "cpp" options#verbose
then Printf.eprintf "%s\n%!" cpp_cmd; then eprintf "%s\n%!" cpp_cmd;
if Sys.command cpp_cmd <> 0 then if Sys.command cpp_cmd <> 0 then
external_ (Printf.sprintf "the command \"%s\" failed." cpp_cmd) external_ (sprintf "the command \"%s\" failed." cpp_cmd)
(** {1 Instanciating the lexer} *) (** {1 Instanciating the lexer} *)
module Lexer = Lexer.Make (LexToken) module Lexer = Lexer.Make (LexToken)
module Log = LexerLog.Make (Lexer) module Log = LexerLog.Make (Lexer)
module ParserFront = ParserAPI.Make (Lexer) (Parser) module ParserFront = ParserAPI.Make (Lexer) (Parser) (ParErr)
let lexer_inst = Lexer.open_token_stream (Some pp_input) let lexer_inst = Lexer.open_token_stream (Some pp_input)
let Lexer.{read; buffer; get_pos; get_last; close} = lexer_inst let Lexer.{read; buffer; get_win; get_pos; get_last; close} = lexer_inst
and cout = stdout and cout = stdout
@ -97,10 +85,10 @@ let tokeniser = read ~log
let () = let () =
try try
(* The incremental API *) let ast =
let ast = ParserFront.incr_contract lexer_inst in if options#mono
(* The monolithic API *) then ParserFront.mono_contract tokeniser buffer
(* let ast = ParserFront.mono_contract tokeniser buffer in *) else ParserFront.incr_contract lexer_inst in
if Utils.String.Set.mem "ast" options#verbose if Utils.String.Set.mem "ast" options#verbose
then let buffer = Buffer.create 131 in then let buffer = Buffer.create 131 in
let state = ParserLog.mk_state let state = ParserLog.mk_state
@ -122,14 +110,36 @@ let () =
Buffer.output_buffer stdout buffer Buffer.output_buffer stdout buffer
end end
with with
(* Lexing errors *)
Lexer.Error err -> Lexer.Error err ->
close_all (); close_all ();
Lexer.print_error ~offsets:options#offsets let msg =
options#mode err ~file Lexer.format_error ~offsets:options#offsets
| Parser.Error -> options#mode err ~file
let region = get_last () in in prerr_string msg
let error = Region.{region; value=SyntaxError} in
(* Incremental API of Menhir *)
| ParserFront.Point point ->
let () = close_all () in let () = close_all () in
print_error ~offsets:options#offsets let error =
options#mode error ~file ParserFront.format_error ~offsets:options#offsets
options#mode point
in eprintf "\027[31m%s\027[0m%!" error
(* Monolithic API of Menhir *)
| Parser.Error ->
let () = close_all () in
let invalid, valid_opt =
match get_win () with
Lexer.Nil ->
assert false (* Safe: There is always at least EOF. *)
| Lexer.One invalid -> invalid, None
| Lexer.Two (invalid, valid) -> invalid, Some valid in
let point = "", valid_opt, invalid in
let error =
ParserFront.format_error ~offsets:options#offsets
options#mode point
in eprintf "\027[31m%s\027[0m%!" error
(* I/O errors *)
| Sys_error msg -> Utils.highlight msg | Sys_error msg -> Utils.highlight msg

View File

@ -8,43 +8,40 @@
(library (library
(name parser_reasonligo) (name parser_reasonligo)
(public_name ligo.parser.reasonligo) (public_name ligo.parser.reasonligo)
(modules SyntaxError reasonligo LexToken Parser) (modules
SyntaxError reasonligo LexToken Parser)
(libraries (libraries
menhirLib menhirLib
parser_shared parser_shared
parser_cameligo parser_cameligo
str str
simple-utils simple-utils
tezos-utils tezos-utils
getopt getopt)
)
(preprocess (preprocess
(pps bisect_ppx --conditional) (pps bisect_ppx --conditional))
) (flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo)))
(flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo ))
)
(executable (executable
(name LexerMain) (name LexerMain)
(libraries (libraries parser_reasonligo)
parser_reasonligo) (modules LexerMain)
(modules
LexerMain)
(preprocess (preprocess
(pps bisect_ppx --conditional) (pps bisect_ppx --conditional))
) (flags (:standard -open Parser_shared -open Parser_reasonligo)))
(flags (:standard -open Parser_shared -open Parser_reasonligo))
)
(executable (executable
(name ParserMain) (name ParserMain)
(libraries (libraries
parser_reasonligo parser_reasonligo
parser_cameligo) parser_cameligo)
(modules (modules
ParserAPI ParErr ParserAPI ParserMain)
ParserMain)
(preprocess (preprocess
(pps bisect_ppx --conditional) (pps bisect_ppx --conditional))
)
(flags (:standard -open Simple_utils -open Parser_cameligo -open Parser_shared -open Parser_reasonligo))) (flags (:standard -open Simple_utils -open Parser_cameligo -open Parser_shared -open Parser_reasonligo)))
(executable
(name Unlexer)
(libraries str)
(modules Unlexer))

View File

@ -0,0 +1,103 @@
(** Converting the textual representation of tokens produced by Menhir
into concrete syntax *)
(* See [ParToken.mly] *)
let gen_sym prefix =
let count = ref 0 in
fun () -> incr count;
prefix ^ string_of_int !count
let id_sym = gen_sym "id"
and ctor_sym = gen_sym "C"
let concrete = function
(* Keywords *)
| "Else" -> "else"
| "False" -> "false"
| "If" -> "if"
| "Let" -> "let"
| "Switch" -> "switch"
| "Mod" -> "mod"
| "Or" -> "or"
| "True" -> "true"
| "Type" -> "type"
(* Data constructors *)
| "C_None" -> "None"
| "C_Some" -> "Some"
(* Symbols *)
| "MINUS" -> "-"
| "PLUS" -> "+"
| "SLASH" -> "/"
| "TIMES" -> "*"
| "LPAR" -> "("
| "RPAR" -> ")"
| "LBRACKET" -> "["
| "RBRACKET" -> "]"
| "LBRACE" -> "{"
| "RBRACE" -> "}"
| "CAT" -> "++"
| "DOT" -> "."
| "ELLIPSIS" -> "..."
| "COMMA" -> ","
| "SEMI" -> ";"
| "COLON" -> ":"
| "VBAR" -> "|"
| "WILD" -> "_"
| "EQ" -> "="
| "EQEQ" -> "=="
| "NE" -> "!="
| "LT" -> "<"
| "GT" -> ">"
| "LE" -> "<="
| "GE" -> ">="
| "ARROW" -> "=>"
| "NOT" -> "!"
| "BOOL_OR" -> "||"
| "BOOL_AND" -> "&&"
(* Literals *)
| "String" -> "\"a string\""
| "Bytes" -> "0xAA"
| "Int" -> "1"
| "Nat" -> "1n"
| "Mutez" -> "1mutez"
| "Ident" -> id_sym ()
| "Constr" -> ctor_sym ()
(* Virtual tokens *)
| "EOF" -> ""
(* For completeness of open sum types *)
| _ -> "<Unknown>"
(* Unlexing a sentence *)
let unlex (sentence: string) : Buffer.t =
let tokens = Str.split (Str.regexp " ") sentence in
let lexemes = List.map concrete tokens in
let buffer = Buffer.create 31 in
let rec trans = function
[] -> ()
| [s] -> Buffer.add_string buffer s
| s::l -> Buffer.add_string buffer (s ^ " "); trans l
in trans lexemes; buffer
(* Reading one line from the standard input channel and unlex it. *)
let out = unlex (input_line stdin) |> Buffer.contents
let () = Printf.printf "%s\n" out

View File

@ -13,10 +13,11 @@ type options = <
verbose : Utils.String.Set.t; verbose : Utils.String.Set.t;
offsets : bool; offsets : bool;
mode : [`Byte | `Point]; mode : [`Byte | `Point];
cmd : command cmd : command;
mono : bool
> >
let make ~input ~libs ~verbose ~offsets ~mode ~cmd = let make ~input ~libs ~verbose ~offsets ~mode ~cmd ~mono =
object object
method input = input method input = input
method libs = libs method libs = libs
@ -24,6 +25,7 @@ let make ~input ~libs ~verbose ~offsets ~mode ~cmd =
method offsets = offsets method offsets = offsets
method mode = mode method mode = mode
method cmd = cmd method cmd = cmd
method mono = mono
end end
(** {1 Auxiliary functions} *) (** {1 Auxiliary functions} *)
@ -49,6 +51,7 @@ let help language extension () =
print " -q, --quiet No output, except errors (default)"; print " -q, --quiet No output, except errors (default)";
print " --columns Columns for source locations"; print " --columns Columns for source locations";
print " --bytes Bytes for source locations"; print " --bytes Bytes for source locations";
print " --mono Use Menhir monolithic API";
print " --verbose=<stages> cmdline, cpp, ast-tokens, ast (colon-separated)"; print " --verbose=<stages> cmdline, cpp, ast-tokens, ast (colon-separated)";
print " --version Commit hash on stdout"; print " --version Commit hash on stdout";
print " -h, --help This help"; print " -h, --help This help";
@ -70,6 +73,7 @@ and verbose = ref Utils.String.Set.empty
and input = ref None and input = ref None
and libs = ref [] and libs = ref []
and verb_str = ref "" and verb_str = ref ""
and mono = ref false
let split_at_colon = Str.(split (regexp ":")) let split_at_colon = Str.(split (regexp ":"))
@ -89,6 +93,7 @@ let specs language extension =
'q', "quiet", set quiet true, None; 'q', "quiet", set quiet true, None;
noshort, "columns", set columns true, None; noshort, "columns", set columns true, None;
noshort, "bytes", set bytes true, None; noshort, "bytes", set bytes true, None;
noshort, "mono", set mono true, None;
noshort, "verbose", None, Some add_verbose; noshort, "verbose", None, Some add_verbose;
'h', "help", Some (help language extension), None; 'h', "help", Some (help language extension), None;
noshort, "version", Some version, None noshort, "version", Some version, None
@ -124,6 +129,7 @@ let print_opt () =
printf "quiet = %b\n" !quiet; printf "quiet = %b\n" !quiet;
printf "columns = %b\n" !columns; printf "columns = %b\n" !columns;
printf "bytes = %b\n" !bytes; printf "bytes = %b\n" !bytes;
printf "mono = %b\b" !mono;
printf "verbose = %s\n" !verb_str; printf "verbose = %s\n" !verb_str;
printf "input = %s\n" (string_of quote !input); printf "input = %s\n" (string_of quote !input);
printf "libs = %s\n" (string_of_path !libs) printf "libs = %s\n" (string_of_path !libs)
@ -151,6 +157,7 @@ let check extension =
and quiet = !quiet and quiet = !quiet
and offsets = not !columns and offsets = not !columns
and mode = if !bytes then `Byte else `Point and mode = if !bytes then `Byte else `Point
and mono = !mono
and verbose = !verbose and verbose = !verbose
and libs = !libs in and libs = !libs in
@ -164,6 +171,7 @@ let check extension =
printf "quiet = %b\n" quiet; printf "quiet = %b\n" quiet;
printf "offsets = %b\n" offsets; printf "offsets = %b\n" offsets;
printf "mode = %s\n" (if mode = `Byte then "`Byte" else "`Point"); printf "mode = %s\n" (if mode = `Byte then "`Byte" else "`Point");
printf "mono = %b\n" mono;
printf "verbose = %s\n" !verb_str; printf "verbose = %s\n" !verb_str;
printf "input = %s\n" (string_of quote input); printf "input = %s\n" (string_of quote input);
printf "libs = %s\n" (string_of_path libs) printf "libs = %s\n" (string_of_path libs)
@ -178,7 +186,7 @@ let check extension =
| false, false, false, true -> Tokens | false, false, false, true -> Tokens
| _ -> abort "Choose one of -q, -c, -u, -t." | _ -> abort "Choose one of -q, -c, -u, -t."
in make ~input ~libs ~verbose ~offsets ~mode ~cmd in make ~input ~libs ~verbose ~offsets ~mode ~cmd ~mono
(** {1 Parsing the command-line options} *) (** {1 Parsing the command-line options} *)

View File

@ -49,7 +49,8 @@ type options = <
verbose : Utils.String.Set.t; verbose : Utils.String.Set.t;
offsets : bool; offsets : bool;
mode : [`Byte | `Point]; mode : [`Byte | `Point];
cmd : command cmd : command;
mono : bool
> >
val make : val make :
@ -58,7 +59,9 @@ val make :
verbose:Utils.String.Set.t -> verbose:Utils.String.Set.t ->
offsets:bool -> offsets:bool ->
mode:[`Byte | `Point] -> mode:[`Byte | `Point] ->
cmd:command -> options cmd:command ->
mono:bool ->
options
(** Parsing the command-line options on stdin. The first parameter is (** Parsing the command-line options on stdin. The first parameter is
the name of the concrete syntax, e.g., "pascaligo", and the second the name of the concrete syntax, e.g., "pascaligo", and the second

View File

@ -124,9 +124,17 @@ module type S =
type file_path = string type file_path = string
type logger = Markup.t list -> token -> unit type logger = Markup.t list -> token -> unit
type window =
Nil
| One of token
| Two of token * token
val slide : token -> window -> window
type instance = { type instance = {
read : ?log:logger -> Lexing.lexbuf -> token; read : ?log:logger -> Lexing.lexbuf -> token;
buffer : Lexing.lexbuf; buffer : Lexing.lexbuf;
get_win : unit -> window;
get_pos : unit -> Pos.t; get_pos : unit -> Pos.t;
get_last : unit -> Region.t; get_last : unit -> Region.t;
close : unit -> unit close : unit -> unit
@ -142,9 +150,9 @@ module type S =
exception Error of error Region.reg exception Error of error Region.reg
val print_error : val format_error :
?offsets:bool -> [`Byte | `Point] -> ?offsets:bool -> [`Byte | `Point] ->
error Region.reg -> file:bool -> unit error Region.reg -> file:bool -> string
end end

View File

@ -140,34 +140,43 @@ module type TOKEN =
(* The module type for lexers is [S]. *) (* The module type for lexers is [S]. *)
module type S = sig module type S =
module Token : TOKEN sig
type token = Token.token module Token : TOKEN
type token = Token.token
type file_path = string type file_path = string
type logger = Markup.t list -> token -> unit type logger = Markup.t list -> token -> unit
type instance = { type window =
read : ?log:logger -> Lexing.lexbuf -> token; Nil
buffer : Lexing.lexbuf; | One of token
get_pos : unit -> Pos.t; | Two of token * token
get_last : unit -> Region.t;
close : unit -> unit
}
val open_token_stream : file_path option -> instance val slide : token -> window -> window
(* Error reporting *) type instance = {
read : ?log:logger -> Lexing.lexbuf -> token;
buffer : Lexing.lexbuf;
get_win : unit -> window;
get_pos : unit -> Pos.t;
get_last : unit -> Region.t;
close : unit -> unit
}
type error val open_token_stream : file_path option -> instance
val error_to_string : error -> string
exception Error of error Region.reg (* Error reporting *)
val print_error : ?offsets:bool -> [`Byte | `Point] -> type error
error Region.reg -> file:bool -> unit
end val error_to_string : error -> string
exception Error of error Region.reg
val format_error : ?offsets:bool -> [`Byte | `Point] ->
error Region.reg -> file:bool -> string
end
(* The functorised interface (* The functorised interface
@ -212,7 +221,27 @@ module Make (Token: TOKEN) : (S with module Token = Token) =
(* STATE *) (* STATE *)
(* Beyond tokens, the result of lexing is a state. The type (** The type [buffer] models a two-slot buffer of tokens for
reporting after a parse error.
In [Two(t1,t2)], the token [t2] is the next to be sent to the
parser.
The call [slide token buffer] pushes the token [token] in the
buffer [buffer]. If the buffer is full, that is, it is
[Two(t1,t2)], then the token [t2] is discarded to make room for
[token].
*)
type window =
Nil
| One of token
| Two of token * token
let slide token = function
Nil -> One token
| One t | Two (t,_) -> Two (token,t)
(** Beyond tokens, the result of lexing is a state. The type
[state] represents the logical state of the lexing engine, that [state] represents the logical state of the lexing engine, that
is, a value which is threaded during scanning and which denotes is, a value which is threaded during scanning and which denotes
useful, high-level information beyond what the type useful, high-level information beyond what the type
@ -238,6 +267,10 @@ module Make (Token: TOKEN) : (S with module Token = Token) =
updated after a single character has been matched: that depends updated after a single character has been matched: that depends
on the regular expression that matched the lexing buffer. on the regular expression that matched the lexing buffer.
The field [win] is a two-token window, that is, a buffer that
contains the last recognised token, and the penultimate (if
any).
The fields [decoder] and [supply] offer the support needed The fields [decoder] and [supply] offer the support needed
for the lexing of UTF-8 encoded characters in comments (the for the lexing of UTF-8 encoded characters in comments (the
only place where they are allowed in LIGO). The former is the only place where they are allowed in LIGO). The former is the
@ -246,10 +279,10 @@ module Make (Token: TOKEN) : (S with module Token = Token) =
it to [decoder]. See the documentation of the third-party it to [decoder]. See the documentation of the third-party
library Uutf. library Uutf.
*) *)
type state = { type state = {
units : (Markup.t list * token) FQueue.t; units : (Markup.t list * token) FQueue.t;
markup : Markup.t list; markup : Markup.t list;
window : window;
last : Region.t; last : Region.t;
pos : Pos.t; pos : Pos.t;
decoder : Uutf.decoder; decoder : Uutf.decoder;
@ -401,10 +434,10 @@ module Make (Token: TOKEN) : (S with module Token = Token) =
exception Error of error Region.reg exception Error of error Region.reg
let print_error ?(offsets=true) mode Region.{region; value} ~file = let format_error ?(offsets=true) mode Region.{region; value} ~file =
let msg = error_to_string value in let msg = error_to_string value in
let reg = region#to_string ~file ~offsets mode in let reg = region#to_string ~file ~offsets mode in
Utils.highlight (sprintf "Lexical error %s:\n%s%!" reg msg) sprintf "\027[31mLexical error %s:\n%s\027[0m%!" reg msg
let fail region value = raise (Error Region.{region; value}) let fail region value = raise (Error Region.{region; value})
@ -804,6 +837,7 @@ type logger = Markup.t list -> token -> unit
type instance = { type instance = {
read : ?log:logger -> Lexing.lexbuf -> token; read : ?log:logger -> Lexing.lexbuf -> token;
buffer : Lexing.lexbuf; buffer : Lexing.lexbuf;
get_win : unit -> window;
get_pos : unit -> Pos.t; get_pos : unit -> Pos.t;
get_last : unit -> Region.t; get_last : unit -> Region.t;
close : unit -> unit close : unit -> unit
@ -820,13 +854,15 @@ let open_token_stream file_path_opt =
let supply = Uutf.Manual.src decoder in let supply = Uutf.Manual.src decoder in
let state = ref {units = FQueue.empty; let state = ref {units = FQueue.empty;
last = Region.ghost; last = Region.ghost;
window = Nil;
pos; pos;
markup = []; markup = [];
decoder; decoder;
supply} in supply} in
let get_pos () = !state.pos let get_pos () = !state.pos
and get_last () = !state.last in and get_last () = !state.last
and get_win () = !state.window in
let patch_buffer (start, stop) buffer = let patch_buffer (start, stop) buffer =
let open Lexing in let open Lexing in
@ -883,7 +919,9 @@ let open_token_stream file_path_opt =
read_token ~log buffer read_token ~log buffer
| Some (units, (left_mark, token)) -> | Some (units, (left_mark, token)) ->
log left_mark token; log left_mark token;
state := {!state with units; last = Token.to_region token}; state := {!state with units;
last = Token.to_region token;
window = slide token !state.window};
check_right_context token buffer; check_right_context token buffer;
patch_buffer (Token.to_region token)#byte_pos buffer; patch_buffer (Token.to_region token)#byte_pos buffer;
token in token in
@ -896,7 +934,7 @@ let open_token_stream file_path_opt =
None | Some "-" -> () None | Some "-" -> ()
| Some file_path -> reset ~file:file_path buffer | Some file_path -> reset ~file:file_path buffer
and close () = close_in cin in and close () = close_in cin in
{read = read_token; buffer; get_pos; get_last; close} {read = read_token; buffer; get_win; get_pos; get_last; close}
end (* of functor [Make] in HEADER *) end (* of functor [Make] in HEADER *)
(* END TRAILER *) (* END TRAILER *)

View File

@ -65,9 +65,11 @@ module Make (Lexer: Lexer.S) : (S with module Lexer = Lexer) =
let file = let file =
match file_path_opt with match file_path_opt with
None | Some "-" -> false None | Some "-" -> false
| Some _ -> true in | Some _ -> true in
Lexer.print_error ~offsets mode e ~file; let msg =
close_all () Lexer.format_error ~offsets mode e ~file
in prerr_string msg;
close_all ()
in iter () in iter ()
with Sys_error msg -> Utils.highlight (sprintf "%s\n" msg) with Sys_error msg -> Utils.highlight (sprintf "%s\n" msg)

View File

@ -19,9 +19,7 @@
Markup Markup
FQueue FQueue
EvalOpt EvalOpt
Version Version))
))
(rule (rule
(targets Version.ml) (targets Version.ml)

View File

@ -4,7 +4,7 @@
# Menhir and generates minimal inputs that cover all of them and only # Menhir and generates minimal inputs that cover all of them and only
# them. # them.
set -x # set -x
# ==================================================================== # ====================================================================
# General Settings and wrappers # General Settings and wrappers
@ -111,8 +111,8 @@ done
usage () { usage () {
cat <<EOF cat <<EOF
Usage: $(basename $0) [-h|--help] Usage: $(basename $0) [-h|--help]
--par-tokens=<par_tolens>.mly --par-tokens=<par_tokens>.mly
--lex-tokens=<par_tokens>.mli --lex-tokens=<lex_tokens>.mli
--unlexer=<binary> --unlexer=<binary>
--ext=<extension> --ext=<extension>
--dir=<path> --dir=<path>
@ -121,7 +121,7 @@ Usage: $(basename $0) [-h|--help]
Generates in directory <path> a set of LIGO source files with Generates in directory <path> a set of LIGO source files with
extension <extension> covering all erroneous states of the LR extension <extension> covering all erroneous states of the LR
automaton produced by Menhir from <parser>.mly, <par_tokens>.mly, automaton produced by Menhir from <parser>.mly, <par_tokens>.mly,
<lex_tokens>.mli and <parser>.msg (see script `messages.sh` for <lex_tokens>.mli and <parser>.msg (see script messages.sh for
generating the latter). The LIGO files will be numbered with their generating the latter). The LIGO files will be numbered with their
corresponding state number in the automaton. The executable <binary> corresponding state number in the automaton. The executable <binary>
reads a line on stdin of tokens and produces a line of corresponding reads a line on stdin of tokens and produces a line of corresponding

199
vendors/ligo-utils/simple-utils/par_err.sh vendored Executable file
View File

@ -0,0 +1,199 @@
#!/bin/sh
# This script calls Menhir with a message file, which generates the
# corresponding OCaml file.
# set -x
# ====================================================================
# General Settings and wrappers
script=$(basename $0)
print_nl () { test "$quiet" != "yes" && echo "$1"; }
print () { test "$quiet" != "yes" && printf "$1"; }
fatal_error () {
echo "$script: fatal error:"
echo "$1" 1>&2
exit 1
}
warn () {
print_nl "$script: warning:"
print_nl "$1"
}
failed () {
printf "\033[31mFAILED$1\033[0m\n"
}
emphasise () {
printf "\033[31m$1\033[0m\n"
}
display () {
printf "\033[31m"; cat $1; printf "\033[0m"
}
# ====================================================================
# Parsing loop
#
while : ; do
case "$1" in
"") break;;
--par-tokens=*)
if test -n "$par_tokens"; then
fatal_error "Repeated option --par-tokens."; fi
par_tokens=$(expr "$1" : "[^=]*=\(.*\)")
;;
--par-tokens)
no_eq=$1
break
;;
--lex-tokens=*)
if test -n "$lex_tokens"; then
fatal_error "Repeated option --lex-tokens."; fi
lex_tokens=$(expr "$1" : "[^=]*=\(.*\)")
;;
--lex-tokens)
no_eq=$1
break
;;
--out=*)
if test -n "$out"; then
fatal_error "Repeated option --out."; fi
out=$(expr "$1" : "[^=]*=\(.*\)")
;;
--out)
no_eq=$1
break
;;
-h | --help | -help)
help=yes
;;
# Invalid option
#
-*)
fatal_error "Invalid option \"$1\"."
;;
# Invalid argument
#
*)
if test -n "$parser_arg"; then
fatal_error "Only one Menhir specification allowed."; fi
parser=$1
esac
shift
done
# ====================================================================
# Help
#
usage () {
cat <<EOF
Usage: $(basename $0) [-h|--help]
--par-tokens=<par_tokens>.mly
--lex-tokens=<lex_tokens>.mli
--out=<par_err>.ml
<parser>.mly
Generates <par_err>.ml from <parser>.msg and the parser specification
(see messages.sh) in the current directory.
The following options, if given, must be given only once.
Display control:
-h, --help display this help and exit
Mandatory options:
--lex-tokens=<name>.mli the lexical tokens
--par-tokens=<name>.mly the syntactical tokens
--out=<par_err>.ml
EOF
exit 1
}
if test "$help" = "yes"; then usage; fi
# ====================================================================
# Checking the command-line options and arguments and applying some of
# them.
# It is a common mistake to forget the "=" in GNU long-option style.
if test -n "$no_eq"
then
fatal_error "Long option style $no_eq must be followed by \"=\"."
fi
# Checking options
if test -z "$parser"; then
fatal_error "No parser specification."; fi
if test -z "$par_tokens"; then
fatal_error "No syntactical tokens specification (use --par-tokens)."; fi
if test -z "$lex_tokens"; then
fatal_error "No lexical tokens specification (use --lex-tokens)."; fi
if test ! -e "$parser"; then
fatal_error "Parser specification \"$parser\" not found."; fi
if test ! -e "$lex_tokens"; then
fatal_error "Lexical tokens specification \"$lex_tokens\" not found."; fi
if test ! -e "$par_tokens"; then
fatal_error "Syntactical tokens specification \"$par_tokens\" not found."; fi
parser_ext=$(expr "$parser" : ".*\.mly$")
if test "$parser_ext" = "0"; then
fatal_error "Parser specification must have extension \".mly\"."; fi
par_tokens_ext=$(expr "$par_tokens" : ".*\.mly$")
if test "$par_tokens_ext" = "0"; then
fatal_error "Syntactical tokens specification must have extension \".mly\"."
fi
lex_tokens_ext=$(expr "$lex_tokens" : ".*\.mli$")
if test "$lex_tokens_ext" = "0"; then
fatal_error "Lexical tokens specification must have extension \".mli\"."
fi
mly=$parser
parser_base=$(basename $mly .mly)
par_tokens_base=$(basename $par_tokens .mly)
lex_tokens_base=$(basename $lex_tokens .mli)
# Checking the presence of the messages
msg=$parser_base.msg
if test ! -e $msg; then
fatal_error "File $msg not found."; fi
# Checking the output file
if test -z "$out"; then
fatal_error "Output file missing (use --out)."; fi
# ====================================================================
# Menhir's flags
flags="--table --strict --external-tokens $lex_tokens_base \
--base $parser_base $par_tokens"
# ===================================================================
# Generating source code from error messages
err=.$msg.err
printf "Making $out from $msg... "
menhir --compile-errors $msg $flags $mly > $out 2> $err
if test "$?" = "0"
then printf "done.\n"
rm -f $err
else failed ":"
display "$err"
fi