diff --git a/src/passes/1-parser/cameligo/.links b/src/passes/1-parser/cameligo/.links index eca6c8680..a29429a42 100644 --- a/src/passes/1-parser/cameligo/.links +++ b/src/passes/1-parser/cameligo/.links @@ -16,4 +16,8 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml ../shared/Markup.mli ../shared/Utils.mli ../shared/Utils.ml +../shared/ParserAPI.mli +../shared/ParserAPI.ml +../shared/LexerUnit.ml +../shared/ParserUnit.ml Stubs/Simple_utils.ml diff --git a/src/passes/1-parser/cameligo/LexerMain.ml b/src/passes/1-parser/cameligo/LexerMain.ml index 80ae8b00d..e9775b803 100644 --- a/src/passes/1-parser/cameligo/LexerMain.ml +++ b/src/passes/1-parser/cameligo/LexerMain.ml @@ -1,56 +1,9 @@ -(** Driver for the LIGO lexer *) +(** Driver for the CameLIGO lexer *) -let extension = ".mligo" -let options = EvalOpt.read "CameLIGO" extension +module IO = + struct + let ext = ".mligo" + let options = EvalOpt.read "CameLIGO" ext + end -(** Error printing and exception tracing -*) -let () = Printexc.record_backtrace true - -let external_ text = - Utils.highlight (Printf.sprintf "External error: %s" text); exit 1;; - -(** {1 Preprocessing the input source and opening the input channels} *) - -(** Path for CPP inclusions (#include) -*) -let lib_path = - match options#libs with - [] -> "" - | libs -> let mk_I dir path = Printf.sprintf " -I %s%s" dir path - in List.fold_right mk_I libs "" - -let prefix = - match options#input with - None | Some "-" -> "temp" - | Some file -> Filename.(file |> basename |> remove_extension) - -let suffix = ".pp" ^ extension - -let pp_input = - if Utils.String.Set.mem "cpp" options#verbose - then prefix ^ suffix - else let pp_input, pp_out = Filename.open_temp_file prefix suffix - in close_out pp_out; pp_input - -let cpp_cmd = - match options#input with - None | Some "-" -> - Printf.sprintf "cpp -traditional-cpp%s - > %s" - lib_path pp_input - | Some file -> - Printf.sprintf "cpp -traditional-cpp%s %s > %s" - lib_path file pp_input - -let () = - if Utils.String.Set.mem "cpp" options#verbose - then Printf.eprintf "%s\n%!" cpp_cmd; - if Sys.command cpp_cmd <> 0 then - external_ (Printf.sprintf "the command \"%s\" failed." cpp_cmd) - -(** {1 Running the lexer on the input file} *) - -module Log = LexerLog.Make (Lexer.Make (LexToken)) - -let () = Log.trace ~offsets:options#offsets - options#mode (Some pp_input) options#cmd +module M = LexerUnit.Make (IO) (Lexer.Make (LexToken)) diff --git a/src/passes/1-parser/cameligo/ParserAPI.mli b/src/passes/1-parser/cameligo/ParserAPI.mli deleted file mode 100644 index 7d969a33c..000000000 --- a/src/passes/1-parser/cameligo/ParserAPI.mli +++ /dev/null @@ -1,22 +0,0 @@ -(** Generic parser API for LIGO *) - -module Make (Lexer: Lexer.S with module Token := LexToken) - (Parser: module type of Parser) - (ParErr: sig val message: int -> string end) : - sig - (* Monolithic and incremental APIs of Menhir for parsing *) - - val mono_contract : (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> 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 diff --git a/src/passes/1-parser/cameligo/ParserMain.ml b/src/passes/1-parser/cameligo/ParserMain.ml index 8ed546f50..855dc639e 100644 --- a/src/passes/1-parser/cameligo/ParserMain.ml +++ b/src/passes/1-parser/cameligo/ParserMain.ml @@ -1,145 +1,27 @@ (** Driver for the CameLIGO parser *) -let extension = ".mligo" -let options = EvalOpt.read "CameLIGO" extension +module IO = + struct + let ext = ".mligo" + let options = EvalOpt.read "CameLIGO" ext + end -open Printf +module ExtParser = + struct + type ast = AST.t + type expr = AST.expr + include Parser + end -(** Error printing and exception tracing -*) -let () = Printexc.record_backtrace true +module ExtParserLog = + struct + type ast = AST.t + include ParserLog + end -(** Extracting the input file -*) -let file = - match options#input with - None | Some "-" -> false - | Some _ -> true - -(** {1 Error printing and exception tracing} *) - -let () = Printexc.record_backtrace true - -let external_ text = - Utils.highlight (sprintf "External error: %s" text); exit 1;; - -(** {1 Preprocessing the input source and opening the input channels} *) - -(** Path for CPP inclusions (#include) -*) -let lib_path = - match options#libs with - [] -> "" - | libs -> let mk_I dir path = sprintf " -I %s%s" dir path - in List.fold_right mk_I libs "" - -let prefix = - match options#input with - None | Some "-" -> "temp" - | Some file -> Filename.(file |> basename |> remove_extension) - -let suffix = ".pp" ^ extension - -let pp_input = - if Utils.String.Set.mem "cpp" options#verbose - then prefix ^ suffix - else let pp_input, pp_out = Filename.open_temp_file prefix suffix - in close_out pp_out; pp_input - -let cpp_cmd = - match options#input with - None | Some "-" -> - sprintf "cpp -traditional-cpp%s - > %s" - lib_path pp_input - | Some file -> - sprintf "cpp -traditional-cpp%s %s > %s" - lib_path file pp_input - -let () = - if Utils.String.Set.mem "cpp" options#verbose - then eprintf "%s\n%!" cpp_cmd; - if Sys.command cpp_cmd <> 0 then - external_ (sprintf "the command \"%s\" failed." cpp_cmd) - -(** {1 Instanciating the lexer} *) - -module Lexer = Lexer.Make (LexToken) -module Log = LexerLog.Make (Lexer) -module ParserFront = ParserAPI.Make (Lexer) (Parser) (ParErr) - -let lexer_inst = Lexer.open_token_stream (Some pp_input) -let Lexer.{read; buffer; get_win; get_pos; get_last; close} = lexer_inst - -and cout = stdout - -let log = Log.output_token ~offsets:options#offsets - options#mode options#cmd cout - -and close_all () = close (); close_out cout - -(** {1 Tokeniser} *) - -let tokeniser = read ~log - -(** {1 Main} *) - -let () = - try - let ast = - if options#mono - then ParserFront.mono_contract tokeniser buffer - else ParserFront.incr_contract lexer_inst in - if Utils.String.Set.mem "ast" options#verbose - then let buffer = Buffer.create 131 in - let state = ParserLog.mk_state - ~offsets:options#offsets - ~mode:options#mode - ~buffer in - begin - ParserLog.pp_ast state ast; - Buffer.output_buffer stdout buffer - end - else if Utils.String.Set.mem "ast-tokens" options#verbose - then let buffer = Buffer.create 131 in - let state = ParserLog.mk_state - ~offsets:options#offsets - ~mode:options#mode - ~buffer in - begin - ParserLog.print_tokens state ast; - Buffer.output_buffer stdout buffer - end - with - (* Lexing errors *) - Lexer.Error err -> - close_all (); - let msg = - Lexer.format_error ~offsets:options#offsets - options#mode err ~file - in prerr_string msg - - (* Incremental API of Menhir *) - | ParserFront.Point point -> - let () = close_all () in - let error = - 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 +module M = ParserUnit.Make (IO) + (Lexer.Make (LexToken)) + (AST) + (ExtParser) + (ParErr) + (ExtParserLog) diff --git a/src/passes/1-parser/cameligo/dune b/src/passes/1-parser/cameligo/dune index 786b20f31..8bfac351e 100644 --- a/src/passes/1-parser/cameligo/dune +++ b/src/passes/1-parser/cameligo/dune @@ -15,9 +15,9 @@ str simple-utils tezos-utils - getopt ) + getopt) (preprocess - (pps bisect_ppx --conditional) ) + (pps bisect_ppx --conditional)) (flags (:standard -open Simple_utils -open Parser_shared))) (executable @@ -32,7 +32,7 @@ (name ParserMain) (libraries parser_cameligo) (modules - ParErr ParserAPI ParserMain) + ParErr ParserMain) (preprocess (pps bisect_ppx --conditional)) (flags (:standard -open Simple_utils -open Parser_shared -open Parser_cameligo))) diff --git a/src/passes/1-parser/pascaligo/.links b/src/passes/1-parser/pascaligo/.links index eca6c8680..a29429a42 100644 --- a/src/passes/1-parser/pascaligo/.links +++ b/src/passes/1-parser/pascaligo/.links @@ -16,4 +16,8 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml ../shared/Markup.mli ../shared/Utils.mli ../shared/Utils.ml +../shared/ParserAPI.mli +../shared/ParserAPI.ml +../shared/LexerUnit.ml +../shared/ParserUnit.ml Stubs/Simple_utils.ml diff --git a/src/passes/1-parser/pascaligo/LexerMain.ml b/src/passes/1-parser/pascaligo/LexerMain.ml index 9838fcbc4..4f1940204 100644 --- a/src/passes/1-parser/pascaligo/LexerMain.ml +++ b/src/passes/1-parser/pascaligo/LexerMain.ml @@ -1,56 +1,9 @@ -(** Driver for the LIGO lexer *) +(** Driver for the PascaLIGO lexer *) -let extension = ".ligo" -let options = EvalOpt.read "PascaLIGO" extension +module IO = + struct + let ext = ".ligo" + let options = EvalOpt.read "PascaLIGO" ext + end -(** Error printing and exception tracing -*) -let () = Printexc.record_backtrace true - -let external_ text = - Utils.highlight (Printf.sprintf "External error: %s" text); exit 1;; - -(** {1 Preprocessing the input source and opening the input channels} *) - -(** Path for CPP inclusions (#include) -*) -let lib_path = - match options#libs with - [] -> "" - | libs -> let mk_I dir path = Printf.sprintf " -I %s%s" dir path - in List.fold_right mk_I libs "" - -let prefix = - match options#input with - None | Some "-" -> "temp" - | Some file -> Filename.(file |> basename |> remove_extension) - -let suffix = ".pp" ^ extension - -let pp_input = - if Utils.String.Set.mem "cpp" options#verbose - then prefix ^ suffix - else let pp_input, pp_out = Filename.open_temp_file prefix suffix - in close_out pp_out; pp_input - -let cpp_cmd = - match options#input with - None | Some "-" -> - Printf.sprintf "cpp -traditional-cpp%s - > %s" - lib_path pp_input - | Some file -> - Printf.sprintf "cpp -traditional-cpp%s %s > %s" - lib_path file pp_input - -let () = - if Utils.String.Set.mem "cpp" options#verbose - then Printf.eprintf "%s\n%!" cpp_cmd; - if Sys.command cpp_cmd <> 0 then - external_ (Printf.sprintf "the command \"%s\" failed." cpp_cmd) - -(** {1 Running the lexer on the input file} *) - -module Log = LexerLog.Make (Lexer.Make (LexToken)) - -let () = Log.trace ~offsets:options#offsets - options#mode (Some pp_input) options#cmd +module M = LexerUnit.Make (IO) (Lexer.Make (LexToken)) diff --git a/src/passes/1-parser/pascaligo/ParserAPI.ml b/src/passes/1-parser/pascaligo/ParserAPI.ml deleted file mode 100644 index df82173a9..000000000 --- a/src/passes/1-parser/pascaligo/ParserAPI.ml +++ /dev/null @@ -1,82 +0,0 @@ -(* Generic parser for LIGO *) - -(* Main functor *) - -module Make (Lexer: Lexer.S with module Token := LexToken) - (Parser: module type of Parser) - (ParErr: sig val message : int -> string end) = - struct - module I = Parser.MenhirInterpreter - module S = MenhirLib.General (* Streams *) - - (* The call [stack checkpoint] extracts the parser's stack out of - a checkpoint. *) - - let stack = function - I.HandlingError env -> I.stack env - | _ -> assert false - - (* The call [state checkpoint] extracts the number of the current - state out of a parser checkpoint. *) - - let state checkpoint : int = - match Lazy.force (stack checkpoint) with - S.Nil -> 0 (* WARNING: Hack. The first state should be 0. *) - | S.Cons (I.Element (s,_,_,_),_) -> I.number s - - (* The parser has successfully produced a semantic value. *) - - let success v = v - - (* The parser has suspended itself because of a syntax error. Stop. *) - - type message = string - type valid = Lexer.token - type invalid = Lexer.token - type error = message * valid option * invalid - - exception Point of error - - let failure get_win checkpoint = - let message = ParErr.message (state checkpoint) in - match get_win () with - Lexer.Nil -> assert false - | Lexer.One invalid -> - raise (Point (message, None, invalid)) - | Lexer.Two (invalid, valid) -> - raise (Point (message, Some valid, invalid)) - - (* The two Menhir APIs are called from the following two functions. *) - - let incr_contract Lexer.{read; buffer; get_win; close; _} : AST.t = - let supplier = I.lexer_lexbuf_to_supplier read buffer - and failure = failure get_win in - let parser = Parser.Incremental.contract buffer.Lexing.lex_curr_p in - let ast = I.loop_handle success failure supplier parser - in close (); ast - - 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 diff --git a/src/passes/1-parser/pascaligo/ParserAPI.mli b/src/passes/1-parser/pascaligo/ParserAPI.mli deleted file mode 100644 index afc0fb8ba..000000000 --- a/src/passes/1-parser/pascaligo/ParserAPI.mli +++ /dev/null @@ -1,22 +0,0 @@ -(** Generic parser API for LIGO *) - -module Make (Lexer: Lexer.S with module Token := LexToken) - (Parser: module type of Parser) - (ParErr: module type of ParErr) : - sig - (* Monolithic and incremental APIs of Menhir for parsing *) - - val mono_contract : (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> 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 diff --git a/src/passes/1-parser/pascaligo/ParserMain.ml b/src/passes/1-parser/pascaligo/ParserMain.ml index 489008453..3fcae9dec 100644 --- a/src/passes/1-parser/pascaligo/ParserMain.ml +++ b/src/passes/1-parser/pascaligo/ParserMain.ml @@ -1,145 +1,27 @@ (** Driver for the PascaLIGO parser *) -let extension = ".ligo" -let options = EvalOpt.read "PascaLIGO" extension +module IO = + struct + let ext = ".ligo" + let options = EvalOpt.read "PascaLIGO" ext + end -open Printf +module ExtParser = + struct + type ast = AST.t + type expr = AST.expr + include Parser + end -(** Error printing and exception tracing -*) -let () = Printexc.record_backtrace true +module ExtParserLog = + struct + type ast = AST.t + include ParserLog + end -(** Extracting the input file -*) -let file = - match options#input with - None | Some "-" -> false - | Some _ -> true - -(** {1 Error printing and exception tracing} *) - -let () = Printexc.record_backtrace true - -let external_ text = - Utils.highlight (sprintf "External error: %s" text); exit 1;; - -(** {1 Preprocessing the input source and opening the input channels} *) - -(** Path for CPP inclusions (#include) -*) -let lib_path = - match options#libs with - [] -> "" - | libs -> let mk_I dir path = sprintf " -I %s%s" dir path - in List.fold_right mk_I libs "" - -let prefix = - match options#input with - None | Some "-" -> "temp" - | Some file -> Filename.(file |> basename |> remove_extension) - -let suffix = ".pp" ^ extension - -let pp_input = - if Utils.String.Set.mem "cpp" options#verbose - then prefix ^ suffix - else let pp_input, pp_out = Filename.open_temp_file prefix suffix - in close_out pp_out; pp_input - -let cpp_cmd = - match options#input with - None | Some "-" -> - sprintf "cpp -traditional-cpp%s - > %s" - lib_path pp_input - | Some file -> - sprintf "cpp -traditional-cpp%s %s > %s" - lib_path file pp_input - -let () = - if Utils.String.Set.mem "cpp" options#verbose - then eprintf "%s\n%!" cpp_cmd; - if Sys.command cpp_cmd <> 0 then - external_ (sprintf "the command \"%s\" failed." cpp_cmd) - -(** {1 Instanciating the lexer} *) - -module Lexer = Lexer.Make (LexToken) -module Log = LexerLog.Make (Lexer) -module ParserFront = ParserAPI.Make (Lexer) (Parser) (ParErr) - -let lexer_inst = Lexer.open_token_stream (Some pp_input) -let Lexer.{read; buffer; get_win; get_pos; get_last; close} = lexer_inst - -and cout = stdout - -let log = Log.output_token ~offsets:options#offsets - options#mode options#cmd cout - -and close_all () = close (); close_out cout - -(** {1 Tokeniser} *) - -let tokeniser = read ~log - -(** {1 Main} *) - -let () = - try - let ast = - if options#mono - then ParserFront.mono_contract tokeniser buffer - else ParserFront.incr_contract lexer_inst in - if Utils.String.Set.mem "ast" options#verbose - then let buffer = Buffer.create 131 in - let state = ParserLog.mk_state - ~offsets:options#offsets - ~mode:options#mode - ~buffer in - begin - ParserLog.pp_ast state ast; - Buffer.output_buffer stdout buffer - end - else if Utils.String.Set.mem "ast-tokens" options#verbose - then let buffer = Buffer.create 131 in - let state = ParserLog.mk_state - ~offsets:options#offsets - ~mode:options#mode - ~buffer in - begin - ParserLog.print_tokens state ast; - Buffer.output_buffer stdout buffer - end - with - (* Lexing errors *) - Lexer.Error err -> - close_all (); - let msg = - Lexer.format_error ~offsets:options#offsets - options#mode err ~file - in prerr_string msg - - (* Incremental API of Menhir *) - | ParserFront.Point point -> - let () = close_all () in - let error = - 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 +module M = ParserUnit.Make (IO) + (Lexer.Make (LexToken)) + (AST) + (ExtParser) + (ParErr) + (ExtParserLog) diff --git a/src/passes/1-parser/pascaligo/dune b/src/passes/1-parser/pascaligo/dune index 908455acb..1c12ca706 100644 --- a/src/passes/1-parser/pascaligo/dune +++ b/src/passes/1-parser/pascaligo/dune @@ -10,15 +10,14 @@ (public_name ligo.parser.pascaligo) (modules AST pascaligo Parser ParserLog LexToken) (libraries - menhirLib - parser_shared - hex - simple-utils - tezos-utils - ) + menhirLib + parser_shared + hex + simple-utils + tezos-utils) (preprocess (pps bisect_ppx --conditional)) - (flags (:standard -open Parser_shared -open Simple_utils))) + (flags (:standard -open Parser_shared -open Simple_utils))) (executable (name LexerMain) @@ -33,7 +32,7 @@ (name ParserMain) (libraries parser_pascaligo) (modules - ParErr ParserAPI ParserMain) + ParErr ParserMain) (preprocess (pps bisect_ppx --conditional)) (flags (:standard -open Simple_utils -open Parser_shared -open Parser_pascaligo))) diff --git a/src/passes/1-parser/reasonligo/.links b/src/passes/1-parser/reasonligo/.links index e827ae13e..e972ad9c6 100644 --- a/src/passes/1-parser/reasonligo/.links +++ b/src/passes/1-parser/reasonligo/.links @@ -16,6 +16,10 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml ../shared/Markup.mli ../shared/Utils.mli ../shared/Utils.ml +../shared/ParserAPI.mli +../shared/ParserAPI.ml +../shared/LexerUnit.ml +../shared/ParserUnit.ml Stubs/Simple_utils.ml Stubs/Parser_cameligo.ml ../cameligo/AST.mli diff --git a/src/passes/1-parser/reasonligo/LexerMain.ml b/src/passes/1-parser/reasonligo/LexerMain.ml index b49af81ff..756a2f103 100644 --- a/src/passes/1-parser/reasonligo/LexerMain.ml +++ b/src/passes/1-parser/reasonligo/LexerMain.ml @@ -1,56 +1,9 @@ -(** Driver for the LIGO lexer *) +(** Driver for the ReasonLIGO lexer *) -let extension = ".religo" -let options = EvalOpt.read "ReasonLIGO" extension +module IO = + struct + let ext = ".religo" + let options = EvalOpt.read "ReasonLIGO" ext + end -(** Error printing and exception tracing -*) -let () = Printexc.record_backtrace true - -let external_ text = - Utils.highlight (Printf.sprintf "External error: %s" text); exit 1;; - -(** {1 Preprocessing the input source and opening the input channels} *) - -(** Path for CPP inclusions (#include) -*) -let lib_path = - match options#libs with - [] -> "" - | libs -> let mk_I dir path = Printf.sprintf " -I %s%s" dir path - in List.fold_right mk_I libs "" - -let prefix = - match options#input with - None | Some "-" -> "temp" - | Some file -> Filename.(file |> basename |> remove_extension) - -let suffix = ".pp" ^ extension - -let pp_input = - if Utils.String.Set.mem "cpp" options#verbose - then prefix ^ suffix - else let pp_input, pp_out = Filename.open_temp_file prefix suffix - in close_out pp_out; pp_input - -let cpp_cmd = - match options#input with - None | Some "-" -> - Printf.sprintf "cpp -traditional-cpp%s - > %s" - lib_path pp_input - | Some file -> - Printf.sprintf "cpp -traditional-cpp%s %s > %s" - lib_path file pp_input - -let () = - if Utils.String.Set.mem "cpp" options#verbose - then Printf.eprintf "%s\n%!" cpp_cmd; - if Sys.command cpp_cmd <> 0 then - external_ (Printf.sprintf "the command \"%s\" failed." cpp_cmd) - -(** {1 Running the lexer on the input file} *) - -module Log = LexerLog.Make (Lexer.Make (LexToken)) - -let () = Log.trace ~offsets:options#offsets - options#mode (Some pp_input) options#cmd +module M = LexerUnit.Make (IO) (Lexer.Make (LexToken)) diff --git a/src/passes/1-parser/reasonligo/ParserAPI.ml b/src/passes/1-parser/reasonligo/ParserAPI.ml deleted file mode 100644 index df82173a9..000000000 --- a/src/passes/1-parser/reasonligo/ParserAPI.ml +++ /dev/null @@ -1,82 +0,0 @@ -(* Generic parser for LIGO *) - -(* Main functor *) - -module Make (Lexer: Lexer.S with module Token := LexToken) - (Parser: module type of Parser) - (ParErr: sig val message : int -> string end) = - struct - module I = Parser.MenhirInterpreter - module S = MenhirLib.General (* Streams *) - - (* The call [stack checkpoint] extracts the parser's stack out of - a checkpoint. *) - - let stack = function - I.HandlingError env -> I.stack env - | _ -> assert false - - (* The call [state checkpoint] extracts the number of the current - state out of a parser checkpoint. *) - - let state checkpoint : int = - match Lazy.force (stack checkpoint) with - S.Nil -> 0 (* WARNING: Hack. The first state should be 0. *) - | S.Cons (I.Element (s,_,_,_),_) -> I.number s - - (* The parser has successfully produced a semantic value. *) - - let success v = v - - (* The parser has suspended itself because of a syntax error. Stop. *) - - type message = string - type valid = Lexer.token - type invalid = Lexer.token - type error = message * valid option * invalid - - exception Point of error - - let failure get_win checkpoint = - let message = ParErr.message (state checkpoint) in - match get_win () with - Lexer.Nil -> assert false - | Lexer.One invalid -> - raise (Point (message, None, invalid)) - | Lexer.Two (invalid, valid) -> - raise (Point (message, Some valid, invalid)) - - (* The two Menhir APIs are called from the following two functions. *) - - let incr_contract Lexer.{read; buffer; get_win; close; _} : AST.t = - let supplier = I.lexer_lexbuf_to_supplier read buffer - and failure = failure get_win in - let parser = Parser.Incremental.contract buffer.Lexing.lex_curr_p in - let ast = I.loop_handle success failure supplier parser - in close (); ast - - 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 diff --git a/src/passes/1-parser/reasonligo/ParserAPI.mli b/src/passes/1-parser/reasonligo/ParserAPI.mli deleted file mode 100644 index 7d969a33c..000000000 --- a/src/passes/1-parser/reasonligo/ParserAPI.mli +++ /dev/null @@ -1,22 +0,0 @@ -(** Generic parser API for LIGO *) - -module Make (Lexer: Lexer.S with module Token := LexToken) - (Parser: module type of Parser) - (ParErr: sig val message: int -> string end) : - sig - (* Monolithic and incremental APIs of Menhir for parsing *) - - val mono_contract : (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> 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 diff --git a/src/passes/1-parser/reasonligo/ParserMain.ml b/src/passes/1-parser/reasonligo/ParserMain.ml index 0af4c4a76..ee7d562de 100644 --- a/src/passes/1-parser/reasonligo/ParserMain.ml +++ b/src/passes/1-parser/reasonligo/ParserMain.ml @@ -1,145 +1,27 @@ -(** Driver for the Reason LIGO parser *) +(** Driver for the ReasonLIGO parser *) -let extension = ".religo" -let options = EvalOpt.read "ReasonLIGO" extension +module IO = + struct + let ext = ".religo" + let options = EvalOpt.read "ReasonLIGO" ext + end -open Printf +module ExtParser = + struct + type ast = AST.t + type expr = AST.expr + include Parser + end -(** Error printing and exception tracing -*) -let () = Printexc.record_backtrace true +module ExtParserLog = + struct + type ast = AST.t + include ParserLog + end -(** Extracting the input file -*) -let file = - match options#input with - None | Some "-" -> false - | Some _ -> true - -(** {1 Error printing and exception tracing} *) - -let () = Printexc.record_backtrace true - -let external_ text = - Utils.highlight (sprintf "External error: %s" text); exit 1;; - -(** {1 Preprocessing the input source and opening the input channels} *) - -(** Path for CPP inclusions (#include) -*) -let lib_path = - match options#libs with - [] -> "" - | libs -> let mk_I dir path = sprintf " -I %s%s" dir path - in List.fold_right mk_I libs "" - -let prefix = - match options#input with - None | Some "-" -> "temp" - | Some file -> Filename.(file |> basename |> remove_extension) - -let suffix = ".pp" ^ extension - -let pp_input = - if Utils.String.Set.mem "cpp" options#verbose - then prefix ^ suffix - else let pp_input, pp_out = Filename.open_temp_file prefix suffix - in close_out pp_out; pp_input - -let cpp_cmd = - match options#input with - None | Some "-" -> - sprintf "cpp -traditional-cpp%s - > %s" - lib_path pp_input - | Some file -> - sprintf "cpp -traditional-cpp%s %s > %s" - lib_path file pp_input - -let () = - if Utils.String.Set.mem "cpp" options#verbose - then eprintf "%s\n%!" cpp_cmd; - if Sys.command cpp_cmd <> 0 then - external_ (sprintf "the command \"%s\" failed." cpp_cmd) - -(** {1 Instanciating the lexer} *) - -module Lexer = Lexer.Make (LexToken) -module Log = LexerLog.Make (Lexer) -module ParserFront = ParserAPI.Make (Lexer) (Parser) (ParErr) - -let lexer_inst = Lexer.open_token_stream (Some pp_input) -let Lexer.{read; buffer; get_win; get_pos; get_last; close} = lexer_inst - -and cout = stdout - -let log = Log.output_token ~offsets:options#offsets - options#mode options#cmd cout - -and close_all () = close (); close_out cout - -(** {1 Tokeniser} *) - -let tokeniser = read ~log - -(** {1 Main} *) - -let () = - try - let ast = - if options#mono - then ParserFront.mono_contract tokeniser buffer - else ParserFront.incr_contract lexer_inst in - if Utils.String.Set.mem "ast" options#verbose - then let buffer = Buffer.create 131 in - let state = ParserLog.mk_state - ~offsets:options#offsets - ~mode:options#mode - ~buffer in - begin - ParserLog.pp_ast state ast; - Buffer.output_buffer stdout buffer - end - else if Utils.String.Set.mem "ast-tokens" options#verbose - then let buffer = Buffer.create 131 in - let state = ParserLog.mk_state - ~offsets:options#offsets - ~mode:options#mode - ~buffer in - begin - ParserLog.print_tokens state ast; - Buffer.output_buffer stdout buffer - end - with - (* Lexing errors *) - Lexer.Error err -> - close_all (); - let msg = - Lexer.format_error ~offsets:options#offsets - options#mode err ~file - in prerr_string msg - - (* Incremental API of Menhir *) - | ParserFront.Point point -> - let () = close_all () in - let error = - 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 +module M = ParserUnit.Make (IO) + (Lexer.Make (LexToken)) + (AST) + (ExtParser) + (ParErr) + (ExtParserLog) diff --git a/src/passes/1-parser/reasonligo/dune b/src/passes/1-parser/reasonligo/dune index 12b0c6d27..63faf40ba 100644 --- a/src/passes/1-parser/reasonligo/dune +++ b/src/passes/1-parser/reasonligo/dune @@ -36,7 +36,7 @@ parser_reasonligo parser_cameligo) (modules - ParErr ParserAPI ParserMain) + ParErr ParserMain) (preprocess (pps bisect_ppx --conditional)) (flags (:standard -open Simple_utils -open Parser_cameligo -open Parser_shared -open Parser_reasonligo))) diff --git a/src/passes/1-parser/cameligo/ParserAPI.ml b/src/passes/1-parser/shared/ParserAPI.ml similarity index 59% rename from src/passes/1-parser/cameligo/ParserAPI.ml rename to src/passes/1-parser/shared/ParserAPI.ml index df82173a9..e24be2b48 100644 --- a/src/passes/1-parser/cameligo/ParserAPI.ml +++ b/src/passes/1-parser/shared/ParserAPI.ml @@ -1,9 +1,47 @@ (* Generic parser for LIGO *) +module type PARSER = + sig + (* The type of tokens, abstract syntax trees and expressions *) + + type token + type ast + type expr + + (* This exception is raised by the monolithic API functions. *) + + exception Error + + (* The monolithic API. *) + + val interactive_expr : + (Lexing.lexbuf -> token) -> Lexing.lexbuf -> expr + val contract : + (Lexing.lexbuf -> token) -> Lexing.lexbuf -> ast + + module MenhirInterpreter : + sig + (* The incremental API. *) + + include MenhirLib.IncrementalEngine.INCREMENTAL_ENGINE + with type token = token + end + + (* The entry point(s) to the incremental API. *) + + module Incremental : + sig + val interactive_expr : + Lexing.position -> expr MenhirInterpreter.checkpoint + val contract : + Lexing.position -> ast MenhirInterpreter.checkpoint + end + end + (* Main functor *) -module Make (Lexer: Lexer.S with module Token := LexToken) - (Parser: module type of Parser) +module Make (Lexer: Lexer.S) + (Parser: PARSER with type token = Lexer.Token.token) (ParErr: sig val message : int -> string end) = struct module I = Parser.MenhirInterpreter @@ -31,9 +69,9 @@ module Make (Lexer: Lexer.S with module Token := LexToken) (* The parser has suspended itself because of a syntax error. Stop. *) type message = string - type valid = Lexer.token - type invalid = Lexer.token - type error = message * valid option * invalid + type valid = Parser.token + type invalid = Parser.token + type error = message * valid option * invalid exception Point of error @@ -48,7 +86,7 @@ module Make (Lexer: Lexer.S with module Token := LexToken) (* The two Menhir APIs are called from the following two functions. *) - let incr_contract Lexer.{read; buffer; get_win; close; _} : AST.t = + let incr_contract Lexer.{read; buffer; get_win; close; _} : Parser.ast = let supplier = I.lexer_lexbuf_to_supplier read buffer and failure = failure get_win in let parser = Parser.Incremental.contract buffer.Lexing.lex_curr_p in @@ -60,21 +98,21 @@ module Make (Lexer: Lexer.S with module Token := LexToken) (* Errors *) let format_error ?(offsets=true) mode (msg, valid_opt, invalid) = - let invalid_region = LexToken.to_region invalid in + let invalid_region = Lexer.Token.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 + if Lexer.Token.is_eof invalid then "" + else let invalid_lexeme = Lexer.Token.to_lexeme invalid in Printf.sprintf ", before \"%s\"" invalid_lexeme | Some valid -> - let valid_lexeme = LexToken.to_lexeme valid in + let valid_lexeme = Lexer.Token.to_lexeme valid in let s = Printf.sprintf ", after \"%s\"" valid_lexeme in - if LexToken.is_eof invalid then s + if Lexer.Token.is_eof invalid then s else - let invalid_lexeme = LexToken.to_lexeme invalid in + let invalid_lexeme = Lexer.Token.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) diff --git a/src/passes/1-parser/shared/ParserAPI.mli b/src/passes/1-parser/shared/ParserAPI.mli new file mode 100644 index 000000000..79ca137c4 --- /dev/null +++ b/src/passes/1-parser/shared/ParserAPI.mli @@ -0,0 +1,60 @@ +(* Generic parser API for LIGO *) + +module type PARSER = + sig + (* The type of tokens. *) + + type token + type ast + type expr + + (* This exception is raised by the monolithic API functions. *) + + exception Error + + (* The monolithic API. *) + + val interactive_expr : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> expr + val contract : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> ast + + (* The incremental API. *) + + module MenhirInterpreter : + sig + include MenhirLib.IncrementalEngine.INCREMENTAL_ENGINE + with type token = token + end + + (* The entry point(s) to the incremental API. *) + + module Incremental : + sig + val interactive_expr : + Lexing.position -> expr MenhirInterpreter.checkpoint + val contract : + Lexing.position -> ast MenhirInterpreter.checkpoint + end + end + +module Make (Lexer: Lexer.S) + (Parser: PARSER with type token = Lexer.Token.token) + (ParErr: sig val message : int -> string end) : + sig + (* Monolithic and incremental APIs of Menhir for parsing *) + + val mono_contract : + (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> Parser.ast + val incr_contract : + Lexer.instance -> Parser.ast + + (* Error handling *) + + type message = string + type valid = Parser.token + type invalid = Parser.token + type error = message * valid option * invalid + + exception Point of error + + val format_error : ?offsets:bool -> [`Byte | `Point] -> error -> string + end diff --git a/src/passes/1-parser/shared/dune b/src/passes/1-parser/shared/dune index ca41804a8..10e377a93 100644 --- a/src/passes/1-parser/shared/dune +++ b/src/passes/1-parser/shared/dune @@ -4,15 +4,17 @@ (name parser_shared) (public_name ligo.parser.shared) (libraries + menhirLib simple-utils uutf getopt - zarith - ) + zarith) (preprocess - (pps bisect_ppx --conditional) - ) + (pps bisect_ppx --conditional)) (modules + LexerUnit + ParserUnit + ParserAPI Lexer LexerLog Utils