Merge branch 'rinderknecht-dev' into 'dev'

Refactoring of the front-end

See merge request ligolang/ligo!332
This commit is contained in:
Christian Rinderknecht 2020-01-22 13:52:03 +00:00
commit 7828b57636
85 changed files with 3043 additions and 2042 deletions

View File

@ -99,9 +99,9 @@ ligo: lexer error: Negative byte sequence.
run_ligo_bad [ "compile-contract" ; "../../test/lexer/reserved_name.ligo" ; "main" ] ; run_ligo_bad [ "compile-contract" ; "../../test/lexer/reserved_name.ligo" ; "main" ] ;
[%expect {| [%expect {|
ligo: lexer error: Reserved name: args. ligo: lexer error: Reserved name: arguments.
Hint: Change the name. Hint: Change the name.
{"parser_loc":"in file \"reserved_name.ligo\", line 1, characters 4-8"} {"parser_loc":"in file \"reserved_name.ligo\", line 1, characters 4-13"}
If you're not sure how to fix this error, you can If you're not sure how to fix this error, you can

View File

@ -137,17 +137,17 @@ let parsify_string = fun (syntax : v_syntax) source_filename ->
let pretty_print_pascaligo = fun source -> let pretty_print_pascaligo = fun source ->
let%bind ast = Parser.Pascaligo.parse_file source in let%bind ast = Parser.Pascaligo.parse_file source in
let buffer = Buffer.create 59 in let buffer = Buffer.create 59 in
let state = Parser.Pascaligo.ParserLog.mk_state let state = Parser_pascaligo.ParserLog.mk_state
~offsets:true ~offsets:true
~mode:`Byte ~mode:`Byte
~buffer in ~buffer in
Parser.Pascaligo.ParserLog.pp_ast state ast; Parser_pascaligo.ParserLog.pp_ast state ast;
ok buffer ok buffer
let pretty_print_cameligo = fun source -> let pretty_print_cameligo = fun source ->
let%bind ast = Parser.Cameligo.parse_file source in let%bind ast = Parser.Cameligo.parse_file source in
let buffer = Buffer.create 59 in let buffer = Buffer.create 59 in
let state = Parser.Cameligo.ParserLog.mk_state let state = Parser_cameligo.ParserLog.mk_state
~offsets:true ~offsets:true
~mode:`Byte ~mode:`Byte
~buffer in ~buffer in

View File

@ -18,7 +18,7 @@ module Errors = struct
] in ] in
error ~data title message error ~data title message
let parser_error source (start: Lexing.position) (end_: Lexing.position) lexbuf = let parser_error source (start: Lexing.position) (stop: Lexing.position) lexbuf =
let title () = "parser error" in let title () = "parser error" in
let file = if source = "" then let file = if source = "" then
"" ""
@ -29,18 +29,18 @@ module Errors = struct
"Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n" "Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
(Lexing.lexeme lexbuf) (Lexing.lexeme lexbuf)
start.pos_lnum (start.pos_cnum - start.pos_bol) start.pos_lnum (start.pos_cnum - start.pos_bol)
end_.pos_lnum (end_.pos_cnum - end_.pos_bol) stop.pos_lnum (stop.pos_cnum - stop.pos_bol)
file file
in in
let message () = str in let message () = str in
let loc = if start.pos_cnum = -1 then let loc = if start.pos_cnum = -1 then
Region.make Region.make
~start: Pos.min ~start:(Pos.min ~file:source)
~stop:(Pos.from_byte end_) ~stop:(Pos.from_byte stop)
else else
Region.make Region.make
~start:(Pos.from_byte start) ~start:(Pos.from_byte start)
~stop:(Pos.from_byte end_) ~stop:(Pos.from_byte stop)
in in
let data = let data =
[ [
@ -51,7 +51,7 @@ module Errors = struct
in in
error ~data title message error ~data title message
let unrecognized_error source (start: Lexing.position) (end_: Lexing.position) lexbuf = let unrecognized_error source (start: Lexing.position) (stop: Lexing.position) lexbuf =
let title () = "unrecognized error" in let title () = "unrecognized error" in
let file = if source = "" then let file = if source = "" then
"" ""
@ -62,13 +62,13 @@ module Errors = struct
"Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n" "Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
(Lexing.lexeme lexbuf) (Lexing.lexeme lexbuf)
start.pos_lnum (start.pos_cnum - start.pos_bol) start.pos_lnum (start.pos_cnum - start.pos_bol)
end_.pos_lnum (end_.pos_cnum - end_.pos_bol) stop.pos_lnum (stop.pos_cnum - stop.pos_bol)
file file
in in
let message () = str in let message () = str in
let loc = Region.make let loc = Region.make
~start:(Pos.from_byte start) ~start:(Pos.from_byte start)
~stop:(Pos.from_byte end_) ~stop:(Pos.from_byte stop)
in in
let data = [ let data = [
("unrecognized_loc", ("unrecognized_loc",
@ -91,15 +91,15 @@ let parse (parser: 'a parser) source lexbuf =
with with
| Parser.Error -> | Parser.Error ->
let start = Lexing.lexeme_start_p lexbuf in let start = Lexing.lexeme_start_p lexbuf in
let end_ = Lexing.lexeme_end_p lexbuf in let stop = Lexing.lexeme_end_p lexbuf in
fail @@ (parser_error source start end_ lexbuf) fail @@ (parser_error source start stop lexbuf)
| Lexer.Error e -> | Lexer.Error e ->
fail @@ (lexer_error e) fail @@ (lexer_error e)
| _ -> | _ ->
let _ = Printexc.print_backtrace Pervasives.stdout in let _ = Printexc.print_backtrace Pervasives.stdout in
let start = Lexing.lexeme_start_p lexbuf in let start = Lexing.lexeme_start_p lexbuf in
let end_ = Lexing.lexeme_end_p lexbuf in let stop = Lexing.lexeme_end_p lexbuf in
fail @@ (unrecognized_error source start end_ lexbuf) fail @@ (unrecognized_error source start stop lexbuf)
in in
close (); close ();
result result
@ -122,8 +122,8 @@ let parse_file (source: string) : AST.t result =
let parse_string (s:string) : AST.t result = let parse_string (s:string) : AST.t result =
let lexbuf = Lexing.from_string s in let lexbuf = Lexing.from_string s in
parse (Parser.contract) "" lexbuf parse Parser.contract "" lexbuf
let parse_expression (s:string) : AST.expr result = let parse_expression (s:string) : AST.expr result =
let lexbuf = Lexing.from_string s in let lexbuf = Lexing.from_string s in
parse (Parser.interactive_expr) "" lexbuf parse Parser.interactive_expr "" lexbuf

View File

@ -1,5 +1,4 @@
$HOME/git/OCaml-build/Makefile $HOME/git/OCaml-build/Makefile
$HOME/git/OCaml-build/Makefile.cfg
$HOME/git/ligo/vendors/ligo-utils/simple-utils/pos.mli $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/pos.ml
$HOME/git/ligo/vendors/ligo-utils/simple-utils/region.mli $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.mli

View File

@ -21,15 +21,6 @@ open Utils
type 'a reg = 'a Region.reg type 'a reg = 'a Region.reg
let rec last to_region = function
[] -> Region.ghost
| [x] -> to_region x
| _::t -> last to_region t
let nsepseq_to_region to_region (hd,tl) =
let reg (_, item) = to_region item in
Region.cover (to_region hd) (last reg tl)
(* Keywords of OCaml *) (* Keywords of OCaml *)
type keyword = Region.t type keyword = Region.t
@ -321,6 +312,7 @@ and comp_expr =
| Neq of neq bin_op reg | Neq of neq bin_op reg
and record = field_assign reg ne_injection and record = field_assign reg ne_injection
and projection = { and projection = {
struct_name : variable; struct_name : variable;
selector : dot; selector : dot;
@ -344,6 +336,7 @@ and update = {
updates : record reg; updates : record reg;
rbrace : rbrace; rbrace : rbrace;
} }
and path = and path =
Name of variable Name of variable
| Path of projection reg | Path of projection reg
@ -387,7 +380,16 @@ and cond_expr = {
ifnot : expr ifnot : expr
} }
(* Projecting regions of the input source code *) (* Projecting regions from some nodes of the AST *)
let rec last to_region = function
[] -> Region.ghost
| [x] -> to_region x
| _::t -> last to_region t
let nsepseq_to_region to_region (hd,tl) =
let reg (_, item) = to_region item in
Region.cover (to_region hd) (last reg tl)
let type_expr_to_region = function let type_expr_to_region = function
TProd {region; _} TProd {region; _}

View File

@ -85,7 +85,7 @@ type t =
| Mutez of (string * Z.t) Region.reg | Mutez of (string * Z.t) Region.reg
| String of string Region.reg | String of string Region.reg
| Bytes of (string * Hex.t) Region.reg | Bytes of (string * Hex.t) Region.reg
| Attr2 of string Region.reg | Attr of string Region.reg
(* Keywords *) (* Keywords *)
@ -150,8 +150,7 @@ val mk_kwd : lexeme -> Region.t -> (token, kwd_err) result
val mk_string : lexeme -> Region.t -> token val mk_string : lexeme -> Region.t -> token
val mk_bytes : lexeme -> Region.t -> token val mk_bytes : lexeme -> Region.t -> token
val mk_constr : lexeme -> Region.t -> token val mk_constr : lexeme -> Region.t -> token
val mk_attr : lexeme -> Region.t -> (token, attr_err) result val mk_attr : string -> lexeme -> Region.t -> (token, attr_err) result
val mk_attr2 : lexeme -> Region.t -> (token, attr_err) result
val eof : Region.t -> token val eof : Region.t -> token
(* Predicates *) (* Predicates *)

View File

@ -69,7 +69,7 @@ type t =
| Mutez of (string * Z.t) Region.reg | Mutez of (string * Z.t) Region.reg
| String of string Region.reg | String of string Region.reg
| Bytes of (string * Hex.t) Region.reg | Bytes of (string * Hex.t) Region.reg
| Attr2 of string Region.reg | Attr of string Region.reg
(* Keywords *) (* Keywords *)
@ -147,6 +147,8 @@ let proj_token = function
region, region,
sprintf "Bytes (\"%s\", \"0x%s\")" sprintf "Bytes (\"%s\", \"0x%s\")"
s (Hex.show b) s (Hex.show b)
| Attr Region.{region; value} ->
region, sprintf "Attr \"%s\"" value
| Begin region -> region, "Begin" | Begin region -> region, "Begin"
| Else region -> region, "Else" | Else region -> region, "Else"
| End region -> region, "End" | End region -> region, "End"
@ -166,7 +168,6 @@ let proj_token = function
| With region -> region, "With" | With region -> region, "With"
| C_None region -> region, "C_None" | C_None region -> region, "C_None"
| C_Some region -> region, "C_Some" | C_Some region -> region, "C_Some"
| Attr2 Region.{region; value} -> region, sprintf "Attr2 %s" value
| EOF region -> region, "EOF" | EOF region -> region, "EOF"
let to_lexeme = function let to_lexeme = function
@ -205,6 +206,7 @@ let to_lexeme = function
| Mutez i -> fst i.Region.value | Mutez i -> fst i.Region.value
| String s -> String.escaped s.Region.value | String s -> String.escaped s.Region.value
| Bytes b -> fst b.Region.value | Bytes b -> fst b.Region.value
| Attr a -> a.Region.value
| Begin _ -> "begin" | Begin _ -> "begin"
| Else _ -> "else" | Else _ -> "else"
@ -226,7 +228,7 @@ let to_lexeme = function
| C_None _ -> "None" | C_None _ -> "None"
| C_Some _ -> "Some" | C_Some _ -> "Some"
| Attr2 a -> a.Region.value
| EOF _ -> "" | EOF _ -> ""
let to_string token ?(offsets=true) mode = let to_string token ?(offsets=true) mode =
@ -469,11 +471,10 @@ let mk_constr lexeme region =
(* Attributes *) (* Attributes *)
let mk_attr _lexeme _region = let mk_attr header lexeme region =
Error Invalid_attribute if header = "[@" then
Error Invalid_attribute
let mk_attr2 lexeme region = else Ok (Attr Region.{value=lexeme; region})
Ok (Attr2 { value = lexeme; region })
(* Predicates *) (* Predicates *)

View File

@ -0,0 +1,5 @@
SHELL := dash
BFLAGS := -strict-sequence -w +A-48-4 -g
clean::
> rm -f Parser.msg Parser.msg.map Parser.msg.states Version.ml

View File

@ -46,7 +46,7 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 33 -> | 33 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 460 -> | 478 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 27 -> | 27 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
@ -68,9 +68,13 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 133 -> | 133 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 373 -> | 379 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 375 -> | 381 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 472 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 169 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 134 -> | 134 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
@ -80,7 +84,7 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 153 -> | 153 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 374 -> | 380 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 63 -> | 63 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
@ -144,137 +148,141 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 156 -> | 156 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 463 -> | 481 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 465 -> | 483 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 221 -> | 221 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 215 -> | 246 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 226 -> | 223 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 255 -> | 225 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 256 -> | 219 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 243 -> | 230 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 264 -> | 259 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 228 -> | 260 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 257 -> | 247 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 258 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 266 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 268 -> | 268 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 232 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 261 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 262 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 270 -> | 270 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 272 -> | 272 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 274 -> | 274 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 192 -> | 276 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 259 -> | 278 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 285 -> | 195 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 288 -> | 263 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 245 -> | 289 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 293 -> | 292 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 262 -> | 249 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 297 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 266 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 160 -> | 160 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 164 -> | 164 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 429 -> | 445 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 332 -> | 337 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 317 -> | 317 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 432 -> | 447 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 445 -> | 319 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 446 -> | 320 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 433 -> | 321 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 434 -> | 448 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 435 -> | 462 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 436 -> | 463 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 437 -> | 449 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 438 -> | 450 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 440 -> | 452 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 328 -> | 451 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 330 -> | 453 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 454 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 455 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 457 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 333 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 335 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 339 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 336 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 334 -> | 334 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<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 -> | 345 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 367 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 346 -> | 346 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 348 -> | 348 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 441 -> | 347 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 443 -> | 349 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 447 -> | 350 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 430 -> | 351 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 312 -> | 373 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 428 -> | 352 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 354 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 458 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 460 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 464 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 446 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 316 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 444 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 165 -> | 165 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
@ -282,65 +290,71 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 168 -> | 168 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 169 -> | 172 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 171 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 163 -> | 163 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 448 -> | 465 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 450 -> | 467 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 451 -> | 468 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 166 -> | 166 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 235 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 236 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 239 -> | 239 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 240 -> | 240 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 425 -> | 243 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 170 -> | 244 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 171 -> | 441 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 172 -> | 173 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 418 -> | 428 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 419 -> | 429 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 174 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 175 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 434 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 435 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 438 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 439 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 427 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 421 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 422 -> | 422 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 423 -> | 423 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 174 -> | 177 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 308 -> | 308 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 320 -> | 309 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 321 -> | 412 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 322 -> | 419 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 323 -> | 411 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 310 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 312 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 324 -> | 324 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
@ -350,67 +364,79 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 327 -> | 327 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 378 -> | 329 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 379 -> | 328 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 381 -> | 330 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 335 -> | 331 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 310 -> | 332 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 307 -> | 384 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 395 -> | 385 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 396 -> | 387 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 397 -> | 340 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 398 -> | 314 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 399 -> | 311 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 400 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 408 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 401 -> | 401 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 402 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 404 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 403 -> | 403 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 175 -> | 405 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 176 -> | 406 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 407 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 415 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 408 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 410 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 178 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 179 -> | 179 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 180 -> | 182 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 183 -> | 183 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 302 -> | 186 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 300 -> | 306 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 185 -> | 304 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 187 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 188 -> | 188 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 189 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 190 -> | 190 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 195 -> | 191 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 192 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 193 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 198 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 218 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 197 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 214 -> | 214 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 194 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 210 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| _ -> | _ ->
raise Not_found raise Not_found

View File

@ -12,7 +12,7 @@
%token <(string * Z.t) Region.reg> Mutez "<mutez>" %token <(string * Z.t) Region.reg> Mutez "<mutez>"
%token <string Region.reg> Ident "<ident>" %token <string Region.reg> Ident "<ident>"
%token <string Region.reg> Constr "<constr>" %token <string Region.reg> Constr "<constr>"
%token <string Region.reg> Attr2 "<attr>" %token <string Region.reg> Attr "<attr>"
(* Symbols *) (* Symbols *)

View File

@ -119,6 +119,7 @@ declaration:
type_decl: type_decl:
"type" type_name "=" type_expr { "type" type_name "=" type_expr {
Scoping.check_reserved_name $2;
let region = cover $1 (type_expr_to_region $4) in let region = cover $1 (type_expr_to_region $4) in
let value = { let value = {
kwd_type = $1; kwd_type = $1;
@ -128,23 +129,23 @@ type_decl:
in {region; value} } in {region; value} }
type_expr: type_expr:
cartesian | sum_type | record_type { $1 } fun_type | sum_type | record_type { $1 }
cartesian:
fun_type { $1 }
| fun_type "*" nsepseq(fun_type,"*") {
let value = Utils.nsepseq_cons $1 $2 $3 in
let region = nsepseq_to_region type_expr_to_region value
in TProd {region; value} }
fun_type: fun_type:
core_type { $1 } cartesian { $1 }
| core_type "->" fun_type { | cartesian "->" fun_type {
let start = type_expr_to_region $1 let start = type_expr_to_region $1
and stop = type_expr_to_region $3 in and stop = type_expr_to_region $3 in
let region = cover start stop in let region = cover start stop in
TFun {region; value=$1,$2,$3} } TFun {region; value=$1,$2,$3} }
cartesian:
core_type { $1 }
| core_type "*" nsepseq(core_type,"*") {
let value = Utils.nsepseq_cons $1 $2 $3 in
let region = nsepseq_to_region type_expr_to_region value
in TProd {region; value} }
core_type: core_type:
type_name { TVar $1 } type_name { TVar $1 }
| par(type_expr) { TPar $1 } | par(type_expr) { TPar $1 }
@ -175,6 +176,7 @@ type_tuple:
sum_type: sum_type:
ioption("|") nsepseq(variant,"|") { ioption("|") nsepseq(variant,"|") {
Scoping.check_variants (Utils.nsepseq_to_list $2);
let region = nsepseq_to_region (fun x -> x.region) $2 let region = nsepseq_to_region (fun x -> x.region) $2
in TSum {region; value=$2} } in TSum {region; value=$2} }
@ -188,6 +190,8 @@ variant:
record_type: record_type:
"{" sep_or_term_list(field_decl,";") "}" { "{" sep_or_term_list(field_decl,";") "}" {
let ne_elements, terminator = $2 in let ne_elements, terminator = $2 in
let () = Utils.nsepseq_to_list ne_elements
|> Scoping.check_fields in
let region = cover $1 $3 let region = cover $1 $3
and value = {compound = Braces ($1,$3); ne_elements; terminator} and value = {compound = Braces ($1,$3); ne_elements; terminator}
in TRecord {region; value} } in TRecord {region; value} }
@ -202,7 +206,7 @@ field_decl:
(* Top-level non-recursive definitions *) (* Top-level non-recursive definitions *)
let_declaration: let_declaration:
"let" let_binding seq(Attr2) { "let" let_binding seq(Attr) {
let kwd_let = $1 in let kwd_let = $1 in
let attributes = $3 in let attributes = $3 in
let binding = $2 in let binding = $2 in
@ -214,9 +218,11 @@ let_declaration:
let_binding: let_binding:
"<ident>" nseq(sub_irrefutable) type_annotation? "=" expr { "<ident>" nseq(sub_irrefutable) type_annotation? "=" expr {
let binders = Utils.nseq_cons (PVar $1) $2 in let binders = Utils.nseq_cons (PVar $1) $2 in
Utils.nseq_iter Scoping.check_pattern binders;
{binders; lhs_type=$3; eq=$4; let_rhs=$5} {binders; lhs_type=$3; eq=$4; let_rhs=$5}
} }
| irrefutable type_annotation? "=" expr { | irrefutable type_annotation? "=" expr {
Scoping.check_pattern $1;
{binders=$1,[]; lhs_type=$2; eq=$3; let_rhs=$4} } {binders=$1,[]; lhs_type=$2; eq=$3; let_rhs=$4} }
type_annotation: type_annotation:
@ -441,10 +447,12 @@ cases(right_expr):
in fst_case, ($2,snd_case)::others } in fst_case, ($2,snd_case)::others }
case_clause(right_expr): case_clause(right_expr):
pattern "->" right_expr { {pattern=$1; arrow=$2; rhs=$3} } pattern "->" right_expr {
Scoping.check_pattern $1;
{pattern=$1; arrow=$2; rhs=$3} }
let_expr(right_expr): let_expr(right_expr):
"let" let_binding seq(Attr2) "in" right_expr { "let" let_binding seq(Attr) "in" right_expr {
let kwd_let = $1 let kwd_let = $1
and binding = $2 and binding = $2
and attributes = $3 and attributes = $3
@ -626,9 +634,9 @@ update_record:
lbrace = $1; lbrace = $1;
record = $2; record = $2;
kwd_with = $3; kwd_with = $3;
updates = { value = {compound = Braces($1,$5); updates = {value = {compound = Braces($1,$5);
ne_elements; ne_elements;
terminator}; terminator};
region = cover $3 $5}; region = cover $3 $5};
rbrace = $5} rbrace = $5}
in {region; value} } in {region; value} }
@ -656,5 +664,5 @@ sequence:
in {region; value} } in {region; value} }
path : path :
"<ident>" {Name $1} "<ident>" { Name $1 }
| projection { Path $1} | projection { Path $1 }

View File

@ -131,7 +131,7 @@ let rec print_tokens state {decl;eof} =
and print_attributes state attributes = and print_attributes state attributes =
List.iter ( List.iter (
fun ({value = attribute; region}) -> fun ({value = attribute; region}) ->
let attribute_formatted = sprintf "[@%s]" attribute in let attribute_formatted = sprintf "[@@%s]" attribute in
print_token state region attribute_formatted print_token state region attribute_formatted
) attributes ) attributes
@ -610,31 +610,41 @@ let rec pp_ast state {decl; _} =
List.iteri (List.length decls |> apply) decls List.iteri (List.length decls |> apply) decls
and pp_declaration state = function and pp_declaration state = function
Let {value = (_, let_binding, _); region} -> Let {value = (_, let_binding, attr); region} ->
pp_loc_node state "Let" region; pp_loc_node state "Let" region;
pp_let_binding state let_binding pp_let_binding state let_binding attr;
| TypeDecl {value; region} -> | TypeDecl {value; region} ->
pp_loc_node state "TypeDecl" region; pp_loc_node state "TypeDecl" region;
pp_type_decl state value pp_type_decl state value
and pp_let_binding state node = and pp_let_binding state node attr =
let {binders; lhs_type; let_rhs; _} = node in let {binders; lhs_type; let_rhs; _} = node in
let fields = if lhs_type = None then 2 else 3 in let fields = if lhs_type = None then 2 else 3 in
let () = let fields = if attr = [] then fields else fields+1 in
let arity =
let state = state#pad fields 0 in let state = state#pad fields 0 in
pp_node state "<binders>"; pp_node state "<binders>";
pp_binders state binders in pp_binders state binders; 0 in
let () = let arity =
match lhs_type with match lhs_type with
None -> () None -> arity
| Some (_, type_expr) -> | Some (_, type_expr) ->
let state = state#pad fields 1 in let state = state#pad fields (arity+1) in
pp_node state "<lhs type>"; pp_node state "<lhs type>";
pp_type_expr (state#pad 1 0) type_expr in pp_type_expr (state#pad 1 0) type_expr;
let () = arity+1 in
let state = state#pad fields (fields - 1) in let arity =
let state = state#pad fields (arity+1) in
pp_node state "<rhs>"; pp_node state "<rhs>";
pp_expr (state#pad 1 0) let_rhs pp_expr (state#pad 1 0) let_rhs;
arity+1 in
let () =
if attr <> [] then
let state = state#pad fields (arity+1) in
pp_node state "<attributes>";
let length = List.length attr in
let apply len rank = pp_ident (state#pad len rank)
in List.iteri (apply length) attr
in () in ()
and pp_type_decl state decl = and pp_type_decl state decl =
@ -838,28 +848,39 @@ and pp_fun_expr state node =
in () in ()
and pp_let_in state node = and pp_let_in state node =
let {binding; body; _} = node in let {binding; body; attributes; _} = node in
let {binders; lhs_type; let_rhs; _} = binding in let {binders; lhs_type; let_rhs; _} = binding in
let fields = if lhs_type = None then 3 else 4 in let fields = if lhs_type = None then 3 else 4 in
let () = let fields = if attributes = [] then fields else fields+1 in
let arity =
let state = state#pad fields 0 in let state = state#pad fields 0 in
pp_node state "<binders>"; pp_node state "<binders>";
pp_binders state binders in pp_binders state binders; 0 in
let () = let arity =
match lhs_type with match lhs_type with
None -> () None -> arity
| Some (_, type_expr) -> | Some (_, type_expr) ->
let state = state#pad fields 1 in let state = state#pad fields (arity+1) in
pp_node state "<lhs type>"; pp_node state "<lhs type>";
pp_type_expr (state#pad 1 0) type_expr in pp_type_expr (state#pad 1 0) type_expr;
let () = arity+1 in
let state = state#pad fields (fields - 2) in let arity =
let state = state#pad fields (arity+1) in
pp_node state "<rhs>"; pp_node state "<rhs>";
pp_expr (state#pad 1 0) let_rhs in pp_expr (state#pad 1 0) let_rhs;
let () = arity+1 in
let state = state#pad fields (fields - 1) in let arity =
let state = state#pad fields (arity+1) in
pp_node state "<body>"; pp_node state "<body>";
pp_expr (state#pad 1 0) body pp_expr (state#pad 1 0) body;
arity+1 in
let () =
if attributes <> [] then
let state = state#pad fields (arity+1) in
pp_node state "<attributes>";
let length = List.length attributes in
let apply len rank = pp_ident (state#pad len rank)
in List.iteri (apply length) attributes
in () in ()
and pp_tuple_expr state {value; _} = and pp_tuple_expr state {value; _} =

View File

@ -25,6 +25,7 @@ val pattern_to_string :
val expr_to_string : val expr_to_string :
offsets:bool -> mode:[`Point|`Byte] -> AST.expr -> string offsets:bool -> mode:[`Point|`Byte] -> AST.expr -> string
(** {1 Pretty-printing of the AST} *) (** {1 Pretty-printing of AST nodes} *)
val pp_ast : state -> AST.t -> unit val pp_ast : state -> AST.t -> unit
val pp_expr : state -> AST.expr -> unit

View File

@ -6,22 +6,86 @@ module IO =
let options = EvalOpt.read "CameLIGO" ext let options = EvalOpt.read "CameLIGO" ext
end end
module ExtParser = module Parser =
struct struct
type ast = AST.t type ast = AST.t
type expr = AST.expr type expr = AST.expr
include Parser include Parser
end end
module ExtParserLog = module ParserLog =
struct struct
type ast = AST.t type ast = AST.t
type expr = AST.expr
include ParserLog include ParserLog
end end
module MyLexer = Lexer.Make (LexToken) module Lexer = Lexer.Make (LexToken)
module Unit = module Unit =
ParserUnit.Make (IO)(MyLexer)(AST)(ExtParser)(ParErr)(ExtParserLog) ParserUnit.Make (Lexer)(AST)(Parser)(ParErr)(ParserLog)(IO)
let () = Unit.run () (* Main *)
let issue_error point =
let error = Unit.format_error ~offsets:IO.options#offsets
IO.options#mode point
in Stdlib.Error error
let parse parser : ('a,string) Stdlib.result =
try parser () with
(* Scoping errors *)
| Scoping.Error (Scoping.Reserved_name name) ->
let token =
Lexer.Token.mk_ident name.Region.value name.Region.region in
(match token with
(* Cannot fail because [name] is a not a
reserved name for the lexer. *)
Stdlib.Error _ -> assert false
| Ok invalid ->
issue_error
("Reserved name.\nHint: Change the name.\n", None, invalid))
| Scoping.Error (Scoping.Duplicate_variant name) ->
let token =
Lexer.Token.mk_constr name.Region.value name.Region.region in
let point = "Duplicate constructor in this sum type declaration.\n\
Hint: Change the constructor.\n",
None, token
in issue_error point
| Scoping.Error (Scoping.Non_linear_pattern var) ->
let token =
Lexer.Token.mk_ident var.Region.value var.Region.region in
(match token with
(* Cannot fail because [var] is a not a
reserved name for the lexer. *)
Stdlib.Error _ -> assert false
| Ok invalid ->
let point = "Repeated variable in this pattern.\n\
Hint: Change the name.\n",
None, invalid
in issue_error point)
| Scoping.Error (Scoping.Duplicate_field name) ->
let token =
Lexer.Token.mk_ident name.Region.value name.Region.region in
(match token with
(* Cannot fail because [name] is a not a
reserved name for the lexer. *)
Stdlib.Error _ -> assert false
| Ok invalid ->
let point = "Duplicate field name in this record declaration.\n\
Hint: Change the name.\n",
None, invalid
in issue_error point)
let () =
if IO.options#expr
then match parse (fun () -> Unit.parse Unit.parse_expr) with
Stdlib.Ok _ -> ()
| Error msg -> Printf.eprintf "\027[31m%s\027[0m%!" msg
else match parse (fun () -> Unit.parse Unit.parse_contract) with
Stdlib.Ok _ -> ()
| Error msg -> Printf.eprintf "\027[31m%s\027[0m%!" msg

View File

@ -0,0 +1,132 @@
[@@@warning "-42"]
type t =
Reserved_name of AST.variable
| Duplicate_variant of AST.variable
| Non_linear_pattern of AST.variable
| Duplicate_field of AST.variable
type error = t
exception Error of t
open Region
(* Useful modules *)
module SSet = Utils.String.Set
module Ord =
struct
type t = AST.variable
let compare v1 v2 =
compare v1.value v2.value
end
module VarSet = Set.Make (Ord)
(* Checking the definition of reserved names (shadowing) *)
let reserved =
let open SSet in
empty
|> add "assert"
|> add "balance"
|> add "time"
|> add "amount"
|> add "gas"
|> add "sender"
|> add "source"
|> add "failwith"
|> add "continue"
|> add "stop"
|> add "int"
|> add "abs"
|> add "unit"
let check_reserved_names vars =
let is_reserved elt = SSet.mem elt.value reserved in
let inter = VarSet.filter is_reserved vars in
if not (VarSet.is_empty inter) then
let clash = VarSet.choose inter in
raise (Error (Reserved_name clash))
else vars
let check_reserved_name var =
if SSet.mem var.value reserved then
raise (Error (Reserved_name var))
(* Checking the linearity of patterns *)
open! AST
let rec vars_of_pattern env = function
PConstr p -> vars_of_pconstr env p
| PUnit _ | PFalse _ | PTrue _
| PInt _ | PNat _ | PBytes _
| PString _ | PWild _ -> env
| PVar var ->
if VarSet.mem var env then
raise (Error (Non_linear_pattern var))
else VarSet.add var env
| PList l -> vars_of_plist env l
| PTuple t -> Utils.nsepseq_foldl vars_of_pattern env t.value
| PPar p -> vars_of_pattern env p.value.inside
| PRecord p -> vars_of_fields env p.value.ne_elements
| PTyped p -> vars_of_pattern env p.value.pattern
and vars_of_fields env fields =
Utils.nsepseq_foldl vars_of_field_pattern env fields
and vars_of_field_pattern env field =
let var = field.value.field_name in
if VarSet.mem var env then
raise (Error (Non_linear_pattern var))
else
let p = field.value.pattern
in vars_of_pattern (VarSet.add var env) p
and vars_of_pconstr env = function
PNone _ -> env
| PSomeApp {value=_, pattern; _} ->
vars_of_pattern env pattern
| PConstrApp {value=_, Some pattern; _} ->
vars_of_pattern env pattern
| PConstrApp {value=_,None; _} -> env
and vars_of_plist env = function
PListComp {value; _} ->
Utils.sepseq_foldl vars_of_pattern env value.elements
| PCons {value; _} ->
let head, _, tail = value in
List.fold_left vars_of_pattern env [head; tail]
let check_linearity = vars_of_pattern VarSet.empty
(* Checking patterns *)
let check_pattern p =
check_linearity p |> check_reserved_names |> ignore
(* Checking variants for duplicates *)
let check_variants variants =
let add acc {value; _} =
if VarSet.mem value.constr acc then
raise (Error (Duplicate_variant value.constr))
else VarSet.add value.constr acc in
let variants =
List.fold_left add VarSet.empty variants
in ignore variants
(* Checking record fields *)
let check_fields fields =
let add acc {value; _} =
if VarSet.mem (value: field_decl).field_name acc then
raise (Error (Duplicate_field value.field_name))
else VarSet.add value.field_name acc in
let fields =
List.fold_left add VarSet.empty fields
in ignore fields

View File

@ -0,0 +1,16 @@
(* This module exports checks on scoping, called from the parser. *)
type t =
Reserved_name of AST.variable
| Duplicate_variant of AST.variable
| Non_linear_pattern of AST.variable
| Duplicate_field of AST.variable
type error = t
exception Error of t
val check_reserved_name : AST.variable -> unit
val check_pattern : AST.pattern -> unit
val check_variants : AST.variant Region.reg list -> unit
val check_fields : AST.field_decl Region.reg list -> unit

View File

@ -1,10 +0,0 @@
#!/bin/sh
set -e
if test -d ../../.git; then
echo true > dot_git_is_dir
else
echo false > dot_git_is_dir
cat .git >> dot_git_is_dir
fi

View File

@ -1,14 +1,21 @@
;; Build of the lexer
(ocamllex LexToken) (ocamllex LexToken)
;; Build of the parser
(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))
;; Build of the parser as a library
(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
Scoping AST cameligo Parser ParserLog LexToken)
(libraries (libraries
menhirLib menhirLib
parser_shared parser_shared
@ -20,6 +27,18 @@
(pps bisect_ppx --conditional)) (pps bisect_ppx --conditional))
(flags (:standard -open Simple_utils -open Parser_shared))) (flags (:standard -open Simple_utils -open Parser_shared)))
;; Build of the unlexer (for covering the
;; error states of the LR automaton)
(executable
(name Unlexer)
(libraries str)
(preprocess
(pps bisect_ppx --conditional))
(modules Unlexer))
;; Local build of a standalone lexer
(executable (executable
(name LexerMain) (name LexerMain)
(libraries parser_cameligo) (libraries parser_cameligo)
@ -28,6 +47,8 @@
(pps bisect_ppx --conditional)) (pps bisect_ppx --conditional))
(flags (:standard -open Parser_shared -open Parser_cameligo))) (flags (:standard -open Parser_shared -open Parser_cameligo)))
;; Local build of a standalone parser
(executable (executable
(name ParserMain) (name ParserMain)
(libraries parser_cameligo) (libraries parser_cameligo)
@ -37,19 +58,16 @@
(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 ;; Build of the covering of error states in the LR automaton
(name Unlexer)
(libraries str)
(preprocess
(pps bisect_ppx --conditional))
(modules Unlexer))
(rule (rule
(targets Parser.msg) (targets Parser.msg)
(deps (:script_messages ../../../../vendors/ligo-utils/simple-utils/messages.sh) Parser.mly LexToken.mli ParToken.mly) (deps (:script_messages ../../../../vendors/ligo-utils/simple-utils/messages.sh) Parser.mly LexToken.mli ParToken.mly)
(action (run %{script_messages} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly Parser.mly ))) (action (run %{script_messages} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly Parser.mly)))
;; Build of all the LIGO source file that cover all error states
(rule (rule
(targets all.ligo) (targets all.mligo)
(deps (:script_cover ../../../../vendors/ligo-utils/simple-utils/cover.sh) Parser.mly LexToken.mli ParToken.mly Parser.msg Unlexer.exe) (deps (:script_cover ../../../../vendors/ligo-utils/simple-utils/cover.sh) Parser.mly LexToken.mli ParToken.mly Parser.msg Unlexer.exe)
(action (run %{script_cover} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly --ext=ligo --unlexer=./Unlexer.exe --messages=Parser.msg --dir=. --concatenate Parser.mly ))) (action (run %{script_cover} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly --ext=mligo --unlexer=./Unlexer.exe --messages=Parser.msg --dir=. --concatenate Parser.mly )))

View File

@ -2,15 +2,12 @@
(name parser) (name parser)
(public_name ligo.parser) (public_name ligo.parser)
(libraries (libraries
simple-utils simple-utils
tezos-utils tezos-utils
parser_shared parser_shared
parser_pascaligo parser_pascaligo
parser_cameligo parser_cameligo
parser_reasonligo parser_reasonligo)
)
(preprocess (preprocess
(pps ppx_let bisect_ppx --conditional) (pps ppx_let bisect_ppx --conditional))
) (flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Parser_shared)))
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils -open Parser_shared))
)

View File

@ -1,129 +1,103 @@
open Trace open Trace
module Parser = Parser_pascaligo.Parser
module AST = Parser_pascaligo.AST module AST = Parser_pascaligo.AST
module ParserLog = Parser_pascaligo.ParserLog
module LexToken = Parser_pascaligo.LexToken module LexToken = Parser_pascaligo.LexToken
module Lexer = Lexer.Make(LexToken) module Lexer = Lexer.Make(LexToken)
module SyntaxError = Parser_pascaligo.SyntaxError module Scoping = Parser_pascaligo.Scoping
module Parser = Parser_pascaligo.Parser
module Errors = struct module Errors =
struct
let reserved_name Region.{value; region} =
let title () = Printf.sprintf "reserved name \"%s\"" value in
let message () = "" in
let data = [
("location",
fun () -> Format.asprintf "%a" Location.pp_lift @@ region)]
in error ~data title message
let lexer_error (e: Lexer.error AST.reg) = let non_linear_pattern Region.{value; region} =
let title () = "lexer error" in let title () =
let message () = Lexer.error_to_string e.value in Printf.sprintf "repeated variable \"%s\" in this pattern" value in
let data = [ let message () = "" in
("parser_loc", let data = [
fun () -> Format.asprintf "%a" Location.pp_lift @@ e.region ("location",
) fun () -> Format.asprintf "%a" Location.pp_lift @@ region)]
] in in error ~data title message
error ~data title message
let reserved_name Region.{value; region} = let duplicate_parameter Region.{value; region} =
let title () = Printf.sprintf "reserved name \"%s\"" value in let title () =
let message () = "" in Printf.sprintf "duplicate parameter \"%s\"" value in
let data = [ let message () = "" in
("location", let data = [
fun () -> Format.asprintf "%a" Location.pp_lift @@ region) ("location",
] in fun () -> Format.asprintf "%a" Location.pp_lift @@ region)]
error ~data title message in error ~data title message
let non_linear_pattern Region.{value; region} = let duplicate_variant Region.{value; region} =
let title () = Printf.sprintf "repeated variable \"%s\" in this pattern" value in let title () =
let message () = "" in Printf.sprintf "duplicate variant \"%s\" in this\
let data = [ type declaration" value in
("location", let message () = "" in
fun () -> Format.asprintf "%a" Location.pp_lift @@ region) let data = [
] in ("location",
error ~data title message fun () -> Format.asprintf "%a" Location.pp_lift @@ region)]
in error ~data title message
let duplicate_parameter Region.{value; region} = let unrecognized_error source (start: Lexing.position)
let title () = Printf.sprintf "duplicate parameter \"%s\"" value in (stop: Lexing.position) lexbuf =
let message () = "" in let title () = "unrecognized error" in
let data = [ let file =
("location", if source = "" then ""
fun () -> Format.asprintf "%a" Location.pp_lift @@ region) else
] in Format.sprintf "In file \"%s|%s\"" start.pos_fname source in
error ~data title message let message () =
Format.sprintf
"Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
(Lexing.lexeme lexbuf)
start.pos_lnum (start.pos_cnum - start.pos_bol)
stop.pos_lnum (stop.pos_cnum - stop.pos_bol)
file in
let loc = Region.make ~start:(Pos.from_byte start)
~stop:(Pos.from_byte stop) in
let data = [
("unrecognized_loc",
fun () -> Format.asprintf "%a" Location.pp_lift @@ loc)]
in error ~data title message
let duplicate_variant Region.{value; region} = let parser_error source (start: Lexing.position)
let title () = Printf.sprintf "duplicate variant \"%s\" in this\ (stop: Lexing.position) lexbuf =
type declaration" value in let title () = "parser error" in
let message () = "" in let file =
let data = [ if source = "" then ""
("location", else
fun () -> Format.asprintf "%a" Location.pp_lift @@ region) Format.sprintf "In file \"%s|%s\"" start.pos_fname source in
] in let message () =
error ~data title message Format.sprintf
"Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
let detached_attributes (attrs: AST.attributes) = (Lexing.lexeme lexbuf)
let title () = "detached attributes" in start.pos_lnum (start.pos_cnum - start.pos_bol)
let message () = "" in stop.pos_lnum (stop.pos_cnum - stop.pos_bol)
let data = [ file in
("location", let loc =
fun () -> Format.asprintf "%a" Location.pp_lift @@ attrs.region) if start.pos_cnum = -1 then
] in Region.make
error ~data title message ~start:(Pos.min ~file:source) ~stop:(Pos.from_byte stop)
else
let parser_error source (start: Lexing.position) (end_: Lexing.position) lexbuf = Region.make ~start:(Pos.from_byte start)
let title () = "parser error" in ~stop:(Pos.from_byte stop) in
let file = if source = "" then let data =
"" [("parser_loc",
else fun () -> Format.asprintf "%a" Location.pp_lift @@ loc)] in
Format.sprintf "In file \"%s|%s\"" start.pos_fname source error ~data title message
in
let str = Format.sprintf
"Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
(Lexing.lexeme lexbuf)
start.pos_lnum (start.pos_cnum - start.pos_bol)
end_.pos_lnum (end_.pos_cnum - end_.pos_bol)
file
in
let message () = str in
let loc = if start.pos_cnum = -1 then
Region.make
~start: Pos.min
~stop:(Pos.from_byte end_)
else
Region.make
~start:(Pos.from_byte start)
~stop:(Pos.from_byte end_)
in
let data =
[
("parser_loc",
fun () -> Format.asprintf "%a" Location.pp_lift @@ loc
)
]
in
error ~data title message
let unrecognized_error source (start: Lexing.position) (end_: Lexing.position) lexbuf =
let title () = "unrecognized error" in
let file = if source = "" then
""
else
Format.sprintf "In file \"%s|%s\"" start.pos_fname source
in
let str = Format.sprintf
"Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
(Lexing.lexeme lexbuf)
start.pos_lnum (start.pos_cnum - start.pos_bol)
end_.pos_lnum (end_.pos_cnum - end_.pos_bol)
file
in
let message () = str in
let loc = Region.make
~start:(Pos.from_byte start)
~stop:(Pos.from_byte end_)
in
let data = [
("unrecognized_loc",
fun () -> Format.asprintf "%a" Location.pp_lift @@ loc
)
] in
error ~data title message
let lexer_error (e: Lexer.error AST.reg) =
let title () = "lexer error" in
let message () = Lexer.error_to_string e.value in
let data = [
("parser_loc",
fun () -> Format.asprintf "%a" Location.pp_lift @@ e.region)]
in error ~data title message
end end
open Errors open Errors
@ -131,35 +105,29 @@ open Errors
type 'a parser = (Lexing.lexbuf -> LexToken.token) -> Lexing.lexbuf -> 'a type 'a parser = (Lexing.lexbuf -> LexToken.token) -> Lexing.lexbuf -> 'a
let parse (parser: 'a parser) source lexbuf = let parse (parser: 'a parser) source lexbuf =
let Lexer.{read ; close ; _} = Lexer.open_token_stream None in let Lexer.{read; close; _} = Lexer.open_token_stream None in
let result = let result =
try try ok (parser read lexbuf) with
ok (parser read lexbuf) Lexer.Error e ->
with fail @@ lexer_error e
SyntaxError.Error (Non_linear_pattern var) ->
fail @@ (non_linear_pattern var)
| SyntaxError.Error (Duplicate_parameter name) ->
fail @@ (duplicate_parameter name)
| SyntaxError.Error (Duplicate_variant name) ->
fail @@ (duplicate_variant name)
| SyntaxError.Error (Reserved_name name) ->
fail @@ (reserved_name name)
| SyntaxError.Error (Detached_attributes attrs) ->
fail @@ (detached_attributes attrs)
| Parser.Error -> | Parser.Error ->
let start = Lexing.lexeme_start_p lexbuf in let start = Lexing.lexeme_start_p lexbuf in
let end_ = Lexing.lexeme_end_p lexbuf in let stop = Lexing.lexeme_end_p lexbuf in
fail @@ (parser_error source start end_ lexbuf) fail @@ parser_error source start stop lexbuf
| Lexer.Error e -> | Scoping.Error (Scoping.Non_linear_pattern var) ->
fail @@ (lexer_error e) fail @@ non_linear_pattern var
| Scoping.Error (Duplicate_parameter name) ->
fail @@ duplicate_parameter name
| Scoping.Error (Duplicate_variant name) ->
fail @@ duplicate_variant name
| Scoping.Error (Reserved_name name) ->
fail @@ reserved_name name
| _ -> | _ ->
let _ = Printexc.print_backtrace Pervasives.stdout in let () = Printexc.print_backtrace Pervasives.stdout in
let start = Lexing.lexeme_start_p lexbuf in let start = Lexing.lexeme_start_p lexbuf in
let end_ = Lexing.lexeme_end_p lexbuf in let stop = Lexing.lexeme_end_p lexbuf in
fail @@ (unrecognized_error source start end_ lexbuf) fail @@ unrecognized_error source start stop lexbuf
in in close (); result
close ();
result
let parse_file (source: string) : AST.t result = let parse_file (source: string) : AST.t result =
let pp_input = let pp_input =

View File

@ -1,21 +1,18 @@
(* This file provides an interface to the PascaLIGO parser. *) (** This file provides an interface to the PascaLIGO parser. *)
open Trace
module Parser = Parser_pascaligo.Parser
module AST = Parser_pascaligo.AST module AST = Parser_pascaligo.AST
module ParserLog = Parser_pascaligo.ParserLog
module LexToken = Parser_pascaligo.LexToken
(** Open a PascaLIGO filename given by string and convert into an
(** Open a PascaLIGO filename given by string and convert into an abstract syntax tree. *) abstract syntax tree. *)
val parse_file : string -> (AST.t result) val parse_file : string -> AST.t Trace.result
(** Convert a given string into a PascaLIGO abstract syntax tree *) (** Convert a given string into a PascaLIGO abstract syntax tree *)
val parse_string : string -> AST.t result val parse_string : string -> AST.t Trace.result
(** Parse a given string as a PascaLIGO expression and return an expression AST. (** Parse a given string as a PascaLIGO expression and return an
expression AST.
This is intended to be used for interactive interpreters, or other scenarios This is intended to be used for interactive interpreters, or other
where you would want to parse a PascaLIGO expression outside of a contract. *) scenarios where you would want to parse a PascaLIGO expression
val parse_expression : string -> AST.expr result outside of a contract. *)
val parse_expression : string -> AST.expr Trace.result

View File

@ -1,5 +1,4 @@
$HOME/git/OCaml-build/Makefile $HOME/git/OCaml-build/Makefile
$HOME/git/OCaml-build/Makefile.cfg
$HOME/git/ligo/vendors/ligo-utils/simple-utils/pos.mli $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/pos.ml
$HOME/git/ligo/vendors/ligo-utils/simple-utils/region.mli $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.mli
@ -19,5 +18,8 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml
../shared/ParserAPI.mli ../shared/ParserAPI.mli
../shared/ParserAPI.ml ../shared/ParserAPI.ml
../shared/LexerUnit.ml ../shared/LexerUnit.ml
../shared/ParserUnit.mli
../shared/ParserUnit.ml ../shared/ParserUnit.ml
../shared/Memo.mli
../shared/Memo.ml
Stubs/Simple_utils.ml Stubs/Simple_utils.ml

View File

@ -25,6 +25,7 @@ type 'a reg = 'a Region.reg
type keyword = Region.t type keyword = Region.t
type kwd_and = Region.t type kwd_and = Region.t
type kwd_attributes = Region.t
type kwd_begin = Region.t type kwd_begin = Region.t
type kwd_block = Region.t type kwd_block = Region.t
type kwd_case = Region.t type kwd_case = Region.t
@ -109,7 +110,7 @@ type field_name = string reg
type map_name = string reg type map_name = string reg
type set_name = string reg type set_name = string reg
type constr = string reg type constr = string reg
type attribute = string reg type attribute = string reg
(* Parentheses *) (* Parentheses *)
@ -144,12 +145,13 @@ type t = {
and ast = t and ast = t
and attributes = attribute list reg
and declaration = and declaration =
TypeDecl of type_decl reg TypeDecl of type_decl reg
| ConstDecl of const_decl reg | ConstDecl of const_decl reg
| FunDecl of fun_decl reg | FunDecl of fun_decl reg
| AttrDecl of attr_decl
and attr_decl = string reg ne_injection reg
and const_decl = { and const_decl = {
kwd_const : kwd_const; kwd_const : kwd_const;
@ -159,7 +161,7 @@ and const_decl = {
equal : equal; equal : equal;
init : expr; init : expr;
terminator : semi option; terminator : semi option;
attributes : attributes; attributes : attr_decl option
} }
(* Type declarations *) (* Type declarations *)
@ -217,7 +219,7 @@ and fun_decl = {
block_with : (block reg * kwd_with) option; block_with : (block reg * kwd_with) option;
return : expr; return : expr;
terminator : semi option; terminator : semi option;
attributes : attributes; attributes : attr_decl option
} }
and parameters = (param_decl, semi) nsepseq par reg and parameters = (param_decl, semi) nsepseq par reg
@ -260,11 +262,12 @@ and statements = (statement, semi) nsepseq
and statement = and statement =
Instr of instruction Instr of instruction
| Data of data_decl | Data of data_decl
| Attr of attr_decl
and data_decl = and data_decl =
LocalConst of const_decl reg LocalConst of const_decl reg
| LocalVar of var_decl reg | LocalVar of var_decl reg
| LocalFun of fun_decl reg | LocalFun of fun_decl reg
and var_decl = { and var_decl = {
kwd_var : kwd_var; kwd_var : kwd_var;
@ -562,6 +565,7 @@ and field_assign = {
equal : equal; equal : equal;
field_expr : expr field_expr : expr
} }
and record = field_assign reg ne_injection and record = field_assign reg ne_injection
and projection = { and projection = {

View File

@ -28,6 +28,11 @@ type lexeme = string
(* TOKENS *) (* TOKENS *)
type attribute = {
header : string;
string : lexeme Region.reg
}
type t = type t =
(* Literals *) (* Literals *)
@ -151,8 +156,7 @@ val mk_kwd : lexeme -> Region.t -> (token, kwd_err) result
val mk_string : lexeme -> Region.t -> token val mk_string : lexeme -> Region.t -> token
val mk_bytes : lexeme -> Region.t -> token val mk_bytes : lexeme -> Region.t -> token
val mk_constr : lexeme -> Region.t -> token val mk_constr : lexeme -> Region.t -> token
val mk_attr : lexeme -> Region.t -> (token, attr_err) result val mk_attr : string -> lexeme -> Region.t -> (token, attr_err) result
val mk_attr2 : lexeme -> Region.t -> (token, attr_err) result
val eof : Region.t -> token val eof : Region.t -> token
(* Predicates *) (* Predicates *)

View File

@ -26,6 +26,11 @@ let rollback buffer =
(* TOKENS *) (* TOKENS *)
type attribute = {
header : string;
string : lexeme Region.reg
}
type t = type t =
(* Literals *) (* Literals *)
@ -33,7 +38,7 @@ type t =
| Bytes of (lexeme * Hex.t) Region.reg | Bytes of (lexeme * Hex.t) Region.reg
| Int of (lexeme * Z.t) Region.reg | Int of (lexeme * Z.t) Region.reg
| Nat of (lexeme * Z.t) Region.reg | Nat of (lexeme * Z.t) Region.reg
| Mutez of (lexeme * Z.t) Region.reg | Mutez of (lexeme * Z.t) Region.reg
| Ident of lexeme Region.reg | Ident of lexeme Region.reg
| Constr of lexeme Region.reg | Constr of lexeme Region.reg
@ -144,6 +149,11 @@ let proj_token = function
| Constr Region.{region; value} -> | Constr Region.{region; value} ->
region, sprintf "Constr \"%s\"" value region, sprintf "Constr \"%s\"" value
(*
| Attr {header; string={region; value}} ->
region, sprintf "Attr (\"%s\",\"%s\")" header value
*)
(* Symbols *) (* Symbols *)
| SEMI region -> region, "SEMI" | SEMI region -> region, "SEMI"
@ -312,6 +322,7 @@ let to_lexeme = function
| EOF _ -> "" | EOF _ -> ""
(* CONVERSIONS *)
let to_string token ?(offsets=true) mode = let to_string token ?(offsets=true) mode =
let region, val_str = proj_token token in let region, val_str = proj_token token in
@ -365,7 +376,7 @@ let keywords = [
let reserved = let reserved =
let open SSet in let open SSet in
empty |> add "args" empty |> add "arguments"
let constructors = [ let constructors = [
(fun reg -> False reg); (fun reg -> False reg);
@ -489,8 +500,6 @@ let eof region = EOF region
type sym_err = Invalid_symbol type sym_err = Invalid_symbol
type attr_err = Invalid_attribute
let mk_sym lexeme region = let mk_sym lexeme region =
match lexeme with match lexeme with
(* Lexemes in common with all concrete syntaxes *) (* Lexemes in common with all concrete syntaxes *)
@ -539,10 +548,9 @@ let mk_constr lexeme region =
(* Attributes *) (* Attributes *)
let mk_attr _lexeme _region = type attr_err = Invalid_attribute
Error Invalid_attribute
let mk_attr2 _lexeme _region = let mk_attr _header _string _region =
Error Invalid_attribute Error Invalid_attribute
(* Predicates *) (* Predicates *)

View File

@ -7,3 +7,8 @@ module IO =
end end
module M = LexerUnit.Make (IO) (Lexer.Make (LexToken)) module M = LexerUnit.Make (IO) (Lexer.Make (LexToken))
let () =
match M.trace () with
Stdlib.Ok _ -> ()
| Error msg -> Printf.eprintf "\027[31m%s\027[0m%!" msg

View File

@ -0,0 +1,5 @@
SHELL := dash
BFLAGS := -strict-sequence -w +A-48-4 -g
clean::
> rm -f Parser.msg Parser.msg.map Parser.msg.states Version.ml

View File

@ -0,0 +1,39 @@
module ParserLog = Parser_pascaligo.ParserLog
module ParErr = Parser_pascaligo.ParErr
module SSet = Utils.String.Set
(* Mock options. TODO: Plug in cmdliner. *)
let pre_options =
EvalOpt.make
~libs:[]
~verbose:SSet.empty
~offsets:true
~mode:`Point
~cmd:EvalOpt.Quiet
~mono:true (* Monolithic API of Menhir for now *)
(* ~input:None *)
(* ~expr:true *)
module Parser =
struct
type ast = AST.t
type expr = AST.expr
include Parser_pascaligo.Parser
end
module ParserLog =
struct
type ast = AST.t
type expr = AST.expr
include Parser_pascaligo.ParserLog
end
module PreUnit = ParserUnit.Make (Lexer)(AST)(Parser)(ParErr)(ParserLog)
module Front = ParserAPI.Make (Lexer)(Parser)(ParErr)
let issue_error point =
let error = Front.format_error ~offsets:true (* TODO: CLI *)
`Point (* TODO: CLI *) point
in Stdlib.Error error

View File

@ -58,13 +58,13 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 64 -> | 64 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 517 -> | 543 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 29 -> | 29 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 32 -> | 32 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 515 -> | 541 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 35 -> | 35 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
@ -78,23 +78,9 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 67 -> | 67 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 70 -> | 68 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 71 -> | 84 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 85 -> | 85 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
@ -102,241 +88,225 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 87 -> | 87 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 88 -> | 514 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 373 -> | 373 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 374 -> | 374 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 507 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 377 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 375 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 376 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 378 -> | 378 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 379 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 380 -> | 380 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 381 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 382 -> | 382 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 383 -> | 484 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 485 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 486 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 487 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 504 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 511 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 510 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 386 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 387 -> | 387 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 384 -> | 388 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 385 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 389 -> | 389 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 390 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 391 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 393 -> | 393 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 395 -> | 395 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 399 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 396 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 397 -> | 397 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 375 -> | 398 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 381 -> | 402 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 399 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 400 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 404 -> | 404 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 408 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 405 -> | 405 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 406 -> | 406 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 492 -> | 390 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 493 -> | 396 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 413 -> | 413 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 414 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 415 -> | 415 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 435 -> | 500 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 436 -> | 501 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 437 -> | 502 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 440 -> | 416 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 441 -> | 496 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 469 -> | 417 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 470 -> | 461 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 473 -> | 456 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 472 -> | 462 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 438 -> | 418 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 467 -> | 419 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 439 -> | 425 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 69 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 428 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 429 -> | 429 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 430 -> | 430 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 431 -> | 420 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 432 -> | 433 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 508 -> | 434 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 521 -> | 435 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 159 -> | 422 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 523 -> | 424 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 137 -> | 444 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 150 -> | 445 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 166 -> | 446 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 167 -> | 449 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 158 -> | 450 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 173 -> | 478 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 152 -> | 479 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 168 -> | 482 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 169 -> | 481 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 175 -> | 447 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 177 -> | 476 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 179 -> | 448 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 437 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 438 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 439 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 440 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 441 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 536 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 515 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 516 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 517 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 518 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 519 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 520 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 529 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 532 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 524 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 525 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 547 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 181 -> | 181 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 183 -> | 549 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 160 -> | 159 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 170 -> | 172 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 157 -> | 188 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 163 -> | 189 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 187 -> | 180 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 92 -> | 195 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 318 -> | 174 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 319 -> | 190 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 322 -> | 191 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 323 -> | 197 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 356 -> | 199 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 351 -> | 201 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 353 -> | 203 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 93 -> | 205 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 94 -> | 182 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 338 -> | 192 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 95 -> | 179 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 96 -> | 185 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 209 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 91 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 342 -> | 342 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
@ -346,169 +316,231 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 347 -> | 347 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 349 -> | 371 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 97 -> | 366 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 136 -> | 368 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 92 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 93 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 362 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 94 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 95 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 144 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 145 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 148 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 149 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 364 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 96 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 158 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 100 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 217 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 218 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 220 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 221 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 224 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 225 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 358 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 353 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 355 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 101 -> | 101 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<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 -> | 102 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 350 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 336 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 338 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 103 -> | 103 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 326 -> | 332 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 312 -> | 330 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 314 -> | 333 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 104 -> | 334 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 308 -> | 328 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 306 -> | 156 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 105 ->
"<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"
| 137 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 138 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 139 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 140 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 151 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 106 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 107 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 309 -> | 309 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 310 -> | 310 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 304 -> | 154 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 134 -> | 177 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 106 -> | 312 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 296 -> | 315 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 297 -> | 316 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 298 -> | 133 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 108 -> | 108 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 285 -> | 69 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 286 -> | 70 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 132 -> | 71 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 155 -> | 72 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 79 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 80 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 75 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 76 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 77 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 109 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 110 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 111 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 112 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 114 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 117 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 230 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 231 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 269 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 293 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 270 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 272 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 273 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 294 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 300 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 299 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 303 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 302 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 240 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 283 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 284 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 287 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 288 -> | 288 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 291 -> | 291 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<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 -> | 277 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 281 -> | 279 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 241 -> | 241 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 210 -> | 266 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 267 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 275 -> | 275 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 211 -> | 263 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 223 -> | 232 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 224 -> | 297 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 240 -> | 233 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 225 -> | 245 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 226 -> | 246 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 234 -> | 262 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 114 -> | 247 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 248 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 256 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 118 -> | 118 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 206 -> | 122 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 119 -> | 228 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 125 -> | 123 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 130 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| _ -> | _ ->
raise Not_found raise Not_found

View File

@ -6,39 +6,6 @@
open Region open Region
open AST open AST
type statement_attributes_mixed =
PInstr of instruction
| PData of data_decl
| PAttributes of attributes
let attributes_to_statement (statement, statements) =
if (List.length statements = 0) then
match statement with
| PInstr i -> Instr i, []
| PData d -> Data d, []
| PAttributes a ->
let open! SyntaxError in
raise (Error (Detached_attributes a))
else (
let statements = (Region.ghost, statement) :: statements in
let rec inner result = function
| (t, PData (LocalConst const)) :: (_, PAttributes a) :: rest ->
inner (result @ [(t, Data (LocalConst {const with value = {const.value with attributes = a}}))]) rest
| (t, PData (LocalFun func)) :: (_, PAttributes a) :: rest ->
inner (result @ [(t, Data (LocalFun {func with value = {func.value with attributes = a}}))]) rest
| (t, PData d) :: rest ->
inner (result @ [(t, Data d)]) rest
| (t, PInstr i) :: rest ->
inner (result @ [(t, Instr i)]) rest
| (_, PAttributes _) :: rest ->
inner result rest
| [] ->
result
in
let result = inner [] statements in
(snd (List.hd result), List.tl result)
)
(* END HEADER *) (* END HEADER *)
%} %}
@ -143,15 +110,24 @@ contract:
nseq(declaration) EOF { {decl=$1; eof=$2} } nseq(declaration) EOF { {decl=$1; eof=$2} }
declaration: declaration:
type_decl { TypeDecl $1 } type_decl { TypeDecl $1 }
| const_decl { ConstDecl $1 } | const_decl { ConstDecl $1 }
| fun_decl { FunDecl $1 } | fun_decl { FunDecl $1 }
| attr_decl { AttrDecl $1 }
(* Attribute declarations *)
attr_decl:
open_attr_decl ";"? { $1 }
open_attr_decl:
ne_injection("attributes","<string>") { $1 }
(* Type declarations *) (* Type declarations *)
type_decl: type_decl:
"type" type_name "is" type_expr ";"? { "type" type_name "is" type_expr ";"? {
ignore (SyntaxError.check_reserved_name $2); Scoping.check_reserved_name $2;
let stop = let stop =
match $5 with match $5 with
Some region -> region Some region -> region
@ -219,7 +195,7 @@ type_tuple:
sum_type: sum_type:
"|"? nsepseq(variant,"|") { "|"? nsepseq(variant,"|") {
SyntaxError.check_variants (Utils.nsepseq_to_list $2); Scoping.check_variants (Utils.nsepseq_to_list $2);
let region = nsepseq_to_region (fun x -> x.region) $2 let region = nsepseq_to_region (fun x -> x.region) $2
in TSum {region; value=$2} } in TSum {region; value=$2} }
@ -234,7 +210,7 @@ record_type:
"record" sep_or_term_list(field_decl,";") "end" { "record" sep_or_term_list(field_decl,";") "end" {
let ne_elements, terminator = $2 in let ne_elements, terminator = $2 in
let () = Utils.nsepseq_to_list ne_elements let () = Utils.nsepseq_to_list ne_elements
|> SyntaxError.check_fields in |> Scoping.check_fields in
let region = cover $1 $3 let region = cover $1 $3
and value = {opening = Kwd $1; and value = {opening = Kwd $1;
ne_elements; ne_elements;
@ -268,76 +244,72 @@ fun_expr:
colon = $3; colon = $3;
ret_type = $4; ret_type = $4;
kwd_is = $5; kwd_is = $5;
return = $6 return = $6}
}
in {region; value} } in {region; value} }
(* Function declarations *) (* Function declarations *)
open_fun_decl: open_fun_decl:
"function" fun_name parameters ":" type_expr "is" "function" fun_name parameters ":" type_expr "is"
block block "with" expr {
"with" expr { Scoping.check_reserved_name $2;
let fun_name = SyntaxError.check_reserved_name $2 in let stop = expr_to_region $9 in
let stop = expr_to_region $9 in let region = cover $1 stop
let region = cover $1 stop and value = {kwd_function = $1;
and value = {kwd_function = $1; fun_name = $2;
fun_name; param = $3;
param = $3; colon = $4;
colon = $4; ret_type = $5;
ret_type = $5; kwd_is = $6;
kwd_is = $6; block_with = Some ($7, $8);
block_with = Some ($7, $8); return = $9;
return = $9; terminator = None;
terminator = None; attributes = None}
attributes = {value = []; region = Region.ghost}} in {region; value}
in {region; value} } }
| "function" fun_name parameters ":" type_expr "is" expr { | "function" fun_name parameters ":" type_expr "is" expr {
let fun_name = SyntaxError.check_reserved_name $2 in Scoping.check_reserved_name $2;
let stop = expr_to_region $7 in let stop = expr_to_region $7 in
let region = cover $1 stop let region = cover $1 stop
and value = {kwd_function = $1; and value = {kwd_function = $1;
fun_name; fun_name = $2;
param = $3; param = $3;
colon = $4; colon = $4;
ret_type = $5; ret_type = $5;
kwd_is = $6; kwd_is = $6;
block_with = None; block_with = None;
return = $7; return = $7;
terminator = None; terminator = None;
attributes = {value = []; region = Region.ghost}} attributes = None}
in {region; value} } in {region; value} }
fun_decl: fun_decl:
open_fun_decl semi_attributes { open_fun_decl ";"? {
let attributes, terminator = $2 in {$1 with value = {$1.value with terminator=$2}} }
{$1 with value = {$1.value with terminator = terminator; attributes = attributes}}
}
parameters: parameters:
par(nsepseq(param_decl,";")) { par(nsepseq(param_decl,";")) {
let params = let params =
Utils.nsepseq_to_list ($1.value: _ par).inside Utils.nsepseq_to_list ($1.value: _ par).inside
in SyntaxError.check_parameters params; in Scoping.check_parameters params; $1 }
$1 }
param_decl: param_decl:
"var" var ":" param_type { "var" var ":" param_type {
let var = SyntaxError.check_reserved_name $2 in Scoping.check_reserved_name $2;
let stop = type_expr_to_region $4 in let stop = type_expr_to_region $4 in
let region = cover $1 stop let region = cover $1 stop
and value = {kwd_var = $1; and value = {kwd_var = $1;
var; var = $2;
colon = $3; colon = $3;
param_type = $4} param_type = $4}
in ParamVar {region; value} in ParamVar {region; value}
} }
| "const" var ":" param_type { | "const" var ":" param_type {
let var = SyntaxError.check_reserved_name $2 in Scoping.check_reserved_name $2;
let stop = type_expr_to_region $4 in let stop = type_expr_to_region $4 in
let region = cover $1 stop let region = cover $1 stop
and value = {kwd_const = $1; and value = {kwd_const = $1;
var; var = $2;
colon = $3; colon = $3;
param_type = $4} param_type = $4}
in ParamConst {region; value} } in ParamConst {region; value} }
@ -349,25 +321,25 @@ block:
"begin" sep_or_term_list(statement,";") "end" { "begin" sep_or_term_list(statement,";") "end" {
let statements, terminator = $2 in let statements, terminator = $2 in
let region = cover $1 $3 let region = cover $1 $3
and value = {opening = Begin $1; and value = {opening = Begin $1;
statements = attributes_to_statement statements; statements;
terminator; terminator;
closing = End $3} closing = End $3}
in {region; value} in {region; value}
} }
| "block" "{" sep_or_term_list(statement,";") "}" { | "block" "{" sep_or_term_list(statement,";") "}" {
let statements, terminator = $3 in let statements, terminator = $3 in
let region = cover $1 $4 let region = cover $1 $4
and value = {opening = Block ($1,$2); and value = {opening = Block ($1,$2);
statements = attributes_to_statement statements; statements;
terminator; terminator;
closing = Block $4} closing = Block $4}
in {region; value} } in {region; value} }
statement: statement:
instruction { PInstr $1 } instruction { Instr $1 }
| open_data_decl { PData $1 } | open_data_decl { Data $1 }
| attributes { PAttributes $1 } | open_attr_decl { Attr $1 }
open_data_decl: open_data_decl:
open_const_decl { LocalConst $1 } open_const_decl { LocalConst $1 }
@ -385,10 +357,9 @@ open_const_decl:
equal; equal;
init; init;
terminator = None; terminator = None;
attributes = {value = []; region = Region.ghost}} attributes = None}
in {region; value} } in {region; value} }
open_var_decl: open_var_decl:
"var" unqualified_decl(":=") { "var" unqualified_decl(":=") {
let name, colon, var_type, assign, init, stop = $2 in let name, colon, var_type, assign, init, stop = $2 in
@ -399,33 +370,18 @@ open_var_decl:
var_type; var_type;
assign; assign;
init; init;
terminator = None; terminator=None}
}
in {region; value} } in {region; value} }
unqualified_decl(OP): unqualified_decl(OP):
var ":" type_expr OP expr { var ":" type_expr OP expr {
let var = SyntaxError.check_reserved_name $1 in Scoping.check_reserved_name $1;
let region = expr_to_region $5 let region = expr_to_region $5
in var, $2, $3, $4, $5, region } in $1, $2, $3, $4, $5, region }
attributes:
"attributes" "[" nsepseq(String,";") "]" {
let region = cover $1 $4 in
let value = (Utils.nsepseq_to_list $3) in
{region; value}
}
semi_attributes:
/* empty */ { {value = []; region = Region.ghost}, None }
| ";" { {value = []; region = Region.ghost}, Some $1 }
| ";" attributes ";" { $2, Some $1 }
const_decl: const_decl:
open_const_decl semi_attributes { open_const_decl ";"? {
let attributes, terminator = $2 in {$1 with value = {$1.value with terminator=$2}} }
{$1 with value = {$1.value with terminator = terminator; attributes = attributes }}
}
instruction: instruction:
conditional { Cond $1 } conditional { Cond $1 }
@ -589,7 +545,7 @@ clause_block:
let statements, terminator = $2 in let statements, terminator = $2 in
let region = cover $1 $3 in let region = cover $1 $3 in
let value = {lbrace = $1; let value = {lbrace = $1;
inside = attributes_to_statement statements, terminator; inside = statements, terminator;
rbrace = $3} in rbrace = $3} in
ShortBlock {value; region} } ShortBlock {value; region} }
@ -629,7 +585,7 @@ cases(rhs):
case_clause(rhs): case_clause(rhs):
pattern "->" rhs { pattern "->" rhs {
SyntaxError.check_pattern $1; Scoping.check_pattern $1;
fun rhs_to_region -> fun rhs_to_region ->
let start = pattern_to_region $1 in let start = pattern_to_region $1 in
let region = cover start (rhs_to_region $3) let region = cover start (rhs_to_region $3)
@ -671,10 +627,10 @@ for_loop:
in For (ForInt {region; value}) in For (ForInt {region; value})
} }
| "for" var arrow_clause? "in" collection expr block { | "for" var arrow_clause? "in" collection expr block {
let var = SyntaxError.check_reserved_name $2 in Scoping.check_reserved_name $2;
let region = cover $1 $7.region in let region = cover $1 $7.region in
let value = {kwd_for = $1; let value = {kwd_for = $1;
var; var = $2;
bind_to = $3; bind_to = $3;
kwd_in = $4; kwd_in = $4;
collection = $5; collection = $5;
@ -689,13 +645,13 @@ collection:
var_assign: var_assign:
var ":=" expr { var ":=" expr {
let name = SyntaxError.check_reserved_name $1 in Scoping.check_reserved_name $1;
let region = cover name.region (expr_to_region $3) let region = cover $1.region (expr_to_region $3)
and value = {name; assign=$2; expr=$3} and value = {name=$1; assign=$2; expr=$3}
in {region; value} } in {region; value} }
arrow_clause: arrow_clause:
"->" var { $1, SyntaxError.check_reserved_name $2 } "->" var { Scoping.check_reserved_name $2; ($1,$2) }
(* Expressions *) (* Expressions *)

View File

@ -114,29 +114,25 @@ let rec print_tokens state ast =
Utils.nseq_iter (print_decl state) decl; Utils.nseq_iter (print_decl state) decl;
print_token state eof "EOF" print_token state eof "EOF"
and print_attributes state attributes = and print_attr_decl state =
let attributes = List.fold_left (fun all a -> all ^ a.value ^ ";") "" attributes.value in print_ne_injection state "attributes" print_string
let line =
sprintf "attributes[%s]"
attributes
in Buffer.add_string state#buffer line
and print_decl state = function and print_decl state = function
TypeDecl decl -> print_type_decl state decl TypeDecl decl -> print_type_decl state decl
| ConstDecl decl -> print_const_decl state decl | ConstDecl decl -> print_const_decl state decl
| FunDecl decl -> print_fun_decl state decl | FunDecl decl -> print_fun_decl state decl
| AttrDecl decl -> print_attr_decl state decl
and print_const_decl state {value; _} = and print_const_decl state {value; _} =
let {kwd_const; name; colon; const_type; let {kwd_const; name; colon; const_type;
equal; init; terminator; attributes} = value in equal; init; terminator; _} = value in
print_token state kwd_const "const"; print_token state kwd_const "const";
print_var state name; print_var state name;
print_token state colon ":"; print_token state colon ":";
print_type_expr state const_type; print_type_expr state const_type;
print_token state equal "="; print_token state equal "=";
print_expr state init; print_expr state init;
print_terminator state terminator; print_terminator state terminator
print_attributes state attributes
and print_type_decl state {value; _} = and print_type_decl state {value; _} =
let {kwd_type; name; kwd_is; let {kwd_type; name; kwd_is;
@ -206,7 +202,7 @@ and print_type_tuple state {value; _} =
and print_fun_decl state {value; _} = and print_fun_decl state {value; _} =
let {kwd_function; fun_name; param; colon; let {kwd_function; fun_name; param; colon;
ret_type; kwd_is; block_with; ret_type; kwd_is; block_with;
return; terminator; attributes } = value in return; terminator; _} = value in
print_token state kwd_function "function"; print_token state kwd_function "function";
print_var state fun_name; print_var state fun_name;
print_parameters state param; print_parameters state param;
@ -220,7 +216,6 @@ and print_fun_decl state {value; _} =
print_token state kwd_with "with"); print_token state kwd_with "with");
print_expr state return; print_expr state return;
print_terminator state terminator; print_terminator state terminator;
print_attributes state attributes
and print_fun_expr state {value; _} = and print_fun_expr state {value; _} =
let {kwd_function; param; colon; let {kwd_function; param; colon;
@ -296,6 +291,7 @@ and print_statements state sequence =
and print_statement state = function and print_statement state = function
Instr instr -> print_instruction state instr Instr instr -> print_instruction state instr
| Data data -> print_data_decl state data | Data data -> print_data_decl state data
| Attr attr -> print_attr_decl state attr
and print_instruction state = function and print_instruction state = function
Cond {value; _} -> print_conditional state value Cond {value; _} -> print_conditional state value
@ -688,10 +684,10 @@ and print_opening state lexeme = function
print_token state kwd lexeme print_token state kwd lexeme
| KwdBracket (kwd, lbracket) -> | KwdBracket (kwd, lbracket) ->
print_token state kwd lexeme; print_token state kwd lexeme;
print_token state lbracket "{" print_token state lbracket "["
and print_closing state = function and print_closing state = function
RBracket rbracket -> print_token state rbracket "}" RBracket rbracket -> print_token state rbracket "]"
| End kwd_end -> print_token state kwd_end "end" | End kwd_end -> print_token state kwd_end "end"
and print_binding state {value; _} = and print_binding state {value; _} =
@ -848,21 +844,27 @@ and pp_declaration state = function
| FunDecl {value; region} -> | FunDecl {value; region} ->
pp_loc_node state "FunDecl" region; pp_loc_node state "FunDecl" region;
pp_fun_decl state value pp_fun_decl state value
| AttrDecl {value; region} ->
pp_loc_node state "AttrDecl" region;
pp_attr_decl state value
and pp_attr_decl state = pp_ne_injection pp_string state
and pp_fun_decl state decl = and pp_fun_decl state decl =
let arity = 5 in
let () = let () =
let state = state#pad 5 0 in let state = state#pad arity 0 in
pp_ident state decl.fun_name in pp_ident state decl.fun_name in
let () = let () =
let state = state#pad 5 1 in let state = state#pad arity 1 in
pp_node state "<parameters>"; pp_node state "<parameters>";
pp_parameters state decl.param in pp_parameters state decl.param in
let () = let () =
let state = state#pad 5 2 in let state = state#pad arity 2 in
pp_node state "<return type>"; pp_node state "<return type>";
pp_type_expr (state#pad 1 0) decl.ret_type in pp_type_expr (state#pad 1 0) decl.ret_type in
let () = let () =
let state = state#pad 5 3 in let state = state#pad arity 3 in
pp_node state "<body>"; pp_node state "<body>";
let statements = let statements =
match decl.block_with with match decl.block_with with
@ -870,15 +872,16 @@ and pp_fun_decl state decl =
| None -> Instr (Skip Region.ghost), [] in | None -> Instr (Skip Region.ghost), [] in
pp_statements state statements in pp_statements state statements in
let () = let () =
let state = state#pad 5 4 in let state = state#pad arity 4 in
pp_node state "<return>"; pp_node state "<return>";
pp_expr (state#pad 1 0) decl.return pp_expr (state#pad 1 0) decl.return
in () in ()
and pp_const_decl state decl = and pp_const_decl state decl =
pp_ident (state#pad 3 0) decl.name; let arity = 3 in
pp_type_expr (state#pad 3 1) decl.const_type; pp_ident (state#pad arity 0) decl.name;
pp_expr (state#pad 3 2) decl.init pp_type_expr (state#pad arity 1) decl.const_type;
pp_expr (state#pad arity 2) decl.init
and pp_type_expr state = function and pp_type_expr state = function
TProd cartesian -> TProd cartesian ->
@ -979,6 +982,9 @@ and pp_statement state = function
| Data data_decl -> | Data data_decl ->
pp_node state "Data"; pp_node state "Data";
pp_data_decl (state#pad 1 0) data_decl pp_data_decl (state#pad 1 0) data_decl
| Attr attr_decl ->
pp_node state "Attr";
pp_attr_decl state attr_decl.value
and pp_instruction state = function and pp_instruction state = function
Cond {value; region} -> Cond {value; region} ->
@ -1161,18 +1167,18 @@ and pp_bin_cons state (head, _, tail) =
and pp_injection : and pp_injection :
'a.(state -> 'a -> unit) -> state -> 'a injection -> unit = 'a.(state -> 'a -> unit) -> state -> 'a injection -> unit =
fun printer state inj -> fun printer state inj ->
let elements = Utils.sepseq_to_list inj.elements in let elements = Utils.sepseq_to_list inj.elements in
let length = List.length elements in let length = List.length elements in
let apply len rank = printer (state#pad len rank) let apply len rank = printer (state#pad len rank)
in List.iteri (apply length) elements in List.iteri (apply length) elements
and pp_ne_injection : and pp_ne_injection :
'a.(state -> 'a -> unit) -> state -> 'a ne_injection -> unit = 'a.(state -> 'a -> unit) -> state -> 'a ne_injection -> unit =
fun printer state inj -> fun printer state inj ->
let ne_elements = Utils.nsepseq_to_list inj.ne_elements in let ne_elements = Utils.nsepseq_to_list inj.ne_elements in
let length = List.length ne_elements in let length = List.length ne_elements in
let apply len rank = printer (state#pad len rank) let apply len rank = printer (state#pad len rank)
in List.iteri (apply length) ne_elements in List.iteri (apply length) ne_elements
and pp_tuple_pattern state tuple = and pp_tuple_pattern state tuple =
let patterns = Utils.nsepseq_to_list tuple.inside in let patterns = Utils.nsepseq_to_list tuple.inside in

View File

@ -18,6 +18,7 @@ val print_tokens : state -> AST.t -> unit
val print_path : state -> AST.path -> unit val print_path : state -> AST.path -> unit
val print_pattern : state -> AST.pattern -> unit val print_pattern : state -> AST.pattern -> unit
val print_instruction : state -> AST.instruction -> unit val print_instruction : state -> AST.instruction -> unit
val print_expr : state -> AST.expr -> unit
(** {1 Printing tokens from the AST in a string} *) (** {1 Printing tokens from the AST in a string} *)
@ -30,6 +31,7 @@ val pattern_to_string :
val instruction_to_string : val instruction_to_string :
offsets:bool -> mode:[`Point|`Byte] -> AST.instruction -> string offsets:bool -> mode:[`Point|`Byte] -> AST.instruction -> string
(** {1 Pretty-printing of the AST} *) (** {1 Pretty-printing of AST nodes} *)
val pp_ast : state -> AST.t -> unit val pp_ast : state -> AST.t -> unit
val pp_expr : state -> AST.expr -> unit

View File

@ -6,100 +6,97 @@ module IO =
let options = EvalOpt.read "PascaLIGO" ext let options = EvalOpt.read "PascaLIGO" ext
end end
module ExtParser = module Parser =
struct struct
type ast = AST.t type ast = AST.t
type expr = AST.expr type expr = AST.expr
include Parser include Parser
end end
module ExtParserLog = module ParserLog =
struct struct
type ast = AST.t type ast = AST.t
type expr = AST.expr
include ParserLog include ParserLog
end end
module MyLexer = Lexer.Make (LexToken) module Lexer = Lexer.Make (LexToken)
module Unit = module Unit =
ParserUnit.Make (IO)(MyLexer)(AST)(ExtParser)(ParErr)(ExtParserLog) ParserUnit.Make (Lexer)(AST)(Parser)(ParErr)(ParserLog)(IO)
open! SyntaxError (* Main *)
let () = let issue_error point =
try Unit.run () with let error = Unit.format_error ~offsets:IO.options#offsets
(* Ad hoc errors from the parser *) IO.options#mode point
in Stdlib.Error error
Error (Reserved_name name) -> let parse parser : ('a,string) Stdlib.result =
let () = Unit.close_all () in try parser () with
(* Scoping errors *)
| Scoping.Error (Scoping.Duplicate_parameter name) ->
let token = let token =
MyLexer.Token.mk_ident name.Region.value name.Region.region in Lexer.Token.mk_ident name.Region.value name.Region.region in
(match token with (match token with
Stdlib.Error _ -> (* Cannot fail because [name] is a not a
assert false (* Should not fail if [name] is valid. *) reserved name for the lexer. *)
Stdlib.Error _ -> assert false
| Ok invalid -> | Ok invalid ->
let point = "Reserved name.\nHint: Change the name.\n", issue_error ("Duplicate parameter.\nHint: Change the name.\n",
None, invalid in None, invalid))
let error =
Unit.format_error ~offsets:IO.options#offsets
IO.options#mode point
in Printf.eprintf "\027[31m%s\027[0m%!" error)
| Error (Duplicate_parameter name) -> | Scoping.Error (Scoping.Reserved_name name) ->
let () = Unit.close_all () in
let token = let token =
MyLexer.Token.mk_ident name.Region.value name.Region.region in Lexer.Token.mk_ident name.Region.value name.Region.region in
(match token with (match token with
Stdlib.Error _ -> (* Cannot fail because [name] is a not a
assert false (* Should not fail if [name] is valid. *) reserved name for the lexer. *)
Stdlib.Error _ -> assert false
| Ok invalid -> | Ok invalid ->
let point = "Duplicate parameter.\nHint: Change the name.\n", issue_error
None, invalid in ("Reserved name.\nHint: Change the name.\n", None, invalid))
let error =
Unit.format_error ~offsets:IO.options#offsets
IO.options#mode point
in Printf.eprintf "\027[31m%s\027[0m%!" error)
| Error (Duplicate_variant name) -> | Scoping.Error (Scoping.Duplicate_variant name) ->
let () = Unit.close_all () in
let token = let token =
MyLexer.Token.mk_constr name.Region.value name.Region.region in Lexer.Token.mk_constr name.Region.value name.Region.region in
let point = "Duplicate variant in this sum type declaration.\n\ let point = "Duplicate constructor in this sum type declaration.\n\
Hint: Change the name.\n", Hint: Change the constructor.\n",
None, token in None, token
let error = in issue_error point
Unit.format_error ~offsets:IO.options#offsets
IO.options#mode point
in Printf.eprintf "\027[31m%s\027[0m%!" error
| Error (Non_linear_pattern var) -> | Scoping.Error (Scoping.Non_linear_pattern var) ->
let () = Unit.close_all () in
let token = let token =
MyLexer.Token.mk_ident var.Region.value var.Region.region in Lexer.Token.mk_ident var.Region.value var.Region.region in
(match token with (match token with
Stdlib.Error _ -> (* Cannot fail because [var] is a not a
assert false (* Should not fail if [name] is valid. *) reserved name for the lexer. *)
Stdlib.Error _ -> assert false
| Ok invalid -> | Ok invalid ->
let point = "Repeated variable in this pattern.\n\ let point = "Repeated variable in this pattern.\n\
Hint: Change the name.\n", Hint: Change the name.\n",
None, invalid in None, invalid
let error = in issue_error point)
Unit.format_error ~offsets:IO.options#offsets
IO.options#mode point
in Printf.eprintf "\027[31m%s\027[0m%!" error)
| Error (Duplicate_field name) -> | Scoping.Error (Scoping.Duplicate_field name) ->
let () = Unit.close_all () in
let token = let token =
MyLexer.Token.mk_ident name.Region.value name.Region.region in Lexer.Token.mk_ident name.Region.value name.Region.region in
(match token with (match token with
Stdlib.Error _ -> (* Cannot fail because [name] is a not a
assert false (* Should not fail if [name] is valid. *) reserved name for the lexer. *)
Stdlib.Error _ -> assert false
| Ok invalid -> | Ok invalid ->
let point = "Duplicate field name in this record declaration.\n\ let point = "Duplicate field name in this record declaration.\n\
Hint: Change the name.\n", Hint: Change the name.\n",
None, invalid in None, invalid
let error = in issue_error point)
Unit.format_error ~offsets:IO.options#offsets
IO.options#mode point let () =
in Printf.eprintf "\027[31m%s\027[0m%!" error) if IO.options#expr
then match parse (fun () -> Unit.parse Unit.parse_expr) with
Stdlib.Ok _ -> ()
| Error msg -> Printf.eprintf "\027[31m%s\027[0m%!" msg
else match parse (fun () -> Unit.parse Unit.parse_contract) with
Stdlib.Ok _ -> ()
| Error msg -> Printf.eprintf "\027[31m%s\027[0m%!" msg

View File

@ -1,12 +1,12 @@
[@@@warning "-42"] [@@@warning "-42"]
type t = type t =
Reserved_name of AST.variable Reserved_name of AST.variable
| Duplicate_parameter of AST.variable | Duplicate_parameter of AST.variable
| Duplicate_variant of AST.variable | Duplicate_variant of AST.variable
| Non_linear_pattern of AST.variable | Non_linear_pattern of AST.variable
| Duplicate_field of AST.variable | Duplicate_field of AST.variable
| Detached_attributes of AST.attributes
type error = t type error = t
@ -95,11 +95,6 @@ let check_reserved_names vars =
let check_reserved_name var = let check_reserved_name var =
if SSet.mem var.value reserved then if SSet.mem var.value reserved then
raise (Error (Reserved_name var)) raise (Error (Reserved_name var))
else var
let check_reserved_name_opt = function
Some var -> ignore (check_reserved_name var)
| None -> ()
(* Checking the linearity of patterns *) (* Checking the linearity of patterns *)

View File

@ -0,0 +1,18 @@
(* This module exports checks on scoping, called from the parser. *)
type t =
Reserved_name of AST.variable
| Duplicate_parameter of AST.variable
| Duplicate_variant of AST.variable
| Non_linear_pattern of AST.variable
| Duplicate_field of AST.variable
type error = t
exception Error of t
val check_reserved_name : AST.variable -> unit
val check_pattern : AST.pattern -> unit
val check_variants : AST.variant Region.reg list -> unit
val check_parameters : AST.param_decl list -> unit
val check_fields : AST.field_decl Region.reg list -> unit

View File

@ -1,27 +0,0 @@
type t =
Reserved_name of AST.variable
| Duplicate_parameter of AST.variable
| Duplicate_variant of AST.variable
| Non_linear_pattern of AST.variable
| Duplicate_field of AST.variable
| Detached_attributes of AST.attributes
type error = t
exception Error of t
module Ord :
sig
type t = AST.variable
val compare : t -> t -> int
end
module VarSet : Set.S with type elt = Ord.t
val check_reserved_name : AST.variable -> AST.variable
val check_reserved_name_opt : AST.variable option -> unit
val check_reserved_names : VarSet.t -> VarSet.t
val check_pattern : AST.pattern -> unit
val check_variants : AST.variant Region.reg list -> unit
val check_parameters : AST.param_decl list -> unit
val check_fields : AST.field_decl Region.reg list -> unit

View File

@ -63,12 +63,12 @@ function claim (var store : store) : list (operation) * store is
case store.backers[sender] of case store.backers[sender] of
None -> None ->
failwith ("Not a backer.") failwith ("Not a backer.")
| Some (amount) -> | Some (quantity) ->
if balance >= store.goal or store.funded then if balance >= store.goal or store.funded then
failwith ("Goal reached: no refund.") failwith ("Goal reached: no refund.")
else else
begin begin
operations.0.foo := list [transaction (unit, sender, amount)]; operations.0.foo := list [transaction (unit, sender, quantity)];
remove sender from map store.backers remove sender from map store.backers
end end
end end

View File

@ -1,10 +0,0 @@
#!/bin/sh
set -e
if test -d ../../.git; then
echo true > dot_git_is_dir
else
echo false > dot_git_is_dir
cat .git >> dot_git_is_dir
fi

View File

@ -15,7 +15,7 @@
(name parser_pascaligo) (name parser_pascaligo)
(public_name ligo.parser.pascaligo) (public_name ligo.parser.pascaligo)
(modules (modules
SyntaxError AST pascaligo Parser ParserLog LexToken) Scoping AST pascaligo Parser ParserLog LexToken ParErr)
(libraries (libraries
menhirLib menhirLib
parser_shared parser_shared
@ -53,32 +53,21 @@
(name ParserMain) (name ParserMain)
(libraries parser_pascaligo) (libraries parser_pascaligo)
(modules (modules
ParErr ParserMain) 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)))
;; Les deux directives (rule) qui suivent sont pour le dev local. ;; Build of the covering of error states in the LR automaton
;; Il suffit de faire "dune build Parser.exe" pour avoir un Parser.exe dans le dossier.
;; Pour le purger, il faut faire "dune clean".
;(rule
; (targets Parser.exe)
; (deps ParserMain.exe)
; (action (copy ParserMain.exe Parser.exe))
; (mode promote-until-clean))
;(rule
; (targets Lexer.exe)
; (deps LexerMain.exe)
; (action (copy LexerMain.exe Lexer.exe))
; (mode promote-until-clean))
(rule (rule
(targets Parser.msg) (targets Parser.msg)
(deps (:script_messages ../../../../vendors/ligo-utils/simple-utils/messages.sh) Parser.mly LexToken.mli ParToken.mly) (deps (:script_messages ../../../../vendors/ligo-utils/simple-utils/messages.sh) Parser.mly LexToken.mli ParToken.mly)
(action (run %{script_messages} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly Parser.mly ))) (action (run %{script_messages} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly Parser.mly)))
;; Build of all the LIGO source file that cover all error states
(rule (rule
(targets all.ligo) (targets all.ligo)
(deps (:script_cover ../../../../vendors/ligo-utils/simple-utils/cover.sh) Parser.mly LexToken.mli ParToken.mly Parser.msg Unlexer.exe) (deps (:script_cover ../../../../vendors/ligo-utils/simple-utils/cover.sh) Parser.mly LexToken.mli ParToken.mly Parser.msg Unlexer.exe)
(action (run %{script_cover} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly --ext=ligo --unlexer=./Unlexer.exe --messages=Parser.msg --dir=. --concatenate Parser.mly ))) (action (run %{script_cover} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly --ext=ligo --unlexer=./Unlexer.exe --messages=Parser.msg --dir=. --concatenate Parser.mly)))

View File

@ -1,5 +1,5 @@
module Parser = Parser module Lexer = Lexer
module AST = AST module LexToken = LexToken
module Lexer = Lexer module AST = AST
module LexToken = LexToken module Parser = Parser
module ParserLog = ParserLog module ParserLog = ParserLog

View File

@ -6,87 +6,76 @@ module ParserLog = Parser_cameligo.ParserLog
module LexToken = Parser_reasonligo.LexToken module LexToken = Parser_reasonligo.LexToken
module Lexer = Lexer.Make(LexToken) module Lexer = Lexer.Make(LexToken)
module SyntaxError = Parser_reasonligo.SyntaxError module SyntaxError = Parser_reasonligo.SyntaxError
module Scoping = Parser_cameligo.Scoping
module Errors = struct module Errors =
struct
let lexer_error (e: Lexer.error AST.reg) =
let title () = "lexer error" in
let message () = Lexer.error_to_string e.value in
let data = [
("parser_loc",
fun () -> Format.asprintf "%a" Location.pp_lift @@ e.region)]
in error ~data title message
let lexer_error (e: Lexer.error AST.reg) = let wrong_function_arguments expr =
let title () = "lexer error" in let title () = "wrong function arguments" in
let message () = Lexer.error_to_string e.value in let message () = "" in
let data = [ let expression_loc = AST.expr_to_region expr in
("parser_loc", let data = [
fun () -> Format.asprintf "%a" Location.pp_lift @@ e.region ("location",
) fun () -> Format.asprintf "%a" Location.pp_lift @@ expression_loc)]
] in in error ~data title message
error ~data title message
let wrong_function_arguments expr = let parser_error source (start: Lexing.position)
let title () = "wrong function arguments" in (end_: Lexing.position) lexbuf =
let message () = "" in let title () = "parser error" in
let expression_loc = AST.expr_to_region expr in let file =
let data = [ if source = "" then ""
("location", else
fun () -> Format.asprintf "%a" Location.pp_lift @@ expression_loc) Format.sprintf "In file \"%s|%s\"" start.pos_fname source in
] in let str =
error ~data title message Format.sprintf
"Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
(Lexing.lexeme lexbuf)
start.pos_lnum (start.pos_cnum - start.pos_bol)
end_.pos_lnum (end_.pos_cnum - end_.pos_bol)
file in
let message () = str in
let loc =
if start.pos_cnum = -1
then Region.make
~start:(Pos.min ~file:source)
~stop:(Pos.from_byte end_)
else Region.make
~start:(Pos.from_byte start)
~stop:(Pos.from_byte end_) in
let data =
[("parser_loc",
fun () -> Format.asprintf "%a" Location.pp_lift @@ loc)]
in error ~data title message
let parser_error source (start: Lexing.position) (end_: Lexing.position) lexbuf = let unrecognized_error source (start: Lexing.position) (end_: Lexing.position) lexbuf =
let title () = "parser error" in let title () = "unrecognized error" in
let file = if source = "" then let file =
"" if source = "" then ""
else else
Format.sprintf "In file \"%s|%s\"" start.pos_fname source Format.sprintf "In file \"%s|%s\"" start.pos_fname source in
in let str =
let str = Format.sprintf Format.sprintf
"Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n" "Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
(Lexing.lexeme lexbuf) (Lexing.lexeme lexbuf)
start.pos_lnum (start.pos_cnum - start.pos_bol) start.pos_lnum (start.pos_cnum - start.pos_bol)
end_.pos_lnum (end_.pos_cnum - end_.pos_bol) end_.pos_lnum (end_.pos_cnum - end_.pos_bol)
file file in
in let message () = str in
let message () = str in let loc = Region.make
let loc = if start.pos_cnum = -1 then ~start:(Pos.from_byte start)
Region.make ~stop:(Pos.from_byte end_) in
~start: Pos.min let data = [
~stop:(Pos.from_byte end_) ("location",
else fun () -> Format.asprintf "%a" Location.pp_lift @@ loc)]
Region.make in error ~data title message
~start:(Pos.from_byte start)
~stop:(Pos.from_byte end_)
in
let data =
[
("parser_loc",
fun () -> Format.asprintf "%a" Location.pp_lift @@ loc
)
]
in
error ~data title message
let unrecognized_error source (start: Lexing.position) (end_: Lexing.position) lexbuf =
let title () = "unrecognized error" in
let file = if source = "" then
""
else
Format.sprintf "In file \"%s|%s\"" start.pos_fname source
in
let str = Format.sprintf
"Parse error at \"%s\" from (%d, %d) to (%d, %d). %s\n"
(Lexing.lexeme lexbuf)
start.pos_lnum (start.pos_cnum - start.pos_bol)
end_.pos_lnum (end_.pos_cnum - end_.pos_bol)
file
in
let message () = str in
let loc = Region.make
~start:(Pos.from_byte start)
~stop:(Pos.from_byte end_)
in
let data = [
("location",
fun () -> Format.asprintf "%a" Location.pp_lift @@ loc
)
] in
error ~data title message
end end

View File

@ -1,5 +1,4 @@
$HOME/git/OCaml-build/Makefile $HOME/git/OCaml-build/Makefile
$HOME/git/OCaml-build/Makefile.cfg
$HOME/git/ligo/vendors/ligo-utils/simple-utils/pos.mli $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/pos.ml
$HOME/git/ligo/vendors/ligo-utils/simple-utils/region.mli $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.mli
@ -22,7 +21,8 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml
../shared/ParserUnit.ml ../shared/ParserUnit.ml
Stubs/Simple_utils.ml Stubs/Simple_utils.ml
Stubs/Parser_cameligo.ml Stubs/Parser_cameligo.ml
../cameligo/AST.mli
../cameligo/AST.ml ../cameligo/AST.ml
../cameligo/ParserLog.mli ../cameligo/ParserLog.mli
../cameligo/ParserLog.ml ../cameligo/ParserLog.ml
../cameligo/Scoping.mli
../cameligo/Scoping.ml

View File

@ -143,8 +143,7 @@ val mk_int : lexeme -> Region.t -> (token, int_err) result
val mk_nat : lexeme -> Region.t -> (token, nat_err) result val mk_nat : lexeme -> Region.t -> (token, nat_err) result
val mk_mutez : lexeme -> Region.t -> (token, int_err) result val mk_mutez : lexeme -> Region.t -> (token, int_err) result
val mk_ident : lexeme -> Region.t -> (token, ident_err) result val mk_ident : lexeme -> Region.t -> (token, ident_err) result
val mk_attr : lexeme -> Region.t -> (token, attr_err) result val mk_attr : string -> lexeme -> Region.t -> (token, attr_err) result
val mk_attr2 : lexeme -> Region.t -> (token, attr_err) result
val mk_sym : lexeme -> Region.t -> (token, sym_err) result val mk_sym : lexeme -> Region.t -> (token, sym_err) result
val mk_kwd : lexeme -> Region.t -> (token, kwd_err) result val mk_kwd : lexeme -> Region.t -> (token, kwd_err) result
val mk_string : lexeme -> Region.t -> token val mk_string : lexeme -> Region.t -> token

View File

@ -453,11 +453,10 @@ let mk_constr lexeme region = mk_constr' lexeme region lexicon
(* Attributes *) (* Attributes *)
let mk_attr lexeme region = let mk_attr header lexeme region =
Ok (Attr { value = lexeme; region }) if header = "[@" then
Ok (Attr Region.{value=lexeme; region})
let mk_attr2 _lexeme _region = else Error Invalid_attribute
Error Invalid_attribute
(* Predicates *) (* Predicates *)

View File

@ -0,0 +1,5 @@
SHELL := dash
BFLAGS := -strict-sequence -w +A-48-4 -g
clean::
> rm -f Parser.msg Parser.msg.map Parser.msg.states Version.ml

View File

@ -0,0 +1,65 @@
type error =
IntErr of LexToken.int_err
| IdentErr of LexToken.ident_err
| NatErr of LexToken.nat_err
| SymErr of LexToken.sym_err
| KwdErr of LexToken.kwd_err
let rec first_of_expr = function
ECase {value; _} ->
(match LexToken.mk_kwd "switch" value.kwd_match with
Error e -> Error (KwdErr e)
| Ok token -> Ok token)
| ECond {value; _} ->
(match LexToken.mk_kwd "if" value.kwd_if with
Error e -> Error (KwdErr e)
| Ok token -> Ok token)
| EPar {value; _} ->
(match LexToken.mk_sym "(" value.lpar with
Error e -> Error (SymErr e)
| Ok token -> Ok token)
| EAnnot {value; _} ->
(match LexToken.mk_sym "(" value.lpar with
Error e -> Error (SymErr e)
| Ok token -> Ok token)
| EUnit {value=opening, _; _} ->
(match LexToken.mk_sym "(" opening with
Error e -> Error (SymErr e)
| Ok token -> Ok token)
| EBytes b ->
Ok (LexToken.mk_bytes (fst b.value) b.region)
| EVar v ->
(match LexToken.mk_ident v.value v.region with
Error e -> Error (IdentErr e)
| Ok token -> Ok token)
| ESeq {value; _} ->
let opening =
match value.compound with
BeginEnd (opening, _)
| Braces (opening, _)
| Brackets (opening, _) -> opening
in (match LexToken.mk_sym "{" opening with
Error e -> Error (SymErr e)
| Ok token -> Ok token)
| EProj {value; _} ->
let structure = value.struct_name in
(match LexToken.mk_ident structure.value structure.region with
Error e -> Error (IdentErr e)
| Ok token -> Ok token)
| EFun {value; _} ->
(match LexToken.mk_kwd "fun" value.kwd_fun with
Error e -> Error (KwdErr e)
| Ok token -> Ok token)
| _ -> failwith "TODO"
(*
| ELogic expr -> first_of_logic_expr expr
| EArith expr -> first_of_arith_expr expr
| EString expr -> first_of_string_expr expr
| EList expr -> first_of_list_expr expr
| EConstr expr -> first_of_constr_expr expr
| ECall {value=expr,_; _} -> first_of_expr expr
| ERecord {value; _} -> (*field_assign reg ne_injection *)
| ETuple {value; _} -> (* (expr, comma) nsepseq *)
| ELetIn {value; _} -> first_of_let_in value
*)

View File

@ -46,9 +46,9 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 11 -> | 11 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 509 -> | 528 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 503 -> | 61 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 48 -> | 48 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
@ -68,335 +68,387 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 14 -> | 14 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 60 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 65 -> | 65 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 505 -> | 70 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 145 -> | 524 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 146 -> | 185 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 144 -> | 186 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 329 -> | 184 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 331 -> | 302 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 330 -> | 304 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 61 -> | 303 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 66 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 69 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 64 -> | 64 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 59 -> | 183 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 143 -> | 311 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 338 -> | 313 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 340 -> | 312 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 339 -> | 191 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 151 -> | 192 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 118 -> | 118 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 125 -> | 298 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 87 -> | 300 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 105 -> | 299 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 132 -> | 132 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 334 -> | 195 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 158 -> | 158 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 512 -> | 165 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 218 -> | 127 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 514 -> | 145 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 216 -> | 147 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 250 -> | 148 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 248 -> | 146 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 249 -> | 128 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 230 -> | 133 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 235 -> | 120 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 121 -> | 121 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 122 -> | 122 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 120 -> | 172 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 466 -> | 307 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 467 -> | 309 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 308 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 173 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 176 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 177 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 197 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 199 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 198 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 59 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 531 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 225 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 533 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 223 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 257 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 255 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 256 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 237 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 242 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 259 ->
"<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"
| 226 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 233 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 234 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 267 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 269 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 271 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 273 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 201 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 202 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 213 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 222 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 206 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 214 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 215 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 203 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 204 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 205 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 263 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 284 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 240 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 286 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 72 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 483 -> | 483 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 492 -> | 484 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 469 -> | 423 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 470 -> | 161 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 468 -> | 162 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 471 -> | 160 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 472 -> | 486 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 487 -> | 487 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 488 -> | 504 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 474 -> | 513 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 498 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 499 -> | 499 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 497 -> | 497 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 465 -> | 488 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 321 -> | 489 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 490 ->
"<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"
| 495 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 509 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 510 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 491 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 520 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 518 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 485 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 372 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 366 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 367 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 369 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 368 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 365 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 76 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 446 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 326 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 332 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 333 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 336 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 337 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 328 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 339 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 100 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 78 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 80 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 315 -> | 315 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 316 -> | 316 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 318 -> | 117 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 317 -> | 82 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 448 -> | 448 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 456 -> | 449 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 457 -> | 451 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 459 -> | 452 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 200 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 236 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 79 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 467 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 468 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 476 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 477 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 479 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 480 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 469 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 470 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 81 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 460 -> | 460 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 449 -> | 461 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 450 -> | 455 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 76 -> | 454 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 458 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 348 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 356 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 360 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 359 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 355 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 349 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 457 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 340 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 341 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 346 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 347 ->
"<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"
| 84 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 85 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 318 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 323 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 324 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 389 ->
"<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"
| 439 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 440 -> | 440 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 441 -> | 441 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 425 -> | 435 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 422 -> | 325 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 428 -> | 362 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 429 -> | 363 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 434 -> | 373 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 438 -> | 374 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 437 -> | 413 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 433 -> | 420 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 423 -> | 408 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 427 -> | 409 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 162 -> | 407 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 163 -> | 375 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 290 -> | 376 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 295 -> | 377 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 402 -> | 402 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
@ -406,105 +458,69 @@ let message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 405 -> | 405 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 399 -> | 417 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 297 -> | 418 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 311 -> | 401 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 312 -> | 429 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 322 -> | 427 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 323 -> | 364 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 377 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 384 -> | 384 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 342 -> | 385 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 343 -> | 383 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 324 -> | 378 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 379 -> | 379 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 380 -> | 380 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 369 -> | 394 ->
"<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"
| 399 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 398 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 393 -> | 393 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 391 -> | 320 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 313 -> | 321 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 348 -> | 86 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 349 -> | 87 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 347 -> | 88 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 350 -> | 89 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 351 -> | 90 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 352 -> | 91 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 359 -> | 96 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 360 -> | 97 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 361 -> | 98 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 362 -> | 111 ->
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| 364 -> | 244 ->
"<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" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
| _ -> | _ ->
raise Not_found raise Not_found

View File

@ -148,6 +148,7 @@ declaration:
type_decl: type_decl:
"type" type_name "=" type_expr { "type" type_name "=" type_expr {
Scoping.check_reserved_name $2;
let region = cover $1 (type_expr_to_region $4) let region = cover $1 (type_expr_to_region $4)
and value = {kwd_type = $1; and value = {kwd_type = $1;
name = $2; name = $2;
@ -192,6 +193,7 @@ core_type:
sum_type: sum_type:
"|" nsepseq(variant,"|") { "|" nsepseq(variant,"|") {
Scoping.check_variants (Utils.nsepseq_to_list $2);
let region = nsepseq_to_region (fun x -> x.region) $2 let region = nsepseq_to_region (fun x -> x.region) $2
in TSum {region; value=$2} } in TSum {region; value=$2} }
@ -205,6 +207,8 @@ variant:
record_type: record_type:
"{" sep_or_term_list(field_decl,",") "}" { "{" sep_or_term_list(field_decl,",") "}" {
let ne_elements, terminator = $2 in let ne_elements, terminator = $2 in
let () = Utils.nsepseq_to_list ne_elements
|> Scoping.check_fields in
let region = cover $1 $3 let region = cover $1 $3
and value = {compound = Braces ($1,$3); ne_elements; terminator} and value = {compound = Braces ($1,$3); ne_elements; terminator}
in TRecord {region; value} } in TRecord {region; value} }
@ -240,21 +244,25 @@ es6_func:
let_binding: let_binding:
"<ident>" type_annotation? "=" expr { "<ident>" type_annotation? "=" expr {
{binders = PVar $1,[]; lhs_type=$2; eq=$3; let_rhs=$4} Scoping.check_reserved_name $1;
{binders = PVar $1, []; lhs_type=$2; eq=$3; let_rhs=$4}
} }
| "_" type_annotation? "=" expr { | "_" type_annotation? "=" expr {
{binders = PWild $1,[]; lhs_type=$2; eq=$3; let_rhs=$4} {binders = PWild $1, []; lhs_type=$2; eq=$3; let_rhs=$4}
} }
| unit type_annotation? "=" expr { | unit type_annotation? "=" expr {
{binders = PUnit $1,[]; lhs_type=$2; eq=$3; let_rhs=$4} {binders = PUnit $1, []; lhs_type=$2; eq=$3; let_rhs=$4}
} }
| record_pattern type_annotation? "=" expr { | record_pattern type_annotation? "=" expr {
Scoping.check_pattern (PRecord $1);
{binders = PRecord $1, []; lhs_type=$2; eq=$3; let_rhs=$4} {binders = PRecord $1, []; lhs_type=$2; eq=$3; let_rhs=$4}
} }
| par(closed_irrefutable) type_annotation? "=" expr { | par(closed_irrefutable) type_annotation? "=" expr {
Scoping.check_pattern $1.value.inside;
{binders = PPar $1, []; lhs_type=$2; eq=$3; let_rhs=$4} {binders = PPar $1, []; lhs_type=$2; eq=$3; let_rhs=$4}
} }
| tuple(sub_irrefutable) type_annotation? "=" expr { | tuple(sub_irrefutable) type_annotation? "=" expr {
Utils.nsepseq_iter Scoping.check_pattern $1;
let hd, tl = $1 in let hd, tl = $1 in
let start = pattern_to_region hd in let start = pattern_to_region hd in
let stop = last fst tl in let stop = last fst tl in
@ -419,8 +427,11 @@ fun_expr:
let region = cover start stop in let region = cover start stop in
let rec arg_to_pattern = function let rec arg_to_pattern = function
EVar v -> PVar v EVar v ->
Scoping.check_reserved_name v;
PVar v
| EAnnot {region; value = {inside = EVar v, colon, typ; _}} -> | EAnnot {region; value = {inside = EVar v, colon, typ; _}} ->
Scoping.check_reserved_name v;
let value = {pattern = PVar v; colon; type_expr = typ} let value = {pattern = PVar v; colon; type_expr = typ}
in PTyped {region; value} in PTyped {region; value}
| EPar p -> | EPar p ->
@ -468,8 +479,9 @@ fun_expr:
arg_to_pattern (EAnnot e), [] arg_to_pattern (EAnnot e), []
| ETuple {value = fun_args; _} -> | ETuple {value = fun_args; _} ->
let bindings = let bindings =
List.map (arg_to_pattern <@ snd) (snd fun_args) List.map (arg_to_pattern <@ snd) (snd fun_args) in
in arg_to_pattern (fst fun_args), bindings List.iter Scoping.check_pattern bindings;
arg_to_pattern (fst fun_args), bindings
| EUnit e -> | EUnit e ->
arg_to_pattern (EUnit e), [] arg_to_pattern (EUnit e), []
| e -> let open! SyntaxError | e -> let open! SyntaxError
@ -535,7 +547,7 @@ switch_expr(right_expr):
let region = cover start stop let region = cover start stop
and cases = { and cases = {
region = nsepseq_to_region (fun x -> x.region) $4; region = nsepseq_to_region (fun x -> x.region) $4;
value = $4} in value = $4} in
let value = { let value = {
kwd_match = $1; kwd_match = $1;
expr = $2; expr = $2;
@ -555,6 +567,7 @@ cases(right_expr):
case_clause(right_expr): case_clause(right_expr):
"|" pattern "=>" right_expr ";"? { "|" pattern "=>" right_expr ";"? {
Scoping.check_pattern $2;
let start = pattern_to_region $2 let start = pattern_to_region $2
and stop = expr_to_region $4 in and stop = expr_to_region $4 in
let region = cover start stop let region = cover start stop

View File

@ -6,39 +6,101 @@ module IO =
let options = EvalOpt.read "ReasonLIGO" ext let options = EvalOpt.read "ReasonLIGO" ext
end end
module ExtParser = module Parser =
struct struct
type ast = AST.t type ast = AST.t
type expr = AST.expr type expr = AST.expr
include Parser include Parser
end end
module ExtParserLog = module ParserLog =
struct struct
type ast = AST.t type ast = AST.t
type expr = AST.expr
include ParserLog include ParserLog
end end
module MyLexer = Lexer.Make (LexToken) module Lexer = Lexer.Make (LexToken)
module Unit = module Unit =
ParserUnit.Make (IO)(MyLexer)(AST)(ExtParser)(ParErr)(ExtParserLog) ParserUnit.Make (Lexer)(AST)(Parser)(ParErr)(ParserLog)(IO)
(* Main *) (* Main *)
let () = let issue_error point =
try Unit.run () with let error = Unit.format_error ~offsets:IO.options#offsets
(* Ad hoc errors from the parsers *) IO.options#mode point
in Stdlib.Error error
let parse parser : ('a,string) Stdlib.result =
try parser () with
(* Ad hoc errors from the parser *)
SyntaxError.Error (SyntaxError.WrongFunctionArguments expr) -> SyntaxError.Error (SyntaxError.WrongFunctionArguments expr) ->
let () = Unit.close_all () in let msg = "It looks like you are defining a function, \
let msg = "It looks like you are defining a function, \ however we do not\n\
however we do not\n\ understand the parameters declaration.\n\
understand the parameters declaration.\n\ Examples of valid functions:\n\
Examples of valid functions:\n\ let x = (a: string, b: int) : int => 3;\n\
let x = (a: string, b: int) : int => 3;\n\ let x = (a: string) : string => \"Hello, \" ++ a;\n"
let x = (a: string) : string => \"Hello, \" ++ a;\n" and reg = AST.expr_to_region expr in
and reg = AST.expr_to_region expr in let error = Unit.short_error ~offsets:IO.options#offsets
let error = Unit.short_error ~offsets:IO.options#offsets IO.options#mode msg reg
IO.options#mode msg reg in Stdlib.Error error
in Printf.eprintf "\027[31m%s\027[0m%!" error
(* Scoping errors *)
| Scoping.Error (Scoping.Reserved_name name) ->
let token =
Lexer.Token.mk_ident name.Region.value name.Region.region in
(match token with
(* Cannot fail because [name] is a not a
reserved name for the lexer. *)
Stdlib.Error _ -> assert false
| Ok invalid ->
issue_error
("Reserved name.\nHint: Change the name.\n", None, invalid))
| Scoping.Error (Scoping.Duplicate_variant name) ->
let token =
Lexer.Token.mk_constr name.Region.value name.Region.region in
let point = "Duplicate constructor in this sum type declaration.\n\
Hint: Change the constructor.\n",
None, token
in issue_error point
| Scoping.Error (Scoping.Non_linear_pattern var) ->
let token =
Lexer.Token.mk_ident var.Region.value var.Region.region in
(match token with
(* Cannot fail because [var] is a not a
reserved name for the lexer. *)
Stdlib.Error _ -> assert false
| Ok invalid ->
let point = "Repeated variable in this pattern.\n\
Hint: Change the name.\n",
None, invalid
in issue_error point)
| Scoping.Error (Scoping.Duplicate_field name) ->
let token =
Lexer.Token.mk_ident name.Region.value name.Region.region in
(match token with
(* Cannot fail because [name] is a not a
reserved name for the lexer. *)
Stdlib.Error _ -> assert false
| Ok invalid ->
let point =
"Duplicate field name in this record declaration.\n\
Hint: Change the name.\n",
None, invalid
in issue_error point)
let () =
if IO.options#expr
then match parse (fun () -> Unit.parse Unit.parse_expr) with
Stdlib.Ok _ -> ()
| Error msg -> Printf.eprintf "\027[31m%s\027[0m%!" msg
else match parse (fun () -> Unit.parse Unit.parse_contract) with
Stdlib.Ok _ -> ()
| Error msg -> Printf.eprintf "\027[31m%s\027[0m%!" msg

View File

@ -1,9 +1,15 @@
;; Build of the lexer
(ocamllex LexToken) (ocamllex LexToken)
;; Build of the parser
(menhir (menhir
(merge_into Parser) (merge_into Parser)
(modules ParToken Parser) (modules ParToken Parser)
(flags -la 1 --table --explain --strict --external-tokens LexToken)) (flags -la 1 --table --explain --strict --external-tokens LexToken))
;; Build of the parser as a library
(library (library
(name parser_reasonligo) (name parser_reasonligo)
@ -22,6 +28,18 @@
(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)))
;; Build of the unlexer (for covering the
;; error states of the LR automaton)
(executable
(name Unlexer)
(libraries str)
(preprocess
(pps bisect_ppx --conditional))
(modules Unlexer))
;; Local build of a standalone lexer
(executable (executable
(name LexerMain) (name LexerMain)
(libraries parser_reasonligo) (libraries parser_reasonligo)
@ -30,6 +48,8 @@
(pps bisect_ppx --conditional)) (pps bisect_ppx --conditional))
(flags (:standard -open Parser_shared -open Parser_reasonligo))) (flags (:standard -open Parser_shared -open Parser_reasonligo)))
;; Local build of a standalone parser
(executable (executable
(name ParserMain) (name ParserMain)
(libraries (libraries
@ -41,19 +61,16 @@
(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 ;; Build of the covering of error states in the LR automaton
(name Unlexer)
(libraries str)
(preprocess
(pps bisect_ppx --conditional))
(modules Unlexer))
(rule (rule
(targets Parser.msg) (targets Parser.msg)
(deps (:script_messages ../../../../vendors/ligo-utils/simple-utils/messages.sh) Parser.mly LexToken.mli ParToken.mly) (deps (:script_messages ../../../../vendors/ligo-utils/simple-utils/messages.sh) Parser.mly LexToken.mli ParToken.mly)
(action (run %{script_messages} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly Parser.mly ))) (action (run %{script_messages} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly Parser.mly )))
;; Build of all the LIGO source file that cover all error states
(rule (rule
(targets all.ligo) (targets all.religo)
(deps (:script_cover ../../../../vendors/ligo-utils/simple-utils/cover.sh) Parser.mly LexToken.mli ParToken.mly Parser.msg Unlexer.exe) (deps (:script_cover ../../../../vendors/ligo-utils/simple-utils/cover.sh) Parser.mly LexToken.mli ParToken.mly Parser.msg Unlexer.exe)
(action (run %{script_cover} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly --ext=ligo --unlexer=./Unlexer.exe --messages=Parser.msg --dir=. --concatenate Parser.mly ))) (action (run %{script_cover} --lex-tokens=LexToken.mli --par-tokens=ParToken.mly --ext=religo --unlexer=./Unlexer.exe --messages=Parser.msg --dir=. --concatenate Parser.mly )))

View File

@ -14,10 +14,11 @@ type options = <
offsets : bool; offsets : bool;
mode : [`Byte | `Point]; mode : [`Byte | `Point];
cmd : command; cmd : command;
mono : bool mono : bool;
expr : bool
> >
let make ~input ~libs ~verbose ~offsets ~mode ~cmd ~mono = let make ~input ~libs ~verbose ~offsets ~mode ~cmd ~mono ~expr =
object object
method input = input method input = input
method libs = libs method libs = libs
@ -26,6 +27,7 @@ let make ~input ~libs ~verbose ~offsets ~mode ~cmd ~mono =
method mode = mode method mode = mode
method cmd = cmd method cmd = cmd
method mono = mono method mono = mono
method expr = expr
end end
(** {1 Auxiliary functions} *) (** {1 Auxiliary functions} *)
@ -42,17 +44,18 @@ let abort msg =
let help language extension () = let help language extension () =
let file = Filename.basename Sys.argv.(0) in let file = Filename.basename Sys.argv.(0) in
printf "Usage: %s [<option> ...] [<input>%s | \"-\"]\n" file extension; printf "Usage: %s [<option> ...] [<input>%s | \"-\"]\n" file extension;
printf "where <input>%s is the %s source file (default: stdin)," extension language; printf "where <input>%s is the %s source file (default: stdin),\n" extension language;
print "and each <option> (if any) is one of the following:"; print "and each <option> (if any) is one of the following:";
print " -I <paths> Library paths (colon-separated)"; print " -I <paths> Library paths (colon-separated)";
print " -c, --copy Print lexemes of tokens and markup (lexer)"; print " -t, --tokens Print tokens";
print " -t, --tokens Print tokens (lexer)"; print " -u, --units Print lexical units";
print " -u, --units Print tokens and markup (lexer)"; print " -c, --copy Print lexemes and markup";
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 " --mono Use Menhir monolithic API";
print " --verbose=<stages> cmdline, cpp, ast-tokens, ast (colon-separated)"; print " --expr Parse an expression";
print " --verbose=<stages> cli, 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";
exit 0 exit 0
@ -74,6 +77,7 @@ and input = ref None
and libs = ref [] and libs = ref []
and verb_str = ref "" and verb_str = ref ""
and mono = ref false and mono = ref false
and expr = ref false
let split_at_colon = Str.(split (regexp ":")) let split_at_colon = Str.(split (regexp ":"))
@ -94,6 +98,7 @@ let specs language extension =
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, "mono", set mono true, None;
noshort, "expr", set expr 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
@ -129,7 +134,8 @@ 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 "mono = %b\n" !mono;
printf "expr = %b\n" !expr;
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)
@ -137,7 +143,7 @@ let print_opt () =
let check extension = let check extension =
let () = let () =
if Utils.String.Set.mem "cmdline" !verbose then print_opt () in if Utils.String.Set.mem "cli" !verbose then print_opt () in
let input = let input =
match !input with match !input with
@ -158,11 +164,12 @@ let check extension =
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 mono = !mono
and expr = !expr
and verbose = !verbose and verbose = !verbose
and libs = !libs in and libs = !libs in
let () = let () =
if Utils.String.Set.mem "cmdline" verbose then if Utils.String.Set.mem "cli" verbose then
begin begin
printf "\nEXPORTED COMMAND LINE\n"; printf "\nEXPORTED COMMAND LINE\n";
printf "copy = %b\n" copy; printf "copy = %b\n" copy;
@ -172,6 +179,7 @@ let check extension =
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 "mono = %b\n" mono;
printf "expr = %b\n" expr;
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)
@ -186,7 +194,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 ~mono in make ~input ~libs ~verbose ~offsets ~mode ~cmd ~mono ~expr
(** {1 Parsing the command-line options} *) (** {1 Parsing the command-line options} *)
@ -195,7 +203,7 @@ let read language extension =
Getopt.parse_cmdline (specs language extension) anonymous; Getopt.parse_cmdline (specs language extension) anonymous;
(verb_str := (verb_str :=
let apply e a = let apply e a =
if a <> "" then Printf.sprintf "%s, %s" e a else e if a = "" then e else Printf.sprintf "%s, %s" e a
in Utils.String.Set.fold apply !verbose ""); in Utils.String.Set.fold apply !verbose "");
check extension check extension
with Getopt.Error msg -> abort msg with Getopt.Error msg -> abort msg

View File

@ -1,4 +1,4 @@
(** Parsing the command-line options of PascaLIGO *) (** Parsing the command-line options of LIGO *)
(** The type [command] denotes some possible behaviours of the (** The type [command] denotes some possible behaviours of the
compiler. The constructors are compiler. The constructors are
@ -23,12 +23,11 @@ type command = Quiet | Copy | Units | Tokens
(** The type [options] gathers the command-line options. (** The type [options] gathers the command-line options.
{ul {ul
{li If the field [input] is [Some src], the name of the {li If the field [input] is [Some src], the name of the LIGO
PascaLIGO source file, with the extension ".ligo", is source file is [src]. If [input] is [Some "-"] or [None],
[src]. If [input] is [Some "-"] or [None], the source file the source file is read from standard input.}
is read from standard input.}
{li The field [libs] is the paths where to find PascaLIGO files {li The field [libs] is the paths where to find LIGO files
for inclusion (#include).} for inclusion (#include).}
{li The field [verbose] is a set of stages of the compiler {li The field [verbose] is a set of stages of the compiler
@ -41,8 +40,14 @@ type command = Quiet | Copy | Units | Tokens
{li If the value [mode] is [`Byte], then the unit in which {li If the value [mode] is [`Byte], then the unit in which
source positions and regions are expressed in messages is source positions and regions are expressed in messages is
the byte. If [`Point], the unit is unicode points.} the byte. If [`Point], the unit is unicode points.}
}
*) {li If the field [mono] is [true], then the monolithic API of
Menhir is called, otherwise the incremental API is.}
{li If the field [expr] is [true], then the parser for
expressions is used, otherwise a full-fledged contract is
expected.}
} *)
type options = < type options = <
input : string option; input : string option;
libs : string list; libs : string list;
@ -50,7 +55,8 @@ type options = <
offsets : bool; offsets : bool;
mode : [`Byte | `Point]; mode : [`Byte | `Point];
cmd : command; cmd : command;
mono : bool mono : bool;
expr : bool
> >
val make : val make :
@ -61,6 +67,7 @@ val make :
mode:[`Byte | `Point] -> mode:[`Byte | `Point] ->
cmd:command -> cmd:command ->
mono:bool -> mono:bool ->
expr:bool ->
options options
(** Parsing the command-line options on stdin. The first parameter is (** Parsing the command-line options on stdin. The first parameter is

View File

@ -77,8 +77,7 @@ module type TOKEN =
val mk_string : lexeme -> Region.t -> token val mk_string : lexeme -> Region.t -> token
val mk_bytes : lexeme -> Region.t -> token val mk_bytes : lexeme -> Region.t -> token
val mk_constr : lexeme -> Region.t -> token val mk_constr : lexeme -> Region.t -> token
val mk_attr : lexeme -> Region.t -> (token, attr_err) result val mk_attr : string -> lexeme -> Region.t -> (token, attr_err) result
val mk_attr2 : lexeme -> Region.t -> (token, attr_err) result
val eof : Region.t -> token val eof : Region.t -> token
(* Predicates *) (* Predicates *)
@ -108,6 +107,8 @@ module type TOKEN =
* a function [get_pos] that returns the current position, and * a function [get_pos] that returns the current position, and
* a function [get_last] that returns the region of the last * a function [get_last] that returns the region of the last
recognised token. recognised token.
* a function [get_file] that returns the name of the file being scanned
(empty string if [stdin]).
Note that a module [Token] is exported too, because the signature Note that a module [Token] is exported too, because the signature
of the exported functions depend on it. of the exported functions depend on it.
@ -140,6 +141,7 @@ module type S =
get_win : unit -> window; get_win : unit -> window;
get_pos : unit -> Pos.t; get_pos : unit -> Pos.t;
get_last : unit -> Region.t; get_last : unit -> Region.t;
get_file : unit -> file_path;
close : unit -> unit close : unit -> unit
} }

View File

@ -119,8 +119,7 @@ module type TOKEN =
val mk_string : lexeme -> Region.t -> token val mk_string : lexeme -> Region.t -> token
val mk_bytes : lexeme -> Region.t -> token val mk_bytes : lexeme -> Region.t -> token
val mk_constr : lexeme -> Region.t -> token val mk_constr : lexeme -> Region.t -> token
val mk_attr : lexeme -> Region.t -> (token, attr_err) result val mk_attr : string -> lexeme -> Region.t -> (token, attr_err) result
val mk_attr2 : lexeme -> Region.t -> (token, attr_err) result
val eof : Region.t -> token val eof : Region.t -> token
(* Predicates *) (* Predicates *)
@ -164,6 +163,7 @@ module type S =
get_win : unit -> window; get_win : unit -> window;
get_pos : unit -> Pos.t; get_pos : unit -> Pos.t;
get_last : unit -> Region.t; get_last : unit -> Region.t;
get_file : unit -> file_path;
close : unit -> unit close : unit -> unit
} }
@ -177,8 +177,9 @@ module type S =
exception Error of error Region.reg exception Error of error Region.reg
val format_error : ?offsets:bool -> [`Byte | `Point] -> val format_error :
error Region.reg -> file:bool -> string ?offsets:bool -> [`Byte | `Point] ->
error Region.reg -> file:bool -> string
end end
(* The functorised interface (* The functorised interface
@ -441,9 +442,9 @@ module Make (Token: TOKEN) : (S with module Token = Token) =
exception Error of error Region.reg exception Error of error Region.reg
let format_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
let reg = region#to_string ~file ~offsets mode in and reg = region#to_string ~file ~offsets mode
sprintf "\027[31mLexical error %s:\n%s\027[0m%!" reg msg in sprintf "Lexical error %s:\n%s" reg msg
let fail region value = raise (Error Region.{region; value}) let fail region value = raise (Error Region.{region; value})
@ -505,7 +506,7 @@ module Make (Token: TOKEN) : (S with module Token = Token) =
let num = Z.of_string (integral ^ fractional) let num = Z.of_string (integral ^ fractional)
and den = Z.of_string ("1" ^ String.make (len-index-1) '0') and den = Z.of_string ("1" ^ String.make (len-index-1) '0')
and million = Q.of_string "1000000" in and million = Q.of_string "1000000" in
let mutez = Q.make num den |> Q.mul million in let mutez = Q.make num den |> Q.mul million in
let should_be_1 = Q.den mutez in let should_be_1 = Q.den mutez in
if Z.equal Z.one should_be_1 then Some (Q.num mutez) else None if Z.equal Z.one should_be_1 then Some (Q.num mutez) else None
| exception Not_found -> assert false | exception Not_found -> assert false
@ -530,21 +531,13 @@ module Make (Token: TOKEN) : (S with module Token = Token) =
Ok token -> token, state Ok token -> token, state
| Error Token.Reserved_name -> fail region (Reserved_name lexeme) | Error Token.Reserved_name -> fail region (Reserved_name lexeme)
let mk_attr state buffer attr = let mk_attr header attr state buffer =
let region, _, state = sync state buffer in let region, _, state = sync state buffer in
match Token.mk_attr attr region with match Token.mk_attr header attr region with
Ok token -> Ok token ->
token, state token, state
| Error Token.Invalid_attribute -> | Error Token.Invalid_attribute ->
fail region Invalid_attribute fail region Invalid_attribute
let mk_attr2 state buffer attr =
let region, _, state = sync state buffer in
match Token.mk_attr2 attr region with
Ok token ->
token, state
| Error Token.Invalid_attribute ->
fail region Invalid_attribute
let mk_constr state buffer = let mk_constr state buffer =
let region, lexeme, state = sync state buffer let region, lexeme, state = sync state buffer
@ -579,6 +572,7 @@ let capital = ['A'-'Z']
let letter = small | capital let letter = small | capital
let ident = small (letter | '_' | digit)* let ident = small (letter | '_' | digit)*
let constr = capital (letter | '_' | digit)* let constr = capital (letter | '_' | digit)*
let attr = ident | constr
let hexa_digit = digit | ['A'-'F'] let hexa_digit = digit | ['A'-'F']
let byte = hexa_digit hexa_digit let byte = hexa_digit hexa_digit
let byte_seq = byte | byte (byte | '_')* byte let byte_seq = byte | byte (byte | '_')* byte
@ -586,8 +580,8 @@ let bytes = "0x" (byte_seq? as seq)
let esc = "\\n" | "\\\"" | "\\\\" | "\\b" let esc = "\\n" | "\\\"" | "\\\\" | "\\b"
| "\\r" | "\\t" | "\\x" byte | "\\r" | "\\t" | "\\x" byte
let pascaligo_sym = "=/=" | '#' | ":=" let pascaligo_sym = "=/=" | '#' | ":="
let cameligo_sym = "<>" | "::" | "||" | "&&" | "[@" let cameligo_sym = "<>" | "::" | "||" | "&&"
let reasonligo_sym = '!' | "=>" | "!=" | "==" | "++" | "..." | "||" | "&&" | "[@" let reasonligo_sym = '!' | "=>" | "!=" | "==" | "++" | "..." | "||" | "&&"
let symbol = let symbol =
';' | ',' | '(' | ')'| '[' | ']' | '{' | '}' ';' | ',' | '(' | ')'| '[' | ']' | '{' | '}'
@ -613,21 +607,24 @@ rule init state = parse
| _ { rollback lexbuf; scan state lexbuf } | _ { rollback lexbuf; scan state lexbuf }
and scan state = parse and scan state = parse
nl { scan (push_newline state lexbuf) lexbuf } nl { scan (push_newline state lexbuf) lexbuf }
| ' '+ { scan (push_space state lexbuf) lexbuf } | ' '+ { scan (push_space state lexbuf) lexbuf }
| '\t'+ { scan (push_tabs state lexbuf) lexbuf } | '\t'+ { scan (push_tabs state lexbuf) lexbuf }
| ident { mk_ident state lexbuf |> enqueue } | ident { mk_ident state lexbuf |> enqueue }
| constr { mk_constr state lexbuf |> enqueue } | constr { mk_constr state lexbuf |> enqueue }
| bytes { (mk_bytes seq) state lexbuf |> enqueue } | bytes { mk_bytes seq state lexbuf |> enqueue }
| natural 'n' { mk_nat state lexbuf |> enqueue } | natural 'n' { mk_nat state lexbuf |> enqueue }
| natural "mutez" { mk_mutez state lexbuf |> enqueue } | natural "mutez" { mk_mutez state lexbuf |> enqueue }
| natural "tz" { mk_tz state lexbuf |> enqueue } | natural "tz"
| decimal "tz" { mk_tz_decimal state lexbuf |> enqueue } | natural "tez" { mk_tz state lexbuf |> enqueue }
| natural { mk_int state lexbuf |> enqueue } | decimal "tz"
| symbol { mk_sym state lexbuf |> enqueue } | decimal "tez" { mk_tz_decimal state lexbuf |> enqueue }
| eof { mk_eof state lexbuf |> enqueue } | natural { mk_int state lexbuf |> enqueue }
| "[@" (ident|constr as attr) "]" { mk_attr state lexbuf attr |> enqueue } | symbol { mk_sym state lexbuf |> enqueue }
| "[@@" (ident|constr as attr) "]" { mk_attr2 state lexbuf attr |> enqueue } | eof { mk_eof state lexbuf |> enqueue }
| "[@" (attr as a) "]" { mk_attr "[@" a state lexbuf |> enqueue }
| "[@@" (attr as a) "]" { mk_attr "[@@" a state lexbuf |> enqueue }
| '"' { let opening, _, state = sync state lexbuf in | '"' { let opening, _, state = sync state lexbuf in
let thread = {opening; len=1; acc=['"']} in let thread = {opening; len=1; acc=['"']} in
scan_string thread state lexbuf |> mk_string |> enqueue } scan_string thread state lexbuf |> mk_string |> enqueue }
@ -676,8 +673,7 @@ and scan state = parse
and file = Filename.basename file in and file = Filename.basename file in
let pos = state.pos#set ~file ~line ~offset:0 in let pos = state.pos#set ~file ~line ~offset:0 in
let state = {state with pos} in let state = {state with pos} in
scan state lexbuf scan state lexbuf }
}
(* Some special errors (* Some special errors
@ -864,6 +860,7 @@ type instance = {
get_win : unit -> window; get_win : unit -> window;
get_pos : unit -> Pos.t; get_pos : unit -> Pos.t;
get_last : unit -> Region.t; get_last : unit -> Region.t;
get_file : unit -> file_path;
close : unit -> unit close : unit -> unit
} }
@ -871,7 +868,7 @@ let open_token_stream file_path_opt =
let file_path = match file_path_opt with let file_path = match file_path_opt with
None | Some "-" -> "" None | Some "-" -> ""
| Some file_path -> file_path in | Some file_path -> file_path in
let pos = Pos.min#set_file file_path in let pos = Pos.min ~file:file_path in
let buf_reg = ref (pos#byte, pos#byte) let buf_reg = ref (pos#byte, pos#byte)
and first_call = ref true and first_call = ref true
and decoder = Uutf.decoder ~encoding:`UTF_8 `Manual in and decoder = Uutf.decoder ~encoding:`UTF_8 `Manual in
@ -886,7 +883,8 @@ let open_token_stream file_path_opt =
let get_pos () = !state.pos let get_pos () = !state.pos
and get_last () = !state.last and get_last () = !state.last
and get_win () = !state.window in and get_win () = !state.window
and get_file () = file_path in
let patch_buffer (start, stop) buffer = let patch_buffer (start, stop) buffer =
let open Lexing in let open Lexing in
@ -958,7 +956,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_win; get_pos; get_last; close} {read = read_token; buffer; get_win; get_pos; get_last; get_file; close}
end (* of functor [Make] in HEADER *) end (* of functor [Make] in HEADER *)
(* END TRAILER *) (* END TRAILER *)

View File

@ -1,7 +1,5 @@
(** Embedding the LIGO lexer in a debug module *) (** Embedding the LIGO lexer in a debug module *)
let sprintf = Printf.sprintf
module type S = module type S =
sig sig
module Lexer : Lexer.S module Lexer : Lexer.S
@ -15,12 +13,12 @@ module type S =
val trace : val trace :
?offsets:bool -> [`Byte | `Point] -> ?offsets:bool -> [`Byte | `Point] ->
file_path option -> EvalOpt.command -> unit file_path option -> EvalOpt.command ->
(unit, string) Stdlib.result
end end
module Make (Lexer: Lexer.S) : (S with module Lexer = Lexer) = module Make (Lexer: Lexer.S) : (S with module Lexer = Lexer) =
struct struct
module Lexer = Lexer module Lexer = Lexer
module Token = Lexer.Token module Token = Lexer.Token
@ -49,28 +47,29 @@ module Make (Lexer: Lexer.S) : (S with module Lexer = Lexer) =
type file_path = string type file_path = string
let trace ?(offsets=true) mode file_path_opt command : unit = let trace ?(offsets=true) mode file_path_opt command :
(unit, string) Stdlib.result =
try try
let Lexer.{read; buffer; close; _} = let Lexer.{read; buffer; close; _} =
Lexer.open_token_stream file_path_opt Lexer.open_token_stream file_path_opt in
and cout = stdout in let log = output_token ~offsets mode command stdout
let log = output_token ~offsets mode command cout and close_all () = close (); close_out stdout in
and close_all () = close (); close_out cout in
let rec iter () = let rec iter () =
match read ~log buffer with match read ~log buffer with
token -> token ->
if Token.is_eof token then close_all () if Token.is_eof token
then Stdlib.Ok ()
else iter () else iter ()
| exception Lexer.Error e -> | exception Lexer.Error error ->
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
let msg = let msg =
Lexer.format_error ~offsets mode e ~file Lexer.format_error ~offsets mode ~file error
in prerr_string msg; in Stdlib.Error msg in
close_all () let result = iter ()
in iter () in (close_all (); result)
with Sys_error msg -> Utils.highlight (sprintf "%s\n" msg) with Sys_error msg -> Stdlib.Error msg
end end

View File

@ -11,7 +11,8 @@ module type S =
val trace : val trace :
?offsets:bool -> [`Byte | `Point] -> ?offsets:bool -> [`Byte | `Point] ->
file_path option -> EvalOpt.command -> unit file_path option -> EvalOpt.command ->
(unit, string) Stdlib.result
end end
module Make (Lexer: Lexer.S) : S with module Lexer = Lexer module Make (Lexer: Lexer.S) : S with module Lexer = Lexer

View File

@ -1,21 +1,20 @@
(* Functor to build a standalone LIGO lexer *) (* Functor to build a standalone LIGO lexer *)
module type S = module type IO =
sig sig
val ext : string (* LIGO file extension *) val ext : string (* LIGO file extension *)
val options : EvalOpt.options (* CLI options *) val options : EvalOpt.options (* CLI options *)
end end
module Make (IO: S) (Lexer: Lexer.S) = module Make (IO: IO) (Lexer: Lexer.S) =
struct struct
open Printf open Printf
module SSet = Utils.String.Set
(* Error printing and exception tracing *) (* Error printing and exception tracing *)
let () = Printexc.record_backtrace true let () = Printexc.record_backtrace true
let external_ text =
Utils.highlight (sprintf "External error: %s" text); exit 1
(* Preprocessing the input source and opening the input channels *) (* Preprocessing the input source and opening the input channels *)
(* Path for CPP inclusions (#include) *) (* Path for CPP inclusions (#include) *)
@ -29,7 +28,7 @@ module Make (IO: S) (Lexer: Lexer.S) =
let prefix = let prefix =
match IO.options#input with match IO.options#input with
None | Some "-" -> "temp" None | Some "-" -> "temp"
| Some file -> Filename.(file |> basename |> remove_extension) | Some file -> Filename.(file |> basename |> remove_extension)
let suffix = ".pp" ^ IO.ext let suffix = ".pp" ^ IO.ext
@ -42,24 +41,68 @@ module Make (IO: S) (Lexer: Lexer.S) =
let cpp_cmd = let cpp_cmd =
match IO.options#input with match IO.options#input with
None | Some "-" -> None | Some "-" ->
sprintf "cpp -traditional-cpp%s - > %s" sprintf "cpp -traditional-cpp%s - > %s"
lib_path pp_input lib_path pp_input
| Some file -> | Some file ->
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 () =
if Utils.String.Set.mem "cpp" IO.options#verbose
then eprintf "%s\n%!" cpp_cmd;
if Sys.command cpp_cmd <> 0 then
external_ (sprintf "the command \"%s\" failed." cpp_cmd)
(* Running the lexer on the input file *) (* Running the lexer on the input file *)
let scan () : (Lexer.token list, string) Stdlib.result =
(* Preprocessing the input *)
if SSet.mem "cpp" IO.options#verbose
then eprintf "%s\n%!" cpp_cmd
else ();
if Sys.command cpp_cmd <> 0 then
let msg =
sprintf "External error: the command \"%s\" failed." cpp_cmd
in Stdlib.Error msg
else
try
let Lexer.{read; buffer; close; _} =
Lexer.open_token_stream (Some pp_input) in
let close_all () = close (); close_out stdout in
let rec read_tokens tokens =
match read ~log:(fun _ _ -> ()) buffer with
token ->
if Lexer.Token.is_eof token
then Stdlib.Ok (List.rev tokens)
else read_tokens (token::tokens)
| exception Lexer.Error error ->
let file =
match IO.options#input with
None | Some "-" -> false
| Some _ -> true in
let msg =
Lexer.format_error ~offsets:IO.options#offsets
IO.options#mode ~file error
in Stdlib.Error msg in
let result = read_tokens []
in close_all (); result
with Sys_error msg -> close_out stdout; Stdlib.Error msg
(* Tracing the lexing (effectful) *)
module Log = LexerLog.Make (Lexer) module Log = LexerLog.Make (Lexer)
let () = Log.trace ~offsets:IO.options#offsets let trace () : (unit, string) Stdlib.result =
IO.options#mode (Some pp_input) (* Preprocessing the input *)
IO.options#cmd
if SSet.mem "cpp" IO.options#verbose
then eprintf "%s\n%!" cpp_cmd
else ();
if Sys.command cpp_cmd <> 0 then
let msg =
sprintf "External error: the command \"%s\" failed." cpp_cmd
in Stdlib.Error msg
else
Log.trace ~offsets:IO.options#offsets
IO.options#mode
(Some pp_input)
IO.options#cmd
end end

View File

@ -0,0 +1,13 @@
(* Functor to build a standalone LIGO lexer *)
module type IO =
sig
val ext : string (* LIGO file extension *)
val options : EvalOpt.options (* CLI options *)
end
module Make (IO: IO) (Lexer: Lexer.S) :
sig
val scan : unit -> (Lexer.token list, string) Stdlib.result
val trace : unit -> (unit, string) Stdlib.result
end

View File

@ -0,0 +1,163 @@
module Region = Simple_utils.Region
type macro = {
origin : Region.t; (* Not ghost *)
current : Region.t (* Maybe ghost *)
}
type location =
Loc of Region.t (* Not ghost *)
| Link of macro
(* Regions must not be ghosts and strings must not be empty. *)
type valid_lexeme = string Region.reg (* Not ghost, not empty. *)
type invalid_lexeme = string Region.reg (* Not ghost, empty if EOF. *)
type phase =
Lexer
| Parser of valid_lexeme option * invalid_lexeme
| Scoping
type error = <
location : location;
message : string; (* Sentence ending with a period *)
hint : string; (* Suggestion to solve the issue *)
help : string (* Off-program help *)
>
type invalid_error = Ghost_region
let check_loc = function
Loc reg ->
if reg#is_ghost then
Stdlib.Error Ghost_region
else Ok ()
| Link {origin; _} ->
if origin#is_ghost then
Stdlib.Error Ghost_region
else Ok ()
let make_error ~location ~message ~hint ~help =
match check_loc location with
Stdlib.Ok () ->
Ok (object
method location = location
method message = message
method hint = hint
method help = help
end)
| Error _ as e -> e
type warning = <
location : location;
message : string; (* Sentence ending with a period *)
hint : string; (* Idem *)
>
type invalid_warning = invalid_error
let make_warning ~location ~message ~hint =
match check_loc location with
Stdlib.Ok () ->
Ok (object
method location = location
method message = message
method hint = hint
method help = help
end)
| Error _ as e -> e
type kind =
Error of error (* Failure of an external invariant *)
| Internal of string (* Failure of an internal invariant *)
| External of string (* Failure of an external process *)
| Warning of warning
| Info of (unit -> string) (* Log *)
type entry = <
phase : phase;
kind : kind
>
type invalid_entry =
Ghost_lexeme
| Empty_lexeme
let check_phase = function
Parser (Some valid_lexeme, invalid_lexeme) ->
let open Region in
if valid_lexeme.region#is_ghost
|| invalid_lexeme.region#is_ghost
then Stdlib.Error Ghost_lexeme
else if valid_lexeme.value = ""
then Stdlib.Error Empty_lexeme
else Ok ()
| Parser (None, invalid_lexeme) ->
if invalid_lexeme.region#is_ghost
then Stdlib.Error Ghost_lexeme
else Ok ()
| Lexer
| Scoping -> Ok ()
let make_entry ~phase ~kind =
match check_phase phase with
Stdlib.Error _ as e -> e
| Ok () -> Ok (object
method phase = phase
method kind = kind
end)
type memo = <
mode : [`Byte | `Point]; (* Bytes vs UTF-8 *)
offsets : bool; (* [true] for horizontal offsets *)
log : entry FQueue.t
>
type t = memo
let empty_memo ~mode ~offsets : memo =
object
method mode = mode
method offsets = offsets
method log = FQueue.empty
method enqueue entry = {< log = FQueue.enq entry log >}
method dequeue =
match FQueue.deq log with
None -> None
| Some (log, entry) -> Some ({< log=log >}, entry)
end
let sprintf = Printf.sprintf
let string_of_entry ~(file:bool) entry : string =
let reg = entry#region#to_string
~file
~offsets:entry#offsets
error#mode in
let string =
match error#phase with
Parser (None, invalid_lexeme) ->
(match invalid_lexeme.Region.value with
"" -> sprintf "Parse error %s" reg (* EOF *)
| lexeme -> sprintf "Parse error %s, before \"%s\""
reg lexeme)
| Parser (Some valid_lexeme, invalid_lexeme) ->
let string =
sprintf "Parse error %s, after \"%s\""
reg valid_lexeme.Region.value in
(match invalid_lexeme.Region.value with
"" -> string (* EOF *)
| lexeme -> sprintf "%s and before \"%s\"" string lexeme)
| Lexer ->
sprintf "Lexical error %s" reg
| Scoping ->
sprintf "Scoping error %s" reg in
let string =
string
^ (if error#message = "" then "."
else ":\n" ^ error#message) ^ "\n" in
let string =
string ^ (if error#hint = "" then ""
else sprintf "Hint: %s\n" error#hint)
in string

View File

@ -0,0 +1,120 @@
(* This module defines compilation memos. *)
(* Locations *)
module Region = Simple_utils.Region
type macro = private <
origin : Region.t; (* Not ghost *)
current : Region.t (* Maybe ghost *)
>
type location = private
Loc of Region.t (* Not ghost *)
| Link of macro
type invalid_loc = Ghost_region
val make_loc :
Region.t -> (location, invalid_loc) Stdlib.result
val make_link :
origin:Region.t ->
current:Region.t ->
(location, invalid_loc) Stdlib.result
type 'a located = <
value : 'a;
location : location
>
val make_located : value:'a -> location:location -> 'a located
(* Lexemes *)
type lexeme = string location (* Not ghost, empty => EOF *)
type window = <
valid_lexeme : lexeme option;
invalid_lexeme : lexeme
>
val make_window : ?valid:lexeme -> invalid:lexeme -> window
(* Compilation phases *)
type phase =
Lexer
| Parser of window
| Scoping
(* Messages *)
type message = private string
type invalid_message = Empty_message
val make_message : string -> (message, invalid_error) Stdlib.result
val string_of_message : message -> string
(* Errors *)
type error = <
location : location;
message : message; (* Non-empty string (ending with a period) *)
hint : string; (* Suggestion to solve the issue (may be empty) *)
help : string (* Off-program help (may be empty) *)
>
val make_error :
location:location ->
message:message ->
hint:string ->
help:string ->
error
(* Warnings *)
type warning = <
location : location;
message : message; (* Non-empty string (ending with a period) *)
hint : string; (* May empty *)
>
val make_warning :
location:location ->
message:message ->
hint:string ->
warning
(* Kinds of entries *)
type kind =
Error of error (* Failure of an external invariant *)
| Internal of message (* Failure of an internal invariant (non-empty) *)
| External of message (* Failure of an external process (non-empty) *)
| Warning of warning
| Info of (unit -> message) (* Log (not-empty) *)
type entry = private <
phase : phase;
kind : kind
>
val make_entry : phase:phase -> kind:kind -> entry
val string_of_entry : file:bool -> entry -> string
(* Memos *)
type memo = <
mode : [`Byte | `Point]; (* Bytes vs UTF-8 *)
offsets : bool; (* [true] for horizontal offsets *)
log : entry FQueue.t;
enqueue : entry -> memo;
dequeue : (memo * entry) option
>
type t = memo
val empty_memo : mode:[`Byte | `Point] -> offsets:bool -> memo

View File

@ -77,6 +77,26 @@ module Make (Lexer: Lexer.S)
exception Point of error exception Point of error
let format_error ?(offsets=true) mode (msg, valid_opt, invalid) =
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 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 = Lexer.Token.to_lexeme valid in
let s = Printf.sprintf ", after \"%s\"" valid_lexeme in
if Lexer.Token.is_eof invalid then s
else
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)
let failure get_win checkpoint = let failure get_win checkpoint =
let message = ParErr.message (state checkpoint) in let message = ParErr.message (state checkpoint) in
match get_win () with match get_win () with
@ -86,42 +106,28 @@ module Make (Lexer: Lexer.S)
| Lexer.Two (invalid, valid) -> | Lexer.Two (invalid, valid) ->
raise (Point (message, Some valid, invalid)) raise (Point (message, Some valid, invalid))
(* The two Menhir APIs are called from the following two functions. *) (* The monolithic API of Menhir *)
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
let ast = I.loop_handle success failure supplier parser
in close (); ast
let mono_contract = Parser.contract let mono_contract = Parser.contract
(* Errors *) let mono_expr = Parser.interactive_expr
let format_error ?(offsets=true) mode (msg, valid_opt, invalid) = (* Incremental API of Menhir *)
let invalid_region = Lexer.Token.to_region invalid in
let header = module Incr = Parser.Incremental
"Parse error " ^ invalid_region#to_string ~offsets mode in
let trailer = let incr_contract Lexer.{read; buffer; get_win; close; _} =
match valid_opt with let supplier = I.lexer_lexbuf_to_supplier read buffer
None -> and failure = failure get_win in
if Lexer.Token.is_eof invalid then "" let parser = Incr.contract buffer.Lexing.lex_curr_p in
else let invalid_lexeme = Lexer.Token.to_lexeme invalid in let ast = I.loop_handle success failure supplier parser
Printf.sprintf ", before \"%s\"" invalid_lexeme in close (); ast
| Some valid ->
let valid_lexeme = Lexer.Token.to_lexeme valid in let incr_expr Lexer.{read; buffer; get_win; close; _} =
let s = Printf.sprintf ", after \"%s\"" valid_lexeme in let supplier = I.lexer_lexbuf_to_supplier read buffer
if Lexer.Token.is_eof invalid then s and failure = failure get_win in
else let parser = Incr.interactive_expr buffer.Lexing.lex_curr_p in
let invalid_lexeme = Lexer.Token.to_lexeme invalid in let expr = I.loop_handle success failure supplier parser
Printf.sprintf "%s and before \"%s\"" s invalid_lexeme in in close (); expr
let header = header ^ trailer in
header ^ (if msg = "" then ".\n" else ":\n" ^ msg)
let short_error ?(offsets=true) mode msg (invalid_region: Region.t) =
let () = assert (not (invalid_region#is_ghost)) in
let header =
"Parse error " ^ invalid_region#to_string ~offsets mode in
header ^ (if msg = "" then ".\n" else ":\n" ^ msg)
end end

View File

@ -2,6 +2,9 @@
module Region = Simple_utils.Region module Region = Simple_utils.Region
(* The signature generated by Menhir with additional type definitions
for [ast] and [expr]. *)
module type PARSER = module type PARSER =
sig sig
(* The type of tokens. *) (* The type of tokens. *)
@ -16,8 +19,10 @@ module type PARSER =
(* The monolithic API. *) (* The monolithic API. *)
val interactive_expr : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> expr val interactive_expr :
val contract : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> ast (Lexing.lexbuf -> token) -> Lexing.lexbuf -> expr
val contract :
(Lexing.lexbuf -> token) -> Lexing.lexbuf -> ast
(* The incremental API. *) (* The incremental API. *)
@ -42,14 +47,15 @@ module Make (Lexer: Lexer.S)
(Parser: PARSER with type token = Lexer.Token.token) (Parser: PARSER with type token = Lexer.Token.token)
(ParErr: sig val message : int -> string end) : (ParErr: sig val message : int -> string end) :
sig sig
(* Monolithic and incremental APIs of Menhir for parsing *) (* The monolithic API of Menhir *)
val mono_contract : val mono_contract :
(Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> Parser.ast (Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> Parser.ast
val incr_contract :
Lexer.instance -> Parser.ast
(* Error handling *) val mono_expr :
(Lexing.lexbuf -> Lexer.token) -> Lexing.lexbuf -> Parser.expr
(* Incremental API of Menhir *)
type message = string type message = string
type valid = Parser.token type valid = Parser.token
@ -58,9 +64,8 @@ module Make (Lexer: Lexer.S)
exception Point of error exception Point of error
val format_error : val incr_contract : Lexer.instance -> Parser.ast
?offsets:bool -> [`Byte | `Point] -> error -> string val incr_expr : Lexer.instance -> Parser.expr
val short_error : val format_error : ?offsets:bool -> [`Point | `Byte] -> error -> string
?offsets:bool -> [`Byte | `Point] -> message -> Region.t -> string
end end

View File

@ -1,6 +1,8 @@
(* Functor to build a standalone LIGO parser *) (* Functor to build a standalone LIGO parser *)
module type S = module Region = Simple_utils.Region
module type IO =
sig sig
val ext : string (* LIGO file extension *) val ext : string (* LIGO file extension *)
val options : EvalOpt.options (* CLI options *) val options : EvalOpt.options (* CLI options *)
@ -10,40 +12,35 @@ module type Pretty =
sig sig
type state type state
type ast type ast
val pp_ast : type expr
state -> ast -> unit
val mk_state : val mk_state :
offsets:bool -> mode:[`Point|`Byte] -> buffer:Buffer.t -> state offsets:bool -> mode:[`Point|`Byte] -> buffer:Buffer.t -> state
val print_tokens :
state -> ast -> unit val pp_ast : state -> ast -> unit
val pp_expr : state -> expr -> unit
val print_tokens : state -> ast -> unit
val print_expr : state -> expr -> unit
end end
module Make (IO: S) module Make (Lexer: Lexer.S)
(Lexer: Lexer.S)
(AST: sig type t type expr end) (AST: sig type t type expr end)
(Parser: ParserAPI.PARSER (Parser: ParserAPI.PARSER
with type ast = AST.t with type ast = AST.t
and type expr = AST.expr and type expr = AST.expr
and type token = Lexer.token) and type token = Lexer.token)
(ParErr: sig val message : int -> string end) (ParErr: sig val message : int -> string end)
(ParserLog: Pretty with type ast = AST.t) = (ParserLog: Pretty with type ast = AST.t
and type expr = AST.expr)
(IO: IO) =
struct struct
open Printf open Printf
module SSet = Utils.String.Set
(* Error printing and exception tracing *) (* Error printing and exception tracing *)
let () = Printexc.record_backtrace true let () = Printexc.record_backtrace true
let external_ text =
Utils.highlight (sprintf "External error: %s" text); exit 1
(* Extracting the input file *)
let file =
match IO.options#input with
None | Some "-" -> false
| Some _ -> true
(* Preprocessing the input source and opening the input channels *) (* Preprocessing the input source and opening the input channels *)
(* Path for CPP inclusions (#include) *) (* Path for CPP inclusions (#include) *)
@ -57,14 +54,15 @@ module Make (IO: S)
let prefix = let prefix =
match IO.options#input with match IO.options#input with
None | Some "-" -> "temp" None | Some "-" -> "temp"
| Some file -> Filename.(file |> basename |> remove_extension) | Some file -> Filename.(file |> basename |> remove_extension)
let suffix = ".pp" ^ IO.ext let suffix = ".pp" ^ IO.ext
let pp_input = let pp_input =
if Utils.String.Set.mem "cpp" IO.options#verbose if SSet.mem "cpp" IO.options#verbose
then prefix ^ suffix then prefix ^ suffix
else let pp_input, pp_out = Filename.open_temp_file prefix suffix else let pp_input, pp_out =
Filename.open_temp_file prefix suffix
in close_out pp_out; pp_input in close_out pp_out; pp_input
let cpp_cmd = let cpp_cmd =
@ -76,100 +74,161 @@ module Make (IO: S)
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 () = (* Error handling (reexported from [ParserAPI]) *)
if Utils.String.Set.mem "cpp" IO.options#verbose
then eprintf "%s\n%!" cpp_cmd; type message = string
type valid = Parser.token
type invalid = Parser.token
type error = message * valid option * invalid
exception Point of error
(* Instantiating the parser *)
module Front = ParserAPI.Make (Lexer)(Parser)(ParErr)
let format_error = Front.format_error
let short_error ?(offsets=true) mode msg (reg: Region.t) =
sprintf "Parse error %s:\n%s" (reg#to_string ~offsets mode) msg
(* Parsing an expression *)
let parse_expr lexer_inst tokeniser output state :
(AST.expr, string) Stdlib.result =
let close_all () =
lexer_inst.Lexer.close (); close_out stdout in
let lexbuf = lexer_inst.Lexer.buffer in
let expr =
try
if IO.options#mono then
Front.mono_expr tokeniser lexbuf
else
Front.incr_expr lexer_inst
with exn -> close_all (); raise exn in
let () =
if SSet.mem "ast-tokens" IO.options#verbose then
begin
Buffer.clear output;
ParserLog.print_expr state expr;
Buffer.output_buffer stdout output
end in
let () =
if SSet.mem "ast" IO.options#verbose then
begin
Buffer.clear output;
ParserLog.pp_expr state expr;
Buffer.output_buffer stdout output
end
in close_all (); Ok expr
(* Parsing a contract *)
let parse_contract lexer_inst tokeniser output state
: (AST.t, string) Stdlib.result =
let close_all () =
lexer_inst.Lexer.close (); close_out stdout in
let lexbuf = lexer_inst.Lexer.buffer in
let ast =
try
if IO.options#mono then
Front.mono_contract tokeniser lexbuf
else
Front.incr_contract lexer_inst
with exn -> close_all (); raise exn in
let () =
if SSet.mem "ast-tokens" IO.options#verbose then
begin
Buffer.clear output;
ParserLog.print_tokens state ast;
Buffer.output_buffer stdout output
end in
let () =
if SSet.mem "ast" IO.options#verbose then
begin
Buffer.clear output;
ParserLog.pp_ast state ast;
Buffer.output_buffer stdout output
end
in close_all (); Ok ast
(* Wrapper for the parsers above *)
let parse parser =
(* Preprocessing the input *)
if SSet.mem "cpp" IO.options#verbose
then eprintf "%s\n%!" cpp_cmd
else ();
if Sys.command cpp_cmd <> 0 then if Sys.command cpp_cmd <> 0 then
external_ (sprintf "the command \"%s\" failed." cpp_cmd) let msg =
sprintf "External error: \"%s\" failed." cpp_cmd
in Stdlib.Error msg
else
(* Instantiating the lexer *)
(* Instanciating the lexer *) let lexer_inst = Lexer.open_token_stream (Some pp_input) in
module ParserFront = ParserAPI.Make (Lexer) (Parser) (ParErr) (* Making the tokeniser *)
let format_error = ParserFront.format_error let module Log = LexerLog.Make (Lexer) in
let short_error = ParserFront.short_error
let lexer_inst = Lexer.open_token_stream (Some pp_input) let log =
let Lexer.{read; buffer; get_win; get_pos; get_last; close} = lexer_inst Log.output_token ~offsets:IO.options#offsets
IO.options#mode IO.options#cmd stdout in
and cout = stdout let tokeniser = lexer_inst.Lexer.read ~log in
let close_all () = close (); close_out cout let output = Buffer.create 131 in
let state = ParserLog.mk_state
~offsets:IO.options#offsets
~mode:IO.options#mode
~buffer:output in
(* Tokeniser *) (* Calling the specific parser (that is, the parameter) *)
module Log = LexerLog.Make (Lexer) match parser lexer_inst tokeniser output state with
Stdlib.Error _ as error -> error
| Stdlib.Ok _ as node -> node
let log = Log.output_token ~offsets:IO.options#offsets
IO.options#mode IO.options#cmd cout
let tokeniser = read ~log
(* Main *)
let run () =
try
let ast =
if IO.options#mono
then ParserFront.mono_contract tokeniser buffer
else ParserFront.incr_contract lexer_inst in
if Utils.String.Set.mem "ast" IO.options#verbose
then let buffer = Buffer.create 131 in
let state = ParserLog.mk_state
~offsets:IO.options#offsets
~mode:IO.options#mode
~buffer in
begin
ParserLog.pp_ast state ast;
Buffer.output_buffer stdout buffer
end
else if Utils.String.Set.mem "ast-tokens" IO.options#verbose
then let buffer = Buffer.create 131 in
let state = ParserLog.mk_state
~offsets:IO.options#offsets
~mode:IO.options#mode
~buffer in
begin
ParserLog.print_tokens state ast;
Buffer.output_buffer stdout buffer
end
with
(* Lexing errors *) (* Lexing errors *)
Lexer.Error err -> | exception Lexer.Error err ->
close_all (); let file =
let msg = match IO.options#input with
Lexer.format_error ~offsets:IO.options#offsets None | Some "-" -> false
IO.options#mode err ~file | Some _ -> true in
in prerr_string msg let error =
Lexer.format_error ~offsets:IO.options#offsets
IO.options#mode err ~file
in Stdlib.Error error
(* Incremental API of Menhir *) (* Incremental API of Menhir *)
| ParserFront.Point point -> | exception Front.Point point ->
let () = close_all () in let error =
let error = Front.format_error ~offsets:IO.options#offsets
ParserFront.format_error ~offsets:IO.options#offsets IO.options#mode point
IO.options#mode point in Stdlib.Error error
in eprintf "\027[31m%s\027[0m%!" error
(* Monolithic API of Menhir *) (* Monolithic API of Menhir *)
| Parser.Error -> | exception Parser.Error ->
let () = close_all () in let invalid, valid_opt =
let invalid, valid_opt = match lexer_inst.Lexer.get_win () with
match get_win () with Lexer.Nil ->
Lexer.Nil -> assert false (* Safe: There is always at least EOF. *)
assert false (* Safe: There is always at least EOF. *) | Lexer.One invalid -> invalid, None
| Lexer.One invalid -> invalid, None | Lexer.Two (invalid, valid) -> invalid, Some valid in
| Lexer.Two (invalid, valid) -> invalid, Some valid in let point = "", valid_opt, invalid in
let point = "", valid_opt, invalid in let error =
let error = Front.format_error ~offsets:IO.options#offsets
ParserFront.format_error ~offsets:IO.options#offsets IO.options#mode point
IO.options#mode point in Stdlib.Error error
in eprintf "\027[31m%s\027[0m%!" error
(* I/O errors *) (* I/O errors *)
| Sys_error msg -> Utils.highlight msg | exception Sys_error error -> Stdlib.Error error
end end

View File

@ -0,0 +1,71 @@
(* Functor to build a standalone LIGO parser *)
module Region = Simple_utils.Region
module type IO =
sig
val ext : string (* LIGO file extension *)
val options : EvalOpt.options (* CLI options *)
end
module type Pretty =
sig
type state
type ast
type expr
val mk_state :
offsets:bool -> mode:[`Point|`Byte] -> buffer:Buffer.t -> state
val pp_ast : state -> ast -> unit
val pp_expr : state -> expr -> unit
val print_tokens : state -> ast -> unit
val print_expr : state -> expr -> unit
end
module Make (Lexer: Lexer.S)
(AST: sig type t type expr end)
(Parser: ParserAPI.PARSER
with type ast = AST.t
and type expr = AST.expr
and type token = Lexer.token)
(ParErr: sig val message : int -> string end)
(ParserLog: Pretty with type ast = AST.t
and type expr = AST.expr)
(IO: IO) :
sig
(* Error handling (reexported from [ParserAPI]) *)
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
val short_error :
?offsets:bool -> [`Point | `Byte] -> string -> Region.t -> string
(* Parsers *)
val parse :
(Lexer.instance ->
(Lexing.lexbuf -> Lexer.token) ->
Buffer.t -> ParserLog.state -> ('a, string) result) ->
('a, string) result
val parse_contract :
Lexer.instance ->
(Lexing.lexbuf -> Lexer.token) ->
Buffer.t -> ParserLog.state ->
(AST.t, string) Stdlib.result
val parse_expr :
Lexer.instance ->
(Lexing.lexbuf -> Lexer.token) ->
Buffer.t -> ParserLog.state -> (AST.expr, string) Stdlib.result
end

View File

@ -12,8 +12,5 @@
(preprocess (preprocess
(pps (pps
ppx_let ppx_let
bisect_ppx --conditional bisect_ppx --conditional))
) (flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils)))
)
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Simple_utils ))
)

View File

@ -4,14 +4,15 @@ open Ast_simplified
module Raw = Parser.Pascaligo.AST module Raw = Parser.Pascaligo.AST
module SMap = Map.String module SMap = Map.String
module SSet = Set.Make (String) module SSet = Set.Make (String)
module ParserLog = Parser_pascaligo.ParserLog
open Combinators open Combinators
let nseq_to_list (hd, tl) = hd :: tl let nseq_to_list (hd, tl) = hd :: tl
let npseq_to_list (hd, tl) = hd :: (List.map snd tl) let npseq_to_list (hd, tl) = hd :: (List.map snd tl)
let pseq_to_list = function let pseq_to_list = function
| None -> [] None -> []
| Some lst -> npseq_to_list lst | Some lst -> npseq_to_list lst
let get_value : 'a Raw.reg -> 'a = fun x -> x.value let get_value : 'a Raw.reg -> 'a = fun x -> x.value
let is_compiler_generated name = String.contains (Var.to_name name) '#' let is_compiler_generated name = String.contains (Var.to_name name) '#'
@ -132,7 +133,7 @@ module Errors = struct
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc) ; fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc) ;
(** TODO: The labelled arguments should be flowing from the CLI. *) (** TODO: The labelled arguments should be flowing from the CLI. *)
("pattern", ("pattern",
fun () -> Parser.Pascaligo.ParserLog.pattern_to_string fun () -> ParserLog.pattern_to_string
~offsets:true ~mode:`Point p) ~offsets:true ~mode:`Point p)
] in ] in
error ~data title message error ~data title message
@ -168,7 +169,7 @@ module Errors = struct
(** TODO: The labelled arguments should be flowing from the CLI. *) (** TODO: The labelled arguments should be flowing from the CLI. *)
let data = [ let data = [
("instruction", ("instruction",
fun () -> Parser.Pascaligo.ParserLog.instruction_to_string fun () -> ParserLog.instruction_to_string
~offsets:true ~mode:`Point t) ~offsets:true ~mode:`Point t)
] in ] in
error ~data title message error ~data title message
@ -562,31 +563,43 @@ and simpl_tuple_expression ?loc (lst:Raw.expr list) : expression result =
| [] -> return @@ e_literal Literal_unit | [] -> return @@ e_literal Literal_unit
| [hd] -> simpl_expression hd | [hd] -> simpl_expression hd
| lst -> | lst ->
let%bind lst = bind_list @@ List.map simpl_expression lst in let%bind lst = bind_list @@ List.map simpl_expression lst
return @@ e_tuple ?loc lst in return @@ e_tuple ?loc lst
and simpl_data_declaration : Raw.data_decl -> _ result = fun t -> and simpl_data_declaration : Raw.data_decl -> _ result =
fun t ->
match t with match t with
| LocalVar x -> | LocalVar x ->
let (x , loc) = r_split x in let (x , loc) = r_split x in
let name = x.name.value in let name = x.name.value in
let%bind t = simpl_type_expression x.var_type in let%bind t = simpl_type_expression x.var_type in
let%bind expression = simpl_expression x.init in let%bind expression = simpl_expression x.init in
return_let_in ~loc (Var.of_name name , Some t) false expression return_let_in ~loc (Var.of_name name, Some t) false expression
| LocalConst x -> | LocalConst x ->
let (x , loc) = r_split x in let (x , loc) = r_split x in
let name = x.name.value in let name = x.name.value in
let%bind t = simpl_type_expression x.const_type in let%bind t = simpl_type_expression x.const_type in
let%bind expression = simpl_expression x.init in let%bind expression = simpl_expression x.init in
let inline = List.exists (fun (f: Raw.attribute) -> f.value = "\"inline\"") x.attributes.value in let inline =
return_let_in ~loc (Var.of_name name , Some t) inline expression match x.attributes with
None -> false
| Some {value; _} ->
npseq_to_list value.ne_elements
|> List.exists (fun Region.{value; _} -> value = "\"inline\"")
in return_let_in ~loc (Var.of_name name, Some t) inline expression
| LocalFun f -> | LocalFun f ->
let (f , loc) = r_split f in let (f , loc) = r_split f in
let%bind (binder, expr) = simpl_fun_decl ~loc f in let%bind (binder, expr) = simpl_fun_decl ~loc f in
let inline = List.exists (fun (f: Raw.attribute) -> f.value = "\"inline\"") f.attributes.value in let inline =
return_let_in ~loc binder inline expr match f.attributes with
None -> false
| Some {value; _} ->
npseq_to_list value.ne_elements
|> List.exists (fun Region.{value; _} -> value = "\"inline\"")
in return_let_in ~loc binder inline expr
and simpl_param : Raw.param_decl -> (expression_variable * type_expression) result = and simpl_param :
Raw.param_decl -> (expression_variable * type_expression) result =
fun t -> fun t ->
match t with match t with
| ParamConst c -> | ParamConst c ->
@ -601,11 +614,18 @@ and simpl_param : Raw.param_decl -> (expression_variable * type_expression) resu
ok (type_name , type_expression) ok (type_name , type_expression)
and simpl_fun_decl : and simpl_fun_decl :
loc:_ -> Raw.fun_decl -> ((expression_variable * type_expression option) * expression) result = loc:_ -> Raw.fun_decl ->
((expression_variable * type_expression option) * expression) result =
fun ~loc x -> fun ~loc x ->
let open! Raw in let open! Raw in
let {fun_name;param;ret_type;block_with;return; attributes} : fun_decl = x in let {fun_name; param; ret_type; block_with;
let inline = List.exists (fun (a: Raw.attribute) -> a.value = "\"inline\"") attributes.value in return; attributes} : fun_decl = x in
let inline =
match attributes with
None -> false
| Some {value; _} ->
npseq_to_list value.ne_elements
|> List.exists (fun Region.{value; _} -> value = "\"inline\"") in
let statements = let statements =
match block_with with match block_with with
| Some (block,_) -> npseq_to_list block.value.statements | Some (block,_) -> npseq_to_list block.value.statements
@ -615,9 +635,7 @@ and simpl_fun_decl :
a, [] -> ( a, [] -> (
let%bind input = simpl_param a in let%bind input = simpl_param a in
let (binder , input_type) = input in let (binder , input_type) = input in
let%bind instructions = bind_list let%bind instructions = simpl_statement_list statements in
@@ List.map simpl_statement
@@ statements in
let%bind result = simpl_expression return in let%bind result = simpl_expression return in
let%bind output_type = simpl_type_expression ret_type in let%bind output_type = simpl_type_expression ret_type in
let body = instructions in let body = instructions in
@ -647,9 +665,7 @@ and simpl_fun_decl :
ass ass
in in
bind_list @@ List.mapi aux params in bind_list @@ List.mapi aux params in
let%bind instructions = bind_list let%bind instructions = simpl_statement_list statements in
@@ List.map simpl_statement
@@ statements in
let%bind result = simpl_expression return in let%bind result = simpl_expression return in
let%bind output_type = simpl_type_expression ret_type in let%bind output_type = simpl_type_expression ret_type in
let body = tpl_declarations @ instructions in let body = tpl_declarations @ instructions in
@ -673,9 +689,7 @@ and simpl_fun_expression :
a, [] -> ( a, [] -> (
let%bind input = simpl_param a in let%bind input = simpl_param a in
let (binder , input_type) = input in let (binder , input_type) = input in
let%bind instructions = bind_list let%bind instructions = simpl_statement_list statements in
@@ List.map simpl_statement
@@ statements in
let%bind result = simpl_expression return in let%bind result = simpl_expression return in
let%bind output_type = simpl_type_expression ret_type in let%bind output_type = simpl_type_expression ret_type in
let body = instructions in let body = instructions in
@ -705,9 +719,7 @@ and simpl_fun_expression :
ass ass
in in
bind_list @@ List.mapi aux params in bind_list @@ List.mapi aux params in
let%bind instructions = bind_list let%bind instructions = simpl_statement_list statements in
@@ List.map simpl_statement
@@ statements in
let%bind result = simpl_expression return in let%bind result = simpl_expression return in
let%bind output_type = simpl_type_expression ret_type in let%bind output_type = simpl_type_expression ret_type in
let body = tpl_declarations @ instructions in let body = tpl_declarations @ instructions in
@ -721,44 +733,39 @@ and simpl_fun_expression :
) )
) )
and simpl_declaration : Raw.declaration -> declaration Location.wrap result = and simpl_statement_list statements =
fun t -> let open Raw in
let open! Raw in let rec hook acc = function
match t with [] -> acc
| TypeDecl x -> | [Attr _] ->
let decl, loc = r_split x in (* Detached attributes are erased. TODO: Warning. *)
let {name;type_expr} : Raw.type_decl = decl in acc
let%bind type_expression = simpl_type_expression type_expr in | Attr _ :: (Attr _ :: _ as statements) ->
ok @@ Location.wrap ~loc (Declaration_type (* Detached attributes are erased. TODO: Warning. *)
(Var.of_name name.value, type_expression)) hook acc statements
| Attr decl :: Data (LocalConst {value; region}) :: statements ->
| ConstDecl x -> let new_const =
let simpl_const_decl = fun {name;const_type; init; attributes} -> Data (LocalConst {value = {value with attributes = Some decl}; region})
let%bind expression = simpl_expression init in in hook acc (new_const :: statements)
let%bind t = simpl_type_expression const_type in | Attr decl :: Data (LocalFun {value; region}) :: statements ->
let type_annotation = Some t in let new_fun =
let inline = List.exists (fun (a: Raw.attribute) -> a.value = "\"inline\"") attributes.value in Data (LocalFun {value = {value with attributes = Some decl}; region})
ok @@ Declaration_constant in hook acc (new_fun :: statements)
(Var.of_name name.value, type_annotation, inline, expression) | Attr _ :: statements ->
in bind_map_location simpl_const_decl (Location.lift_region x) (* Detached attributes are erased. TODO: Warning. *)
| FunDecl x -> hook acc statements
let decl, loc = r_split x in | Instr i :: statements ->
let%bind ((name, ty_opt), expr) = simpl_fun_decl ~loc decl in hook (simpl_instruction i :: acc) statements
let inline = List.exists (fun (a: Raw.attribute) -> a.value = "\"inline\"") x.value.attributes.value in | Data d :: statements ->
ok @@ Location.wrap ~loc (Declaration_constant (name, ty_opt, inline, expr)) hook (simpl_data_declaration d :: acc) statements
in bind_list @@ hook [] (List.rev statements)
and simpl_statement : Raw.statement -> (_ -> expression result) result =
fun s ->
match s with
| Instr i -> simpl_instruction i
| Data d -> simpl_data_declaration d
and simpl_single_instruction : Raw.instruction -> (_ -> expression result) result = and simpl_single_instruction : Raw.instruction -> (_ -> expression result) result =
fun t -> fun t ->
match t with match t with
| ProcCall x -> ( | ProcCall x -> (
let ((f, args) , loc) = r_split x in let (f, args) , loc = r_split x in
let (args , args_loc) = r_split args in let args, args_loc = r_split args in
let args' = npseq_to_list args.inside in let args' = npseq_to_list args.inside in
match f with match f with
| EVar name -> ( | EVar name -> (
@ -1057,10 +1064,10 @@ and simpl_cases : type a . (Raw.pattern * a) list -> (a, unit) matching result =
let aux (x , y) = let aux (x , y) =
let error = let error =
let title () = "Pattern" in let title () = "Pattern" in
(** TODO: The labelled arguments should be flowing from the CLI. *) (* TODO: The labelled arguments should be flowing from the CLI. *)
let content () = let content () =
Printf.sprintf "Pattern : %s" Printf.sprintf "Pattern : %s"
(Parser.Pascaligo.ParserLog.pattern_to_string (ParserLog.pattern_to_string
~offsets:true ~mode:`Point x) in ~offsets:true ~mode:`Point x) in
error title content in error title content in
let%bind x' = let%bind x' =
@ -1071,23 +1078,22 @@ and simpl_cases : type a . (Raw.pattern * a) list -> (a, unit) matching result =
ok @@ ez_match_variant constrs ok @@ ez_match_variant constrs
and simpl_instruction : Raw.instruction -> (_ -> expression result) result = and simpl_instruction : Raw.instruction -> (_ -> expression result) result =
fun t -> fun t -> trace (simplifying_instruction t) @@ simpl_single_instruction t
trace (simplifying_instruction t) @@ simpl_single_instruction t
and simpl_statements : Raw.statements -> (_ -> expression result) result = and simpl_statements : Raw.statements -> (_ -> expression result) result =
fun ss -> fun statements ->
let lst = npseq_to_list ss in let lst = npseq_to_list statements in
let%bind fs = bind_map_list simpl_statement lst in let%bind fs = simpl_statement_list lst in
let aux : _ -> (expression option -> expression result) -> _ = let aux : _ -> (expression option -> expression result) -> _ =
fun prec cur -> fun prec cur ->
let%bind res = cur prec in let%bind res = cur prec
ok @@ Some res in in ok @@ Some res in
ok @@ fun (expr' : _ option) -> ok @@ fun (expr' : _ option) ->
let%bind ret = bind_fold_right_list aux expr' fs in let%bind ret = bind_fold_right_list aux expr' fs in
ok @@ Option.unopt_exn ret ok @@ Option.unopt_exn ret
and simpl_block : Raw.block -> (_ -> expression result) result = fun t -> and simpl_block : Raw.block -> (_ -> expression result) result =
simpl_statements t.statements fun t -> simpl_statements t.statements
and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi -> and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
(* cond part *) (* cond part *)
@ -1263,11 +1269,13 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun
(* STEP 5 *) (* STEP 5 *)
let rec add_return (expr : expression) = match expr.expression with let rec add_return (expr : expression) = match expr.expression with
| E_sequence (a,b) -> e_sequence a (add_return b) | E_sequence (a,b) -> e_sequence a (add_return b)
| _ -> e_sequence expr (e_variable (Var.of_name "#COMPILER#acc")) in (* TODO fresh *) | _ -> (* TODO fresh *)
e_sequence expr (e_variable (Var.of_name "#COMPILER#acc")) in
let for_body = add_return for_body in let for_body = add_return for_body in
(* STEP 6 *) (* STEP 6 *)
let for_body = let for_body =
let ( arg_access: Types.access_path -> expression ) = e_accessor (e_variable (Var.of_name "arguments")) in (* TODO fresh *) let ( arg_access: Types.access_path -> expression ) =
e_accessor (e_variable (Var.of_name "arguments")) in (* TODO fresh *)
( match fc.collection with ( match fc.collection with
| Map _ -> | Map _ ->
let acc = arg_access [Access_tuple 0 ] in let acc = arg_access [Access_tuple 0 ] in
@ -1290,7 +1298,8 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun
let fold = e_constant op_name [lambda; collect ; init_record] in let fold = e_constant op_name [lambda; collect ; init_record] in
(* STEP 8 *) (* STEP 8 *)
let assign_back (prev : expression option) (captured_varname : string) : expression option = let assign_back (prev : expression option) (captured_varname : string) : expression option =
let access = e_accessor (e_variable (Var.of_name "#COMPILER#folded_record")) (* TODO fresh *) let access = (* TODO fresh *)
e_accessor (e_variable (Var.of_name "#COMPILER#folded_record"))
[Access_record captured_varname] in [Access_record captured_varname] in
let assign = e_assign captured_varname [] access in let assign = e_assign captured_varname [] access in
match prev with match prev with
@ -1303,6 +1312,74 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun
| None -> e_skip () | None -> e_skip ()
| Some seq -> e_let_in (Var.of_name "#COMPILER#folded_record", None) false fold seq in (* TODO fresh *) | Some seq -> e_let_in (Var.of_name "#COMPILER#folded_record", None) false fold seq in (* TODO fresh *)
return_statement @@ final_sequence return_statement @@ final_sequence
(*
and simpl_declaration : Raw.declaration -> declaration Location.wrap result =
*)
let simpl_program : Raw.ast -> program result = fun t -> and simpl_declaration_list declarations :
bind_list @@ List.map simpl_declaration @@ nseq_to_list t.decl Ast_simplified.declaration Location.wrap list result =
let open Raw in
let rec hook acc = function
[] -> acc
| [AttrDecl _] ->
(* Detached attributes are erased. TODO: Warning. *)
acc
| AttrDecl _ :: (AttrDecl _ :: _ as declarations) ->
(* Detached attributes are erased. TODO: Warning. *)
hook acc declarations
| AttrDecl decl :: ConstDecl {value; region} :: declarations ->
let new_const =
ConstDecl {value = {value with attributes = Some decl}; region}
in hook acc (new_const :: declarations)
| AttrDecl decl :: FunDecl {value; region} :: declarations ->
let new_fun =
FunDecl {value = {value with attributes = Some decl}; region}
in hook acc (new_fun :: declarations)
| AttrDecl _ :: declarations ->
(* Detached attributes are erased. TODO: Warning. *)
hook acc declarations
| TypeDecl decl :: declarations ->
let decl, loc = r_split decl in
let {name; type_expr} : Raw.type_decl = decl in
let%bind type_expression = simpl_type_expression type_expr in
let new_decl =
Declaration_type (Var.of_name name.value, type_expression) in
let res = Location.wrap ~loc new_decl in
hook (bind_list_cons res acc) declarations
| ConstDecl decl :: declarations ->
let simpl_const_decl =
fun {name;const_type; init; attributes} ->
let%bind expression = simpl_expression init in
let%bind t = simpl_type_expression const_type in
let type_annotation = Some t in
let inline =
match attributes with
None -> false
| Some {value; _} ->
npseq_to_list value.ne_elements
|> List.exists (fun Region.{value; _} -> value = "\"inline\"") in
let new_decl =
Declaration_constant
(Var.of_name name.value, type_annotation, inline, expression)
in ok new_decl in
let%bind res =
bind_map_location simpl_const_decl (Location.lift_region decl)
in hook (bind_list_cons res acc) declarations
| FunDecl fun_decl :: declarations ->
let decl, loc = r_split fun_decl in
let%bind ((name, ty_opt), expr) = simpl_fun_decl ~loc decl in
let inline =
match fun_decl.value.attributes with
None -> false
| Some {value; _} ->
npseq_to_list value.ne_elements
|> List.exists (fun Region.{value; _} -> value = "\"inline\"") in
let new_decl =
Declaration_constant (name, ty_opt, inline, expr) in
let res = Location.wrap ~loc new_decl in
hook (bind_list_cons res acc) declarations
in
hook (ok @@ []) (List.rev declarations)
let simpl_program : Raw.ast -> program result =
fun t -> simpl_declaration_list @@ nseq_to_list t.decl

View File

@ -1,17 +1,19 @@
const x: int = 1; attributes ["inline"]; const x : int = 1; attributes ["inline"]
function foo (const a : int) : int is function foo (const a : int) : int is
block { begin
const test: int = 2 + a; attributes ["inline"]; const test : int = 2 + a;
} with test; attributes ["inline"];
end with test;
attributes ["inline"]; attributes ["inline"];
const y: int = 1; attributes ["inline"; "other"]; const y : int = 1; attributes ["inline"; "other"]
function bar (const b : int) : int is function bar (const b : int) : int is
block { begin
function test (const z : int) : int is begin function test (const z : int) : int is
const r : int = 2 + b + z begin
end with r; const r : int = 2 + b + z
attributes ["inline"; "foo"; "bar"]; end with r;
} with test(b); attributes ["inline"; "foo"; "bar"]
end with test(b)

View File

@ -1,13 +1,10 @@
let x = 1 [@@inline] let x = 1 [@@inline]
let foo (a: int): int = ( let foo (a: int): int =
let test = 2 + a [@@inline] in (let test = 2 + a [@@inline] in test) [@@inline]
test
) [@@inline]
let y = 1 [@@inline][@@other] let y = 1 [@@inline][@@other]
let bar (b: int): int = ( let bar (b: int): int =
let test = fun (z: int) -> 2 + b + z [@@inline][@@foo][@@bar] in let test = fun (z: int) -> 2 + b + z [@@inline][@@foo][@@bar]
test b in test b
)

View File

@ -25,8 +25,8 @@
(action (run ./parser_negative_tests.exe)) (action (run ./parser_negative_tests.exe))
(deps (deps
../passes/1-parser/pascaligo/all.ligo ../passes/1-parser/pascaligo/all.ligo
../passes/1-parser/cameligo/all.ligo ../passes/1-parser/cameligo/all.mligo
../passes/1-parser/reasonligo/all.ligo ../passes/1-parser/reasonligo/all.religo
)) ))
(alias (alias

View File

@ -1 +1 @@
let args = 1; let arguments = 1;

View File

@ -6,10 +6,10 @@ let pascaligo_sdata = {
erroneous_source_file = "../passes/1-parser/pascaligo/all.ligo" ; erroneous_source_file = "../passes/1-parser/pascaligo/all.ligo" ;
parser = Parser.Pascaligo.parse_expression } parser = Parser.Pascaligo.parse_expression }
let cameligo_sdata = { let cameligo_sdata = {
erroneous_source_file = "../passes/1-parser/cameligo/all.ligo" ; erroneous_source_file = "../passes/1-parser/cameligo/all.mligo" ;
parser = Parser.Cameligo.parse_expression } parser = Parser.Cameligo.parse_expression }
let reasonligo_sdata = { let reasonligo_sdata = {
erroneous_source_file = "../passes/1-parser/reasonligo/all.ligo" ; erroneous_source_file = "../passes/1-parser/reasonligo/all.religo" ;
parser = Parser.Reasonligo.parse_expression } parser = Parser.Reasonligo.parse_expression }
let get_exp_as_string filename = let get_exp_as_string filename =

View File

@ -23,9 +23,10 @@ type t = <
is_ghost : bool; is_ghost : bool;
to_string : ?offsets:bool -> [`Byte | `Point] -> string; to_string :
compact : ?offsets:bool -> [`Byte | `Point] -> string; ?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string;
anonymous : ?offsets:bool -> [`Byte | `Point] -> string compact :
?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string;
> >
type pos = t type pos = t
@ -61,8 +62,6 @@ let make ~byte ~point_num ~point_bol =
let pos = pos#set_offset offset let pos = pos#set_offset offset
in pos in pos
(* The string must not contain '\n'. See [new_line]. *)
method shift_bytes len = method shift_bytes len =
{< byte = Lexing.{byte with pos_cnum = byte.pos_cnum + len}; {< byte = Lexing.{byte with pos_cnum = byte.pos_cnum + len};
point_num = point_num + len >} point_num = point_num + len >}
@ -77,11 +76,13 @@ let make ~byte ~point_num ~point_bol =
pos_bol = byte.pos_cnum}; pos_bol = byte.pos_cnum};
point_bol = point_num >} point_bol = point_num >}
(* The string must not contain '\n'. See [add_line]. *)
method new_line string = method new_line string =
let len = String.length string let len = String.length string
in (self#shift_bytes len)#add_nl in (self#shift_bytes len)#add_nl
method is_ghost = byte = Lexing.dummy_pos method is_ghost = (byte = Lexing.dummy_pos)
method file = byte.Lexing.pos_fname method file = byte.Lexing.pos_fname
@ -99,24 +100,30 @@ let make ~byte ~point_num ~point_bol =
method byte_offset = byte.Lexing.pos_cnum method byte_offset = byte.Lexing.pos_cnum
method to_string ?(offsets=true) mode = method to_string ?(file=true) ?(offsets=true) mode =
let offset = self#offset mode in
let horizontal, value =
if offsets then "character", offset else "column", offset + 1
in sprintf "File \"%s\", line %i, %s %i"
self#file self#line horizontal value
method compact ?(offsets=true) mode =
if self#is_ghost then "ghost" if self#is_ghost then "ghost"
else else
let offset = self#offset mode in let offset = self#offset mode in
sprintf "%s:%i:%i" let horizontal, value =
self#file self#line (if offsets then offset else offset + 1) if offsets then
"character", offset
else "column", offset + 1 in
if file && self#file <> "" then
sprintf "File \"%s\", line %i, %s %i"
self#file self#line horizontal value
else sprintf "Line %i, %s %i"
self#line horizontal value
method anonymous ?(offsets=true) mode = method compact ?(file=true) ?(offsets=true) mode =
if self#is_ghost then "ghost" if self#is_ghost then "ghost"
else sprintf "%i:%i" self#line else
(if offsets then self#offset mode else self#column mode) let horizontal =
if offsets then self#offset mode
else self#column mode in
if file && self#file <> "" then
sprintf "%s:%i:%i" self#file self#line horizontal
else
sprintf "%i:%i" self#line horizontal
end end
let from_byte byte = let from_byte byte =
@ -126,7 +133,9 @@ let from_byte byte =
let ghost = make ~byte:Lexing.dummy_pos ~point_num:(-1) ~point_bol:(-1) let ghost = make ~byte:Lexing.dummy_pos ~point_num:(-1) ~point_bol:(-1)
let min = make ~byte:Lexing.dummy_pos ~point_num:0 ~point_bol:0 let min ~file =
let pos = make ~byte:Lexing.dummy_pos ~point_num:0 ~point_bol:0
in pos#set_file file
(* Comparisons *) (* Comparisons *)

View File

@ -62,19 +62,20 @@ type t = <
(* Payload *) (* Payload *)
byte : Lexing.position; byte : Lexing.position;
point_num : int; point_num : int; (* point_num >= point_bol *)
point_bol : int; point_bol : int; (* point_bol >= 0 *)
file : string; file : string; (* May be empty *)
line : int; line : int; (* line > 0 *)
(* Setters *) (* Setters *)
set_file : string -> t; set_file : string -> t;
set_line : int -> t; set_line : int -> t;
set_offset : int -> t; set_offset : int -> t;
set : file:string -> line:int -> offset:int -> t;
new_line : string -> t; set : file:string -> line:int -> offset:int -> t;
new_line : string -> t; (* String must be "\n" or "\c\r" *)
add_nl : t; add_nl : t;
shift_bytes : int -> t; shift_bytes : int -> t;
@ -93,9 +94,10 @@ type t = <
(* Conversions to [string] *) (* Conversions to [string] *)
to_string : ?offsets:bool -> [`Byte | `Point] -> string; to_string :
compact : ?offsets:bool -> [`Byte | `Point] -> string; ?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string;
anonymous : ?offsets:bool -> [`Byte | `Point] -> string compact :
?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string;
> >
(** A shorthand after an [open Pos]. (** A shorthand after an [open Pos].
@ -104,18 +106,20 @@ type pos = t
(** {1 Constructors} *) (** {1 Constructors} *)
val make : byte:Lexing.position -> point_num:int -> point_bol:int -> t val make :
byte:Lexing.position -> point_num:int -> point_bol:int -> t
val from_byte : Lexing.position -> t val from_byte : Lexing.position -> t
(** {1 Special positions} *) (** {1 Special positions} *)
(** The value [ghost] is the same as {! Lexing.dummy_pos}. (** The value [ghost] based on the same as {! Lexing.dummy_pos}.
*) *)
val ghost : t val ghost : t
(** Lexing convention: line [1], offsets to [0] and file to [""]. (** Lexing convention: line [1], offset to [0].
*) *)
val min : t val min : file:string -> t
(** {1 Comparisons} *) (** {1 Comparisons} *)

View File

@ -101,8 +101,8 @@ let make ~(start: Pos.t) ~(stop: Pos.t) =
if start#is_ghost || stop#is_ghost then "ghost" if start#is_ghost || stop#is_ghost then "ghost"
else else
let prefix = if file then start#file ^ ":" else "" let prefix = if file then start#file ^ ":" else ""
and start_str = start#anonymous ~offsets mode and start_str = start#compact ~file:false ~offsets mode
and stop_str = stop#anonymous ~offsets mode in and stop_str = stop#compact ~file:false ~offsets mode in
if start#file = stop#file then if start#file = stop#file then
if start#line = stop#line then if start#line = stop#line then
sprintf "%s%s-%i" prefix start_str sprintf "%s%s-%i" prefix start_str
@ -120,7 +120,7 @@ let ghost = make ~start:Pos.ghost ~stop:Pos.ghost
let wrap_ghost value = {value ; region = ghost} let wrap_ghost value = {value ; region = ghost}
let min = make ~start:Pos.min ~stop:Pos.min let min ~file = make ~start:(Pos.min ~file) ~stop:(Pos.min ~file)
(* Comparisons *) (* Comparisons *)

View File

@ -54,7 +54,7 @@
{li The method [compact] has the same signature as and calling {li The method [compact] has the same signature as and calling
convention as [to_string], except that the resulting string convention as [to_string], except that the resulting string
is more compact.}} is shorter (usually for debugging or tracing).}}
*) *)
type t = < type t = <
start : Pos.t; start : Pos.t;
@ -86,9 +86,9 @@ type t = <
*) *)
type region = t type region = t
(** The type ['a reg] enables the concept of something of type ['a] to (** The type ['a reg] enables the concept of some value of type ['a] to
be related to a region in a source file. be related to a region in a source file.
*) *)
type 'a reg = {region: t; value: 'a} type 'a reg = {region: t; value: 'a}
(* {1 Constructors} *) (* {1 Constructors} *)
@ -119,7 +119,7 @@ val wrap_ghost : 'a -> 'a reg
(** Occasionnally, we may need a minimum region. It is here made of (** Occasionnally, we may need a minimum region. It is here made of
two minimal positions. two minimal positions.
*) *)
val min : t val min : file:string -> t
(** {1 Comparisons} *) (** {1 Comparisons} *)

View File

@ -1,4 +1,4 @@
(** Trace tutorial (* Trace tutorial
This module guides the reader through the writing of a simplified This module guides the reader through the writing of a simplified
version of the trace monad [result], and the definition of a few version of the trace monad [result], and the definition of a few
@ -6,53 +6,53 @@
*) *)
module Trace_tutorial = struct module Trace_tutorial = struct
(** The trace monad is fairly similar to the predefined [option] (* The trace monad is fairly similar to the predefined [option]
type. It is an instance of the predefined [result] type. *) type. It is an instance of the predefined [result] type. *)
type annotation = string type annotation = string
type error = string type error = string
(** The type ['a result] is used by the trace monad to both model an (* The type ['a result] is used by the trace monad to both model an
expected value of type ['a] or the failure to obtain it, instead expected value of type ['a] or the failure to obtain it, instead
of working directly with ['a] values and handling separately of working directly with ['a] values and handling separately
errors, for example by means of exceptions. (See the type [('a,'b) errors, for example by means of exceptions. (See the type [('a,'b)
result] in the module [Pervasives] of the OCaml system for a result] in the module [Pervasives] of the OCaml system for a
comparable approach to error handling.) comparable approach to error handling.)
The type ['a result] carries either a value of type ['a], with a
list of annotations (information about past successful
computations), or it is a list of errors accumulated so far.
The former case is denoted by the data constructor [Ok], and the
second by [Error]. *)
The type ['a result] carries either a value of type ['a], with a
list of annotations (information about past successful
computations), or it is a list of errors accumulated so far.
The former case is denoted by the data constructor [Ok], and the
second by [Error].
*)
type nonrec 'a result = ('a * annotation list, error list) result type nonrec 'a result = ('a * annotation list, error list) result
(* (*
= Ok of 'a * annotation list = Ok of 'a * annotation list
| Error of error list | Error of error list
*) *)
(** The function [divide_trace] shows the basic use of the trace (* The function [divide_trace] shows the basic use of the trace
monad. monad. *)
*)
let divide_trace a b = let divide_trace a b =
if b = 0 if b = 0
then Error [Printf.sprintf "division by zero: %d/%d" a b] then Error [Printf.sprintf "division by zero: %d/%d" a b]
else Ok (a/b, []) else Ok (a/b, [])
(** The function [divide_three] shows that when composing two (* The function [divide_three] shows that when composing two
functions, if the first call fails, the error is passed along functions, if the first call fails, the error is passed along
and the second call is not evaluated. (A pattern called and the second call is not evaluated. (A pattern called
"error-passing style"). "error-passing style"). *)
*)
let divide_three a b c = let divide_three a b c =
match divide_trace a b with match divide_trace a b with
Ok (a_div_b , _) -> divide_trace a_div_b c Ok (a_div_b , _) -> divide_trace a_div_b c
| errors -> errors | errors -> errors
(** The function [divide_three_annot] shows that when composing two (* The function [divide_three_annot] shows that when composing two
functions, if both calls are successful, the lists of functions, if both calls are successful, the lists of
annotations are joined. annotations are joined. *)
*)
let divide_three_annot a b c = let divide_three_annot a b c =
match divide_trace a b with match divide_trace a b with
Ok (a_div_b, annot1) -> ( Ok (a_div_b, annot1) -> (
@ -62,21 +62,19 @@ module Trace_tutorial = struct
| errors -> errors) | errors -> errors)
| errors -> errors | errors -> errors
(** The systematic matching of the result of each call in a function (* The systematic matching of the result of each call in a function
composition is bulky, so we define a [bind] function which takes composition is bulky, so we define a [bind] function which takes
a function [f: 'a -> 'b result] and applies it to a current ['a a function [f: 'a -> 'b result] and applies it to a current ['a
result] (not ['a]). result] (not ['a]).
{ul
{li If the current result is an error, then [bind]
returns that same error without calling [f];}
{li otherwise [bind] unwraps the [Ok] of the current result * If the current result is an error, then [bind]
and calls [f] on it: returns that same error without calling [f];
{ul
{li That call itself may return an error;} * otherwise [bind] unwraps the [Ok] of the current result
{li if not, [bind] combines the annotations and returns the last and calls [f] on it:
result.}}}} * That call itself may return an error;}
*) * if not, [bind] combines the annotations and returns the
last result. *)
let bind (f: 'a -> 'b result) : 'a result -> 'b result = let bind (f: 'a -> 'b result) : 'a result -> 'b result =
function function
Ok (x, annot) -> ( Ok (x, annot) -> (
@ -85,64 +83,64 @@ module Trace_tutorial = struct
| errors -> ignore annot; errors) | errors -> ignore annot; errors)
| Error _ as e -> e | Error _ as e -> e
(** The function [divide_three_bind] is equivalent to the verbose (* The function [divide_three_bind] is equivalent to the verbose
[divide_three] above, but makes use of [bind]. [divide_three] above, but makes use of [bind]. *)
*)
let divide_three_bind a b c = let divide_three_bind a b c =
let maybe_a_div_b = divide_trace a b in let maybe_a_div_b = divide_trace a b in
let continuation a_div_b = divide_trace a_div_b c let continuation a_div_b = divide_trace a_div_b c
in bind continuation maybe_a_div_b in bind continuation maybe_a_div_b
(** The operator [(>>?)] is a redefinition of [bind] that makes the (* The operator [(>>?)] is a redefinition of [bind] that makes the
program shorter, at the cost of a slightly program shorter, at the cost of a slightly
awkward reading because the two parameters are swapped. awkward reading because the two parameters are swapped. *)
*)
let (>>?) x f = bind f x let (>>?) x f = bind f x
(** The function [divide_three_bind_symbol] is equivalent to (* The function [divide_three_bind_symbol] is equivalent to
[divide_three_bind], but makes use of the operator [(>>?)]. [divide_three_bind], but makes use of the operator [(>>?)]. *)
*)
let divide_three_bind_symbol a b c = let divide_three_bind_symbol a b c =
let maybe_a_div_b = divide_trace a b in let maybe_a_div_b = divide_trace a b in
let continuation a_div_b = divide_trace a_div_b c in let continuation a_div_b = divide_trace a_div_b c in
maybe_a_div_b >>? continuation maybe_a_div_b >>? continuation
(** The function [divide_three_bind_symbol'] is equivalent to (* The function [divide_three_bind_symbol'] is equivalent to
[divide_three_bind_symbol], where the two temporary [let] [divide_three_bind_symbol], where the two temporary [let]
definitions are inlined for a more compact reading. definitions are inlined for a more compact reading. *)
*)
let divide_three_bind_symbol' a b c = let divide_three_bind_symbol' a b c =
divide_trace a b >>? (fun a_div_b -> divide_trace a_div_b c) divide_trace a b >>? (fun a_div_b -> divide_trace a_div_b c)
(** This is now fairly legible, but chaining many such functions is (* This is now fairly legible, but chaining many such functions is
not the usual way of writing code. We use the PPX extension to not the usual way of writing code. We use the PPX extension to
the OCaml compiler [ppx_let] to add some syntactic sugar. the OCaml compiler [ppx_let] to add some syntactic sugar.
The extension framework PPX is enabled by adding the following The extension framework PPX is enabled by adding the following
lines inside the section [(library ...)] or [(executable ...)] lines inside the section [(library ...)] or [(executable ...)]
of the [dune] file for the project that uses [ppx_let], like so: of the [dune] file for the project that uses [ppx_let], like so:
[(preprocess [(preprocess
(pps simple-utils.ppx_let_generalized))] (pps simple-utils.ppx_let_generalized))]
The extension [ppx_let] requires the module [Let_syntax] to be The extension [ppx_let] requires the module [Let_syntax] to be
defined. defined. *)
*)
module Let_syntax = struct module Let_syntax = struct
let bind m ~f = m >>? f let bind m ~f = m >>? f
module Open_on_rhs_bind = struct end module Open_on_rhs_bind = struct end
end end
(** The function [divide_three_bind_ppx_let] is equivalent to the (* The function [divide_three_bind_ppx_let] is equivalent to the
function [divide_three_bind_symbol']. The only difference is function [divide_three_bind_symbol']. The only difference is
that the module [Open_on_rhs_bind] is implicitly opened around that the module [Open_on_rhs_bind] is implicitly opened around
the expression on the righ-hand side of the [=] sign, namely the expression on the righ-hand side of the [=] sign, namely
[divide_trace a b]. [divide_trace a b]. *)
*)
let divide_three_bind_ppx_let a b c = let divide_three_bind_ppx_let a b c =
let%bind a_div_b = divide_trace a b let%bind a_div_b = divide_trace a b
in divide_trace a_div_b c in divide_trace a_div_b c
(** The function [divide_many_bind_ppx_let] shows how well this (** The function [divide_many_bind_ppx_let] shows how well this
notation composes. notation composes. *)
*)
let divide_many_bind_ppx_let a b c d e f = let divide_many_bind_ppx_let a b c d e f =
let x = a in let x = a in
let%bind x = divide_trace x b in let%bind x = divide_trace x b in
@ -153,34 +151,35 @@ module Trace_tutorial = struct
in Ok (x, []) in Ok (x, [])
(** The function [ok] is a shorthand for an [Ok] without (** The function [ok] is a shorthand for an [Ok] without
annotations. annotations. *)
*)
let ok x = Ok (x, []) let ok x = Ok (x, [])
(** The function [map] lifts a regular ['a -> 'b] function on values to (* The function [map] lifts a regular ['a -> 'b] function on values to
a function on results, of type ['a result -> 'b result]. a function on results, of type ['a result -> 'b result]. *)
*)
let map f = function let map f = function
Ok (x, annotations) -> Ok (f x, annotations) Ok (x, annotations) -> Ok (f x, annotations)
| e -> e | e -> e
(** The function [bind_list] turns a list of results of type [('a (* The function [bind_list] turns a list of results of type [('a
result) list] into a result of list, of type [('a list) result], result) list] into a result of list, of type [('a list) result],
as follows. as follows.
{ul * If the list only contains [Ok] values, it strips the [Ok]
{li If the list only contains [Ok] values, it strips the [Ok] of each element and returns that list wrapped with [Ok].}
of each element and returns that list wrapped with [Ok].}
{li Otherwise, one or more of the elements of the input list * Otherwise, one or more of the elements of the input list
is [Error], then [bind_list] returns the first error in the is [Error], then [bind_list] returns the first error in the
list.}} list.
*) *)
let rec bind_list = function let rec bind_list = function
[] -> ok [] [] -> ok []
| hd::tl -> | hd::tl ->
hd >>? fun hd -> hd >>? fun hd ->
bind_list tl >>? fun tl -> bind_list tl >>? fun tl ->
ok @@ hd::tl ok @@ hd::tl
(** A major feature of [Trace] is that it enables having a stack of (* A major feature of [Trace] is that it enables having a stack of
errors (that should act as a simplified stack frame), rather errors (that should act as a simplified stack frame), rather
than a unique error. It is done by using the function than a unique error. It is done by using the function
[trace]. For instance, let's say that you have a function that [trace]. For instance, let's say that you have a function that
@ -198,17 +197,17 @@ module Trace_tutorial = struct
trace (simple_error "error getting key") @@ trace (simple_error "error getting key") @@
get key map get key map
in ...] in ...]
And this will pass along the error triggered by [get key map]. And this will pass along the error triggered by [get key map]. *)
*)
let trace err = function let trace err = function
Error e -> Error (err::e) Error e -> Error (err::e)
| ok -> ok | ok -> ok
(** The real trace monad is very similar to the one that we have (* The real trace monad is very similar to the one that we have
defined above. The main difference is that the errors and defined above. The main difference is that the errors and
annotations are structured data (instead of plain strings) and annotations are structured data (instead of plain strings) and
are generated lazily. are generated lazily. *)
*)
let the_end = "End of the tutorial." let the_end = "End of the tutorial."
end (* end Trace_tutorial. *) end (* end Trace_tutorial. *)
@ -239,8 +238,7 @@ module JSON_string_utils = struct
match assoc j with match assoc j with
None -> j None -> j
| Some assoc -> `Assoc ( | Some assoc -> `Assoc (
List.map (fun (k', v') -> (k', if k = k' then v else v')) assoc List.map (fun (k', v') -> (k', if k = k' then v else v')) assoc)
)
let swap f l r = f r l let swap f l r = f r l
@ -264,38 +262,39 @@ module JSON_string_utils = struct
let (||) l r = l |> default r let (||) l r = l |> default r
let (|^) = bind2 (^) let (|^) = bind2 (^)
end end
type 'a thunk = unit -> 'a type 'a thunk = unit -> 'a
(** Errors are encoded in JSON. This is because different libraries (* Errors are encoded in JSON. This is because different libraries
will implement their own helpers, and we do not want to hardcode will implement their own helpers, and we do not want to hardcode
in their type how they are supposed to interact. in their type how they are supposed to interact. *)
*)
type error = J.t type error = J.t
(** Thunks are used because computing some errors can be costly, and (* Thunks are used because computing some errors can be costly, and
we do not want to spend most of our time building errors. Instead, we do not want to spend most of our time building errors. Instead,
their computation is deferred. their computation is deferred.*)
*)
type error_thunk = error thunk type error_thunk = error thunk
(** Annotations should be used in debug mode to aggregate information (* Annotations should be used in debug mode to aggregate information
about some value history. Where it was produced, when it was about some value history. Where it was produced, when it was
modified, etc. It is currently not being used. *) modified, etc. It is currently not being used. *)
type annotation = J.t type annotation = J.t
(** Even in debug mode, building annotations can be quite (* Even in debug mode, building annotations can be quite
resource-intensive. Instead, a thunk is passed, that is computed resource-intensive. Instead, a thunk is passed, that is computed
only when debug information is queried (typically before a print). only when debug information is queried (typically before a print).*)
*)
type annotation_thunk = annotation thunk type annotation_thunk = annotation thunk
(** Types of traced elements. It might be good to rename it [trace] at (* Types of traced elements. It might be good to rename it [trace] at
some point. some point. *)
*)
type nonrec 'a result = ('a * annotation_thunk list, error_thunk) result type nonrec 'a result = ('a * annotation_thunk list, error_thunk) result
(* (*
= Ok of 'a * annotation_thunk list = Ok of 'a * annotation_thunk list
| Error of error_thunk | Error of error_thunk
@ -308,29 +307,28 @@ let ok x = Ok (x, [])
let fail err = Error err let fail err = Error err
(** {1 Monadic operators} *) (* Monadic operators *)
let bind f = function let bind f = function
Ok (x, ann) -> ( Error _ as e -> e
| Ok (x, ann) ->
match f x with match f x with
Ok (x', ann') -> Ok (x', ann' @ ann) Ok (x', ann') -> Ok (x', ann' @ ann)
| Error _ as e' -> ignore ann; e') | Error _ as e' -> ignore ann; e'
| Error _ as e -> e
let map f = function let map f = function
Ok (x, annotations) -> Ok (f x, annotations) Ok (x, annotations) -> Ok (f x, annotations)
| Error _ as e -> e | Error _ as e -> e
(** The lexical convention usually adopted for the bind function is (* The lexical convention usually adopted for the bind function is
[>>=], but ours comes from the Tezos code base, where the [result] [>>=], but ours comes from the Tezos code base, where the [result]
bind is [>>?], and [Lwt]'s (threading library) is [>>=], and the bind is [>>?], and [Lwt]'s (threading library) is [>>=], and the
combination of both is [>>=?]. combination of both is [>>=?]. *)
*)
let (>>?) x f = bind f x let (>>?) x f = bind f x
let (>>|?) x f = map f x let (>>|?) x f = map f x
(** (* Used by PPX_let, an OCaml preprocessor.
Used by PPX_let, an OCaml preprocessor.
What it does is that, when you only care about the case where a result isn't What it does is that, when you only care about the case where a result isn't
an error, instead of writing: an error, instead of writing:
[ [
@ -344,21 +342,20 @@ let (>>|?) x f = map f x
] ]
This is much more typical of OCaml. This makes the code more This is much more typical of OCaml. This makes the code more
readable, easy to write and refactor. It is used pervasively in readable, easy to write and refactor. It is used pervasively in
LIGO. LIGO. *)
*)
module Let_syntax = struct module Let_syntax = struct
let bind m ~f = m >>? f let bind m ~f = m >>? f
module Open_on_rhs_bind = struct end module Open_on_rhs_bind = struct end
end end
(* Build a thunk from a constant. *)
(** Build a thunk from a constant.
*)
let thunk x () = x let thunk x () = x
(** Build a standard error, with a title, a message, an error code and (* Build a standard error, with a title, a message, an error code and
some data. some data. *)
*)
let mk_error let mk_error
?(error_code : int thunk option) ?(message : string thunk option) ?(error_code : int thunk option) ?(message : string thunk option)
?(data : (string * string thunk) list option) ?(data : (string * string thunk) list option)
@ -373,9 +370,11 @@ let mk_error
let type' = Some ("type" , `String "error") in let type' = Some ("type" , `String "error") in
let children' = Some ("children" , `List children) in let children' = Some ("children" , `List children) in
let infos' = Some ("infos" , `List infos) in let infos' = Some ("infos" , `List infos) in
`Assoc (X_option.collapse_list [ error_code' ; title' ; message' ; data' ; type' ; children' ; infos' ]) `Assoc (X_option.collapse_list
[error_code'; title'; message'; data'; type'; children'; infos'])
let error ?data ?error_code ?children ?infos title message () = mk_error ?data ?error_code ?children ?infos ~title:(title) ~message:(message) () let error ?data ?error_code ?children ?infos title message () =
mk_error ?data ?error_code ?children ?infos ~title ~message ()
let prepend_child = fun child err -> let prepend_child = fun child err ->
let open JSON_string_utils in let open JSON_string_utils in
@ -389,9 +388,8 @@ let patch_children = fun children err ->
let open JSON_string_utils in let open JSON_string_utils in
patch err "children" (`List (List.map (fun f -> f ()) children)) patch err "children" (`List (List.map (fun f -> f ()) children))
(** (* Build a standard info, with a title, a message, an info code and some data. *)
Build a standard info, with a title, a message, an info code and some data.
*)
let mk_info let mk_info
?(info_code : int thunk option) ?(message : string thunk option) ?(info_code : int thunk option) ?(message : string thunk option)
?(data : (string * string thunk) list option) ?(data : (string * string thunk) list option)
@ -405,7 +403,8 @@ let mk_info
let type' = Some ("type" , `String "info") in let type' = Some ("type" , `String "info") in
`Assoc (X_option.collapse_list [ error_code' ; title' ; message' ; data' ; type' ]) `Assoc (X_option.collapse_list [ error_code' ; title' ; message' ; data' ; type' ])
let info ?data ?info_code title message () = mk_info ?data ?info_code ~title:(title) ~message:(message) () let info ?data ?info_code title message () =
mk_info ?data ?info_code ~title ~message ()
let prepend_info = fun info err -> let prepend_info = fun info err ->
let open JSON_string_utils in let open JSON_string_utils in
@ -416,32 +415,31 @@ let prepend_info = fun info err ->
patch err "infos" (`List infos) patch err "infos" (`List infos)
(** Helpers that ideally should not be used in production. (* Helpers that ideally should not be used in production. *)
*)
let simple_error str () = mk_error ~title:(thunk str) () let simple_error str () = mk_error ~title:(thunk str) ()
let simple_info str () = mk_info ~title:(thunk str) () let simple_info str () = mk_info ~title:(thunk str) ()
let simple_fail str = fail @@ simple_error str let simple_fail str = fail @@ simple_error str
let internal_assertion_failure str = simple_error ("assertion failed: " ^ str) let internal_assertion_failure str = simple_error ("assertion failed: " ^ str)
(** To be used when you only want to signal an error. It can be useful (* To be used when you only want to signal an error. It can be useful
when followed by [trace_strong]. when followed by [trace_strong]. *)
*)
let dummy_fail = simple_fail "dummy" let dummy_fail = simple_fail "dummy"
let trace info = function let trace info = function
Ok _ as o -> o Ok _ as o -> o
| Error err -> Error (fun () -> prepend_info (info ()) (err ())) | Error err -> Error (fun () -> prepend_info (info ()) (err ()))
(** Erase the current error stack, and replace it by the given (* Erase the current error stack, and replace it by the given
error. It's useful when using [Assert] and you want to discard its error. It's useful when using [Assert] and you want to discard its
autogenerated message. autogenerated message. *)
*)
let trace_strong err = function let trace_strong err = function
Ok _ as o -> o Ok _ as o -> o
| Error _ -> Error err | Error _ -> Error err
(** (* Sometimes, when you have a list of potentially erroneous elements, you need
Sometimes, when you have a list of potentially erroneous elements, you need
to retrieve all the errors, instead of just the first one. In that case, do: to retrieve all the errors, instead of just the first one. In that case, do:
[let type_list lst = [let type_list lst =
let%bind lst' = let%bind lst' =
@ -451,8 +449,7 @@ let trace_strong err = function
Where before you would have written: Where before you would have written:
[let type_list lst = [let type_list lst =
let%bind lst' = bind_map_list type_element lst in let%bind lst' = bind_map_list type_element lst in
...] ...] *)
*)
let trace_list err lst = let trace_list err lst =
let oks = let oks =
let aux = function let aux = function
@ -468,30 +465,24 @@ let trace_list err lst =
| [] -> ok oks | [] -> ok oks
| errs -> fail (fun () -> patch_children errs err) | errs -> fail (fun () -> patch_children errs err)
(** (* Trace, but with an error which generation may itself fail. *)
Trace, but with an error which generation may itself fail.
*)
let trace_r err_thunk_may_fail = function let trace_r err_thunk_may_fail = function
| Ok _ as o -> o Ok _ as o -> o
| Error _ -> ( | Error _ ->
match err_thunk_may_fail () with match err_thunk_may_fail () with
| Ok (err, annotations) -> ignore annotations; Error (err) Ok (err, annotations) -> ignore annotations; Error (err)
| Error errors_while_generating_error -> | Error errors_while_generating_error ->
(* TODO: the complexity could be O(n*n) in the worst case, (* TODO: the complexity could be O(n*n) in the worst case,
this should use some catenable lists. *) this should use some catenable lists. *)
Error (errors_while_generating_error) Error (errors_while_generating_error)
)
(** (* [trace_f f error] yields a function that acts the same as `f`, but with an
`trace_f f error` yields a function that acts the same as `f`, but with an error frame that has one more error. *)
error frame that has one more error.
*) let trace_f f error x = trace error @@ f x
let trace_f f error x = (* Same, but for functions with 2 parameters. *)
trace error @@ f x
(**
Same, but for functions with 2 parameters.
*)
let trace_f_2 f error x y = let trace_f_2 f error x y =
trace error @@ f x y trace error @@ f x y
@ -520,8 +511,8 @@ let to_option = function
Convert an option to a result, with a given error if the parameter is None. Convert an option to a result, with a given error if the parameter is None.
*) *)
let trace_option error = function let trace_option error = function
| None -> fail error None -> fail error
| Some s -> ok s | Some s -> ok s
(** Utilities to interact with other data-structure. [bind_t] takes (** Utilities to interact with other data-structure. [bind_t] takes
an ['a result t] and makes a ['a t result] out of it. It "lifts" the an ['a result t] and makes a ['a t result] out of it. It "lifts" the
@ -535,22 +526,14 @@ let trace_option error = function
*) *)
let bind_map_option f = function let bind_map_option f = function
| None -> ok None None -> ok None
| Some s -> f s >>? fun x -> ok (Some x) | Some s -> f s >>? fun x -> ok (Some x)
let rec bind_list = function let rec bind_list = function
| [] -> ok [] [] -> ok []
| hd :: tl -> ( | hd::tl -> hd >>? fun hd -> bind_list tl >>? fun tl -> ok @@ hd :: tl
hd >>? fun hd -> let bind_ne_list (hd, tl) =
bind_list tl >>? fun tl -> hd >>? fun hd -> bind_list tl >>? fun tl -> ok @@ (hd, tl)
ok @@ hd :: tl
)
let bind_ne_list = fun (hd , tl) ->
hd >>? fun hd ->
bind_list tl >>? fun tl ->
ok @@ (hd , tl)
let bind_smap (s:_ X_map.String.t) = let bind_smap (s:_ X_map.String.t) =
let open X_map.String in let open X_map.String in
let aux k v prev = let aux k v prev =
@ -718,6 +701,10 @@ let bind_fold_map_pair f acc (a, b) =
let bind_map_triple f (a, b, c) = let bind_map_triple f (a, b, c) =
bind_and3 (f a, f b, f c) bind_and3 (f a, f b, f c)
let bind_list_cons v lst =
lst >>? fun lst ->
ok (v::lst)
let rec bind_chain : ('a -> 'a result) list -> 'a -> 'a result = fun fs x -> let rec bind_chain : ('a -> 'a result) list -> 'a -> 'a result = fun fs x ->
match fs with match fs with
| [] -> ok x | [] -> ok x
@ -726,7 +713,6 @@ let rec bind_chain : ('a -> 'a result) list -> 'a -> 'a result = fun fs x ->
bind aux (ok x) bind aux (ok x)
) )
(** (**
Wraps a call that might trigger an exception in a result. Wraps a call that might trigger an exception in a result.
*) *)