From 37faf9022efb82dc95e81ae229a48b252e755701 Mon Sep 17 00:00:00 2001 From: Christian Rinderknecht Date: Mon, 23 Mar 2020 19:43:06 +0100 Subject: [PATCH] [WIP] Does not compile yet. --- vendors/Preproc/{.EMain.tag => .E_Main.tag} | 0 .../{.Eparser.mly.tag => .E_Parser.mly.tag} | 0 vendors/Preproc/.links | 4 + vendors/Preproc/EMain.ml | 33 - vendors/Preproc/{Etree.ml => E_AST.ml} | 0 vendors/Preproc/E_Lexer.mll | 108 +++ vendors/Preproc/E_Main.ml | 53 ++ vendors/Preproc/E_Parser.mly | 50 ++ vendors/Preproc/Eparser.mly | 50 -- vendors/Preproc/Error.ml | 31 - vendors/Preproc/Escan.mll | 95 --- vendors/Preproc/EvalOpt.ml | 105 +++ vendors/Preproc/EvalOpt.mli | 25 + vendors/Preproc/Preproc.mll | 664 ++++++++++-------- vendors/Preproc/ProcMain.ml | 6 +- vendors/Preproc/build.sh | 6 +- vendors/Preproc/dune | 15 +- 17 files changed, 745 insertions(+), 500 deletions(-) rename vendors/Preproc/{.EMain.tag => .E_Main.tag} (100%) rename vendors/Preproc/{.Eparser.mly.tag => .E_Parser.mly.tag} (100%) delete mode 100644 vendors/Preproc/EMain.ml rename vendors/Preproc/{Etree.ml => E_AST.ml} (100%) create mode 100644 vendors/Preproc/E_Lexer.mll create mode 100644 vendors/Preproc/E_Main.ml create mode 100644 vendors/Preproc/E_Parser.mly delete mode 100644 vendors/Preproc/Eparser.mly delete mode 100644 vendors/Preproc/Error.ml delete mode 100644 vendors/Preproc/Escan.mll create mode 100644 vendors/Preproc/EvalOpt.ml create mode 100644 vendors/Preproc/EvalOpt.mli diff --git a/vendors/Preproc/.EMain.tag b/vendors/Preproc/.E_Main.tag similarity index 100% rename from vendors/Preproc/.EMain.tag rename to vendors/Preproc/.E_Main.tag diff --git a/vendors/Preproc/.Eparser.mly.tag b/vendors/Preproc/.E_Parser.mly.tag similarity index 100% rename from vendors/Preproc/.Eparser.mly.tag rename to vendors/Preproc/.E_Parser.mly.tag diff --git a/vendors/Preproc/.links b/vendors/Preproc/.links index 71ff816cb..a79e26681 100644 --- a/vendors/Preproc/.links +++ b/vendors/Preproc/.links @@ -1 +1,5 @@ $HOME/git/OCaml-build/Makefile +$HOME/git/ligo/vendors/ligo-utils/simple-utils/pos.mli +$HOME/git/ligo/vendors/ligo-utils/simple-utils/pos.ml +$HOME/git/ligo/vendors/ligo-utils/simple-utils/region.mli +$HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml diff --git a/vendors/Preproc/EMain.ml b/vendors/Preproc/EMain.ml deleted file mode 100644 index 7108f35ca..000000000 --- a/vendors/Preproc/EMain.ml +++ /dev/null @@ -1,33 +0,0 @@ -(* This module is only used for testing modules [Escan] and [Eparser] - as units *) - -module Lexer = struct - let run () = - match Array.length Sys.argv with - 2 -> Escan.trace Sys.argv.(1) - | _ -> prerr_endline ("Usage: " ^ Sys.argv.(0) ^ " [file]") -end - -module Parser = struct - let run () = - if Array.length Sys.argv = 2 - then - match open_in Sys.argv.(1) with - exception Sys_error msg -> prerr_endline msg - | cin -> - let buffer = Lexing.from_channel cin in - let open Error in - let () = - try - let tree = Eparser.pp_expression Escan.token buffer in - let value = Preproc.(eval Env.empty tree) - in (print_string (string_of_bool value); - print_newline ()) - with Lexer diag -> print "Lexical" diag - | Parser diag -> print "Syntactical" diag - | Eparser.Error -> print "" ("Parse", mk_seg buffer, 1) - in close_in cin - else prerr_endline ("Usage: " ^ Sys.argv.(0) ^ " [file]") -end - -let _ = Parser.run() diff --git a/vendors/Preproc/Etree.ml b/vendors/Preproc/E_AST.ml similarity index 100% rename from vendors/Preproc/Etree.ml rename to vendors/Preproc/E_AST.ml diff --git a/vendors/Preproc/E_Lexer.mll b/vendors/Preproc/E_Lexer.mll new file mode 100644 index 000000000..814cf0e6d --- /dev/null +++ b/vendors/Preproc/E_Lexer.mll @@ -0,0 +1,108 @@ +(* Auxiliary scanner for boolean expressions of the C# preprocessor *) + +{ +(* START HEADER *) + +module Region = Simple_utils.Region +module Pos = Simple_utils.Pos + +let sprintf = Printf.sprintf + +open E_Parser + +(* Concrete syntax of tokens. See module [E_Parser]. *) + +let string_of_token = function + True -> "true" +| False -> "false" +| Ident id -> id +| OR -> "||" +| AND -> "&&" +| EQ -> "==" +| NEQ -> "!=" +| NOT -> "!" +| LPAR -> "(" +| RPAR -> ")" +| EOL -> "EOL" + +(* Errors *) + +module Error = + struct + type t = Invalid_character of char + + let to_string = function + Invalid_character c -> + sprintf "Invalid character '%c' (%d).\n" c (Char.code c) + + let format ?(offsets=true) Region.{region; value} ~file = + let msg = to_string value + and reg = region#to_string ~file ~offsets `Byte in + let value = sprintf "Preprocessing error %s:\n%s" reg msg + in Region.{value; region} + end + +exception Error of Error.t Region.reg + +let mk_reg buffer = + let start = Lexing.lexeme_start_p buffer |> Pos.from_byte + and stop = Lexing.lexeme_end_p buffer |> Pos.from_byte + in Region.make ~start ~stop + +let stop value region = raise (Error Region.{region; value}) +let fail error buffer = stop error (mk_reg buffer) + +(* END HEADER *) +} + +(* Regular expressions for literals *) + +(* White space *) + +let newline = '\n' | '\r' | "\r\n" +let blank = ' ' | '\t' + +(* Unicode escape sequences *) + +let digit = ['0'-'9'] +let hexdigit = digit | ['A'-'F' 'a'-'f'] +let four_hex = hexdigit hexdigit hexdigit hexdigit +let uni_esc = "\\u" four_hex | "\\U" four_hex four_hex + +(* Identifiers *) + +let lowercase = ['a'-'z'] +let uppercase = ['A'-'Z'] +let letter = lowercase | uppercase | uni_esc +let start = '_' | letter +let alphanum = letter | digit | '_' +let ident = start alphanum* + +(* Rules *) + +rule scan = parse + blank+ { scan lexbuf } +| newline { Lexing.new_line lexbuf; EOL } +| eof { EOL } +| "true" { True } +| "false" { False } +| ident as id { Ident id } +| '(' { LPAR } +| ')' { RPAR } +| "||" { OR } +| "&&" { AND } +| "==" { EQ } +| "!=" { NEQ } +| "!" { NOT } +| "//" { inline_com lexbuf } +| _ as c { fail (Error.Invalid_character c) lexbuf } + +and inline_com = parse + newline { Lexing.new_line lexbuf; EOL } +| eof { EOL } +| _ { inline_com lexbuf } + +{ + (* START TRAILER *) + (* END TRAILER *) +} diff --git a/vendors/Preproc/E_Main.ml b/vendors/Preproc/E_Main.ml new file mode 100644 index 000000000..0e5d79fdf --- /dev/null +++ b/vendors/Preproc/E_Main.ml @@ -0,0 +1,53 @@ +(* This module is only used for testing modules [Escan] and [E_Parser] + as units *) + +module Lexer = struct + open E_Lexer + + let run () = + let options = EvalOpt.read () in + match open_in options#input with + cin -> + let buffer = Lexing.from_channel cin in + let rec iter () = + match E_Lexer.scan buffer with + E_Parser.EOL -> close_in cin; close_out stdout + | t -> begin + output_string stdout (string_of_token t); + output_string stdout "\n"; + flush stdout; + iter () + end + | exception E_Lexer.Error err -> + let form = Error.format ~offsets:options#offsets + err + ~file:options#input + in output_string stdout (form ^ "\n") + in iter () + | exception Sys_error msg -> prerr_endline msg + +end + +module Parser = struct + let run () = + if Array.length Sys.argv = 2 + then + match open_in Sys.argv.(1) with + exception Sys_error msg -> prerr_endline msg + | cin -> + let buffer = Lexing.from_channel cin in + let open Error in + let () = + try + let tree = E_Parser.pp_expression E_Lexer.token buffer in + let value = Preproc.(eval Env.empty tree) + in (print_string (string_of_bool value); + print_newline ()) + with Lexer diag -> print "Lexical" diag + | Parser diag -> print "Syntactical" diag + | E_Parser.Error -> print "" ("Parse", mk_seg buffer, 1) + in close_in cin + else prerr_endline ("Usage: " ^ Sys.argv.(0) ^ " [file]") +end + +let _ = Parser.run() diff --git a/vendors/Preproc/E_Parser.mly b/vendors/Preproc/E_Parser.mly new file mode 100644 index 000000000..8405426c7 --- /dev/null +++ b/vendors/Preproc/E_Parser.mly @@ -0,0 +1,50 @@ +%{ +(* Grammar for boolean expressions in preprocessing directives of C# *) +%} + +%token Ident "" +%token True "true" +%token False "false" +%token OR "||" +%token AND "&&" +%token EQ "==" +%token NEQ "!=" +%token NOT "!" +%token LPAR "(" +%token RPAR ")" +%token EOL + +(* Entries *) + +%start expr +%type expr + +%% + +(* Grammar *) + +expr: + or_expr EOL { $1 } + +or_expr: + or_expr "||" and_expr { E_AST.Or ($1,$3) } +| and_expr { $1 } + +and_expr: + and_expr "&&" unary_expr { E_AST.And ($1,$3) } +| equality_expr { $1 } + +equality_expr: + equality_expr "==" unary_expr { E_AST.Eq ($1,$3) } +| equality_expr "!=" unary_expr { E_AST.Neq ($1,$3) } +| unary_expr { $1 } + +unary_expr: + primary_expr { $1 } +| "!" unary_expr { E_AST.Not $2 } + +primary_expr: + "true" { E_AST.True } +| "false" { E_AST.False } +| "" { E_AST.Ident $1 } +| "(" or_expr ")" { $2 } diff --git a/vendors/Preproc/Eparser.mly b/vendors/Preproc/Eparser.mly deleted file mode 100644 index 19462a8da..000000000 --- a/vendors/Preproc/Eparser.mly +++ /dev/null @@ -1,50 +0,0 @@ -%{ -(* Grammar for boolean expressions in preprocessing directives of C# *) -%} - -%token True False -%token Ident -%token OR AND EQ NEQ NOT EOL LPAR RPAR - -(* Entries *) - -%start pp_expression -%type pp_expression - -%% - -(* Grammar *) - -pp_expression: - e=pp_or_expression EOL { e } - -pp_or_expression: - e=pp_and_expression { e } -| e1=pp_or_expression OR e2=pp_and_expression { - Etree.Or (e1,e2) - } - -pp_and_expression: - e=pp_equality_expression { e } -| e1=pp_and_expression AND e2=pp_unary_expression { - Etree.And (e1,e2) - } - -pp_equality_expression: - e=pp_unary_expression { e } -| e1=pp_equality_expression EQ e2=pp_unary_expression { - Etree.Eq (e1,e2) - } -| e1=pp_equality_expression NEQ e2=pp_unary_expression { - Etree.Neq (e1,e2) - } - -pp_unary_expression: - e=pp_primary_expression { e } -| NOT e=pp_unary_expression { Etree.Not e } - -pp_primary_expression: - True { Etree.True } -| False { Etree.False } -| id=Ident { Etree.Ident id } -| LPAR e=pp_or_expression RPAR { e } diff --git a/vendors/Preproc/Error.ml b/vendors/Preproc/Error.ml deleted file mode 100644 index cf7f342f9..000000000 --- a/vendors/Preproc/Error.ml +++ /dev/null @@ -1,31 +0,0 @@ -(* This module provides support for managing and printing errors when - preprocessing C# source files. *) - -type message = string -type start = Lexing.position -type stop = Lexing.position -type seg = start * stop - -let mk_seg buffer = - Lexing.(lexeme_start_p buffer, lexeme_end_p buffer) - -type vline = int - -exception Lexer of (message * seg * vline) -exception Parser of (message * seg * vline) - -let print (kind: string) (msg, (start, stop), vend) = - let open Lexing in - let delta = vend - stop.pos_lnum in - let vstart = start.pos_lnum + delta -in assert (msg <> ""); - prerr_endline - ((if kind = "" then msg else kind) ^ " error at line " - ^ string_of_int vstart ^ ", char " - ^ string_of_int (start.pos_cnum - start.pos_bol) - ^ (if stop.pos_lnum = start.pos_lnum - then "--" ^ string_of_int (stop.pos_cnum - stop.pos_bol) - else " to line " ^ string_of_int vend - ^ ", char " - ^ string_of_int (stop.pos_cnum - stop.pos_bol)) - ^ (if kind = "" then "." else ":\n" ^ msg)) diff --git a/vendors/Preproc/Escan.mll b/vendors/Preproc/Escan.mll deleted file mode 100644 index 23becbf76..000000000 --- a/vendors/Preproc/Escan.mll +++ /dev/null @@ -1,95 +0,0 @@ -{ -(* Auxiliary scanner for boolean expressions of the C# preprocessor *) - -(* Concrete syntax of tokens. See module [Eparser]. *) - -let string_of_token = - let open Eparser -in function True -> "true" - | False -> "false" - | Ident id -> id - | OR -> "||" - | AND -> "&&" - | EQ -> "==" - | NEQ -> "!=" - | NOT -> "!" - | LPAR -> "(" - | RPAR -> ")" - | EOL -> "EOL" - -} - -(* Regular expressions for literals *) - -(* White space *) - -let newline = '\n' | '\r' | "\r\n" -let blank = ' ' | '\t' - -(* Unicode escape sequences *) - -let digit = ['0'-'9'] -let hexdigit = digit | ['A'-'F' 'a'-'f'] -let four_hex = hexdigit hexdigit hexdigit hexdigit -let uni_esc = "\\u" four_hex | "\\U" four_hex four_hex - -(* Identifiers *) - -let lowercase = ['a'-'z'] -let uppercase = ['A'-'Z'] -let letter = lowercase | uppercase | uni_esc -let start = '_' | letter -let alphanum = letter | digit | '_' -let ident = start alphanum* - -(* Rules *) - -rule token = parse - blank+ { token lexbuf } -| newline { Lexing.new_line lexbuf; Eparser.EOL } -| eof { Eparser.EOL } -| "true" { Eparser.True } -| "false" { Eparser.False } -| ident as id { Eparser.Ident id } -| '(' { Eparser.LPAR } -| ')' { Eparser.RPAR } -| "||" { Eparser.OR } -| "&&" { Eparser.AND } -| "==" { Eparser.EQ } -| "!=" { Eparser.NEQ } -| "!" { Eparser.NOT } -| "//" { inline_com lexbuf } -| _ as c { let code = Char.code c in - let msg = "Invalid character " ^ String.make 1 c - ^ " (" ^ string_of_int code ^ ")." - in raise Error.(Lexer (msg, mk_seg lexbuf, 1)) - } - -and inline_com = parse - newline { Lexing.new_line lexbuf; Eparser.EOL } -| eof { Eparser.EOL } -| _ { inline_com lexbuf } - -{ -(* Standalone lexer for debugging purposes. See module [Topexp]. *) - -type filename = string - -let trace (name: filename) = - match open_in name with - cin -> - let buffer = Lexing.from_channel cin - and cout = stdout in - let rec iter () = - match token buffer with - Eparser.EOL -> close_in cin; close_out cout - | t -> begin - output_string cout (string_of_token t); - output_string cout "\n"; - flush cout; - iter () - end - | exception Error.Lexer diag -> Error.print "Lexical" diag - in iter () - | exception Sys_error msg -> prerr_endline msg -} diff --git a/vendors/Preproc/EvalOpt.ml b/vendors/Preproc/EvalOpt.ml new file mode 100644 index 000000000..99ffbe8bf --- /dev/null +++ b/vendors/Preproc/EvalOpt.ml @@ -0,0 +1,105 @@ +(* Parsing command-line options *) + +(* The type [options] gathers the command-line options. *) + +type language = PascaLIGO | CameLIGO | ReasonLIGO + +type options = < + input : string; + libs : string list; + lang : language; + offsets : bool +> + +let make ~input ~libs ~lang ~offsets = + object + method input = input + method libs = libs + method lang = lang + method offsets = offsets + end + +(* Auxiliary functions and modules *) + +let printf = Printf.printf +let sprintf = Printf.sprintf +let print = print_endline + +(* Printing a string in red to standard error *) + +let highlight msg = Printf.eprintf "\027[31m%s\027[0m%!" msg + +(* Failure *) + +let abort msg = + highlight (sprintf "Command-line error: %s\n" msg); exit 1 + +(* Help *) + +let help () = + let file = Filename.basename Sys.argv.(0) in + printf "Usage: %s [