summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.depend43
-rw-r--r--Makefile3
-rw-r--r--Makefile.Mac4
-rw-r--r--Makefile.nt3
-rw-r--r--driver/compile.ml2
-rw-r--r--driver/errors.ml5
-rw-r--r--driver/optcompile.ml2
-rw-r--r--driver/opterrors.ml5
-rw-r--r--parsing/parse.ml12
-rw-r--r--parsing/parse.mli1
-rw-r--r--parsing/parser.mly56
-rw-r--r--parsing/syntaxerr.ml47
-rw-r--r--parsing/syntaxerr.mli22
-rw-r--r--tools/Makefile2
-rw-r--r--tools/Makefile.Mac2
-rw-r--r--tools/Makefile.nt2
-rw-r--r--tools/ocamlprof.ml5
17 files changed, 172 insertions, 44 deletions
diff --git a/.depend b/.depend
index a397caeac..1dacd1217 100644
--- a/.depend
+++ b/.depend
@@ -15,11 +15,12 @@ utils/tbl.cmx: utils/tbl.cmi
utils/terminfo.cmo: utils/terminfo.cmi
utils/terminfo.cmx: utils/terminfo.cmi
parsing/lexer.cmi: parsing/parser.cmi
-parsing/parse.cmi: parsing/parsetree.cmi
+parsing/parse.cmi: parsing/parsetree.cmi parsing/syntaxerr.cmi
parsing/parser.cmi: parsing/parsetree.cmi
parsing/parsetree.cmi: parsing/asttypes.cmi parsing/location.cmi \
parsing/longident.cmi
parsing/pstream.cmi: parsing/parsetree.cmi
+parsing/syntaxerr.cmi: parsing/location.cmi
parsing/lexer.cmo: utils/misc.cmi parsing/parser.cmi parsing/lexer.cmi
parsing/lexer.cmx: utils/misc.cmx parsing/parser.cmx parsing/lexer.cmi
parsing/linenum.cmo: utils/misc.cmi parsing/linenum.cmi
@@ -31,9 +32,9 @@ parsing/location.cmx: parsing/linenum.cmx utils/terminfo.cmx \
parsing/longident.cmo: utils/misc.cmi parsing/longident.cmi
parsing/longident.cmx: utils/misc.cmx parsing/longident.cmi
parsing/parse.cmo: parsing/lexer.cmi parsing/location.cmi parsing/parser.cmi \
- parsing/parse.cmi
+ parsing/syntaxerr.cmi parsing/parse.cmi
parsing/parse.cmx: parsing/lexer.cmx parsing/location.cmx parsing/parser.cmx \
- parsing/parse.cmi
+ parsing/syntaxerr.cmx parsing/parse.cmi
parsing/parser.cmo: parsing/asttypes.cmi utils/clflags.cmo \
parsing/location.cmi parsing/longident.cmi parsing/parsetree.cmi \
parsing/pstream.cmi parsing/parser.cmi
@@ -44,6 +45,8 @@ parsing/pstream.cmo: parsing/asttypes.cmi parsing/location.cmi \
parsing/longident.cmi parsing/parsetree.cmi parsing/pstream.cmi
parsing/pstream.cmx: parsing/asttypes.cmi parsing/location.cmx \
parsing/longident.cmx parsing/parsetree.cmi parsing/pstream.cmi
+parsing/syntaxerr.cmo: parsing/location.cmi parsing/syntaxerr.cmi
+parsing/syntaxerr.cmx: parsing/location.cmx parsing/syntaxerr.cmi
typing/btype.cmi: typing/path.cmi typing/types.cmi
typing/ctype.cmi: parsing/asttypes.cmi typing/env.cmi typing/ident.cmi \
typing/types.cmi
@@ -361,8 +364,6 @@ asmcomp/selectgen.cmi: asmcomp/arch.cmo asmcomp/cmm.cmi typing/ident.cmi \
asmcomp/selection.cmi: asmcomp/cmm.cmi asmcomp/mach.cmi
asmcomp/spill.cmi: asmcomp/mach.cmi
asmcomp/split.cmi: asmcomp/mach.cmi
-asmcomp/arch.cmo: utils/config.cmi
-asmcomp/arch.cmx: utils/config.cmx
asmcomp/asmgen.cmo: utils/clflags.cmo asmcomp/closure.cmi asmcomp/cmm.cmi \
asmcomp/cmmgen.cmi asmcomp/coloring.cmi utils/config.cmi asmcomp/emit.cmi \
asmcomp/emitaux.cmi asmcomp/interf.cmi asmcomp/linearize.cmi \
@@ -435,12 +436,12 @@ asmcomp/compilenv.cmx: asmcomp/clambda.cmx utils/config.cmx typing/env.cmx \
typing/ident.cmx utils/misc.cmx asmcomp/compilenv.cmi
asmcomp/emit.cmo: asmcomp/arch.cmo asmcomp/cmm.cmi asmcomp/compilenv.cmi \
utils/config.cmi asmcomp/emitaux.cmi asmcomp/linearize.cmi \
- parsing/location.cmi asmcomp/mach.cmi utils/misc.cmi utils/nativeint.cmi \
- asmcomp/proc.cmi asmcomp/reg.cmi asmcomp/emit.cmi
+ asmcomp/mach.cmi utils/misc.cmi utils/nativeint.cmi asmcomp/proc.cmi \
+ asmcomp/reg.cmi asmcomp/emit.cmi
asmcomp/emit.cmx: asmcomp/arch.cmx asmcomp/cmm.cmx asmcomp/compilenv.cmx \
utils/config.cmx asmcomp/emitaux.cmx asmcomp/linearize.cmx \
- parsing/location.cmx asmcomp/mach.cmx utils/misc.cmx utils/nativeint.cmx \
- asmcomp/proc.cmx asmcomp/reg.cmx asmcomp/emit.cmi
+ asmcomp/mach.cmx utils/misc.cmx utils/nativeint.cmx asmcomp/proc.cmx \
+ asmcomp/reg.cmx asmcomp/emit.cmi
asmcomp/emitaux.cmo: utils/nativeint.cmi asmcomp/emitaux.cmi
asmcomp/emitaux.cmx: utils/nativeint.cmx asmcomp/emitaux.cmi
asmcomp/interf.cmo: asmcomp/mach.cmi asmcomp/proc.cmi asmcomp/reg.cmi \
@@ -479,8 +480,10 @@ asmcomp/proc.cmx: asmcomp/arch.cmx utils/ccomp.cmx asmcomp/cmm.cmx \
asmcomp/mach.cmx utils/misc.cmx asmcomp/reg.cmx asmcomp/proc.cmi
asmcomp/reg.cmo: asmcomp/cmm.cmi asmcomp/reg.cmi
asmcomp/reg.cmx: asmcomp/cmm.cmx asmcomp/reg.cmi
-asmcomp/reload.cmo: asmcomp/reloadgen.cmi asmcomp/reload.cmi
-asmcomp/reload.cmx: asmcomp/reloadgen.cmx asmcomp/reload.cmi
+asmcomp/reload.cmo: asmcomp/arch.cmo asmcomp/cmm.cmi asmcomp/mach.cmi \
+ asmcomp/reg.cmi asmcomp/reloadgen.cmi asmcomp/reload.cmi
+asmcomp/reload.cmx: asmcomp/arch.cmx asmcomp/cmm.cmx asmcomp/mach.cmx \
+ asmcomp/reg.cmx asmcomp/reloadgen.cmx asmcomp/reload.cmi
asmcomp/reloadgen.cmo: asmcomp/mach.cmi utils/misc.cmi asmcomp/reg.cmi \
asmcomp/reloadgen.cmi
asmcomp/reloadgen.cmx: asmcomp/mach.cmx utils/misc.cmx asmcomp/reg.cmx \
@@ -489,10 +492,8 @@ asmcomp/schedgen.cmo: asmcomp/arch.cmo asmcomp/cmm.cmi asmcomp/linearize.cmi \
asmcomp/mach.cmi utils/misc.cmi asmcomp/reg.cmi asmcomp/schedgen.cmi
asmcomp/schedgen.cmx: asmcomp/arch.cmx asmcomp/cmm.cmx asmcomp/linearize.cmx \
asmcomp/mach.cmx utils/misc.cmx asmcomp/reg.cmx asmcomp/schedgen.cmi
-asmcomp/scheduling.cmo: asmcomp/arch.cmo asmcomp/mach.cmi \
- asmcomp/schedgen.cmi asmcomp/scheduling.cmi
-asmcomp/scheduling.cmx: asmcomp/arch.cmx asmcomp/mach.cmx \
- asmcomp/schedgen.cmx asmcomp/scheduling.cmi
+asmcomp/scheduling.cmo: asmcomp/schedgen.cmi asmcomp/scheduling.cmi
+asmcomp/scheduling.cmx: asmcomp/schedgen.cmx asmcomp/scheduling.cmi
asmcomp/selectgen.cmo: asmcomp/arch.cmo asmcomp/cmm.cmi typing/ident.cmi \
asmcomp/mach.cmi utils/misc.cmi utils/nativeint.cmi asmcomp/proc.cmi \
asmcomp/reg.cmi utils/tbl.cmi asmcomp/selectgen.cmi
@@ -500,10 +501,10 @@ asmcomp/selectgen.cmx: asmcomp/arch.cmx asmcomp/cmm.cmx typing/ident.cmx \
asmcomp/mach.cmx utils/misc.cmx utils/nativeint.cmx asmcomp/proc.cmx \
asmcomp/reg.cmx utils/tbl.cmx asmcomp/selectgen.cmi
asmcomp/selection.cmo: asmcomp/arch.cmo asmcomp/cmm.cmi asmcomp/mach.cmi \
- utils/misc.cmi asmcomp/reg.cmi asmcomp/selectgen.cmi \
+ utils/misc.cmi asmcomp/proc.cmi asmcomp/reg.cmi asmcomp/selectgen.cmi \
asmcomp/selection.cmi
asmcomp/selection.cmx: asmcomp/arch.cmx asmcomp/cmm.cmx asmcomp/mach.cmx \
- utils/misc.cmx asmcomp/reg.cmx asmcomp/selectgen.cmx \
+ utils/misc.cmx asmcomp/proc.cmx asmcomp/reg.cmx asmcomp/selectgen.cmx \
asmcomp/selection.cmi
asmcomp/spill.cmo: asmcomp/mach.cmi asmcomp/proc.cmi asmcomp/reg.cmi \
asmcomp/spill.cmi
@@ -527,13 +528,13 @@ driver/compile.cmx: bytecomp/bytegen.cmx utils/ccomp.cmx utils/clflags.cmx \
typing/typedtree.cmx typing/typemod.cmx driver/compile.cmi
driver/errors.cmo: bytecomp/bytelibrarian.cmi bytecomp/bytelink.cmi \
typing/env.cmi typing/includemod.cmi parsing/lexer.cmi \
- parsing/location.cmi parsing/parse.cmi bytecomp/symtable.cmi \
+ parsing/location.cmi bytecomp/symtable.cmi parsing/syntaxerr.cmi \
bytecomp/translcore.cmi typing/typeclass.cmi typing/typecore.cmi \
typing/typedecl.cmi typing/typemod.cmi typing/typetexp.cmi \
driver/errors.cmi
driver/errors.cmx: bytecomp/bytelibrarian.cmx bytecomp/bytelink.cmx \
typing/env.cmx typing/includemod.cmx parsing/lexer.cmx \
- parsing/location.cmx parsing/parse.cmx bytecomp/symtable.cmx \
+ parsing/location.cmx bytecomp/symtable.cmx parsing/syntaxerr.cmx \
bytecomp/translcore.cmx typing/typeclass.cmx typing/typecore.cmx \
typing/typedecl.cmx typing/typemod.cmx typing/typetexp.cmx \
driver/errors.cmi
@@ -556,13 +557,13 @@ driver/optcompile.cmx: asmcomp/asmgen.cmx utils/ccomp.cmx utils/clflags.cmx \
driver/opterrors.cmo: asmcomp/asmgen.cmi asmcomp/asmlibrarian.cmi \
asmcomp/asmlink.cmi asmcomp/compilenv.cmi typing/env.cmi \
typing/includemod.cmi parsing/lexer.cmi parsing/location.cmi \
- parsing/parse.cmi bytecomp/translcore.cmi typing/typeclass.cmi \
+ parsing/syntaxerr.cmi bytecomp/translcore.cmi typing/typeclass.cmi \
typing/typecore.cmi typing/typedecl.cmi typing/typemod.cmi \
typing/typetexp.cmi driver/opterrors.cmi
driver/opterrors.cmx: asmcomp/asmgen.cmx asmcomp/asmlibrarian.cmx \
asmcomp/asmlink.cmx asmcomp/compilenv.cmx typing/env.cmx \
typing/includemod.cmx parsing/lexer.cmx parsing/location.cmx \
- parsing/parse.cmx bytecomp/translcore.cmx typing/typeclass.cmx \
+ parsing/syntaxerr.cmx bytecomp/translcore.cmx typing/typeclass.cmx \
typing/typecore.cmx typing/typedecl.cmx typing/typemod.cmx \
typing/typetexp.cmx driver/opterrors.cmi
driver/optmain.cmo: asmcomp/asmlibrarian.cmi asmcomp/asmlink.cmi \
diff --git a/Makefile b/Makefile
index 7833fb116..ffd35c77e 100644
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,8 @@ UTILS=utils/misc.cmo utils/tbl.cmo utils/config.cmo \
OPTUTILS=$(UTILS) utils/nativeint.cmo
PARSING=parsing/linenum.cmo parsing/location.cmo parsing/longident.cmo \
- parsing/pstream.cmo parsing/parser.cmo parsing/lexer.cmo parsing/parse.cmo
+ parsing/syntaxerr.cmo parsing/pstream.cmo parsing/parser.cmo \
+ parsing/lexer.cmo parsing/parse.cmo
TYPING=typing/ident.cmo typing/path.cmo \
typing/primitive.cmo typing/types.cmo \
diff --git a/Makefile.Mac b/Makefile.Mac
index 9cca910f4..3a5636919 100644
--- a/Makefile.Mac
+++ b/Makefile.Mac
@@ -19,8 +19,8 @@ UTILS = :utils:misc.cmo :utils:tbl.cmo :utils:config.cmo ¶
:utils:clflags.cmo :utils:terminfo.cmo :utils:ccomp.cmo
PARSING = :parsing:linenum.cmo :parsing:location.cmo :parsing:longident.cmo ¶
- :parsing:pstream.cmo :parsing:parser.cmo :parsing:lexer.cmo ¶
- :parsing:parse.cmo
+ :parsing:syntaxerr.cmo :parsing:pstream.cmo :parsing:parser.cmo ¶
+ :parsing:lexer.cmo :parsing:parse.cmo
TYPING = :typing:ident.cmo :typing:path.cmo ¶
:typing:primitive.cmo :typing:types.cmo ¶
diff --git a/Makefile.nt b/Makefile.nt
index 872ab87d6..1d5705f78 100644
--- a/Makefile.nt
+++ b/Makefile.nt
@@ -21,7 +21,8 @@ UTILS=utils\misc.cmo utils\tbl.cmo utils\config.cmo \
OPTUTILS=$(UTILS) utils\nativeint.cmo
PARSING=parsing\linenum.cmo parsing\location.cmo parsing\longident.cmo \
- parsing\pstream.cmo parsing\parser.cmo parsing\lexer.cmo parsing\parse.cmo
+ parsing\syntaxerr.cmo parsing\pstream.cmo parsing\parser.cmo \
+ parsing\lexer.cmo parsing\parse.cmo
TYPING=typing\ident.cmo typing\path.cmo \
typing\primitive.cmo typing\types.cmo \
diff --git a/driver/compile.ml b/driver/compile.ml
index 285db4743..d79101792 100644
--- a/driver/compile.ml
+++ b/driver/compile.ml
@@ -77,7 +77,7 @@ let parse_file inputfile parse_fun ast_magic =
else false
with
Outdated_version ->
- failwith "Ocaml and preprocessor have incompatible versions"
+ fatal_error "Ocaml and preprocessor have incompatible versions"
| _ -> false
in
let ast =
diff --git a/driver/errors.ml b/driver/errors.ml
index c93f6f3eb..6b032f782 100644
--- a/driver/errors.ml
+++ b/driver/errors.ml
@@ -24,9 +24,8 @@ let report_error exn =
Lexer.Error(err, start, stop) ->
Location.print {loc_start = start; loc_end = stop};
Lexer.report_error err
- | Parse.Error(start, stop) ->
- Location.print {loc_start = start; loc_end = stop};
- print_string "Syntax error"
+ | Syntaxerr.Error err ->
+ Syntaxerr.report_error err
| Env.Error err ->
Env.report_error err
| Typecore.Error(loc, err) ->
diff --git a/driver/optcompile.ml b/driver/optcompile.ml
index 7d1e67a94..897f03910 100644
--- a/driver/optcompile.ml
+++ b/driver/optcompile.ml
@@ -74,7 +74,7 @@ let parse_file inputfile parse_fun ast_magic =
else false
with
Outdated_version ->
- failwith "Ocaml and preprocessor have incompatible versions"
+ fatal_error "Ocaml and preprocessor have incompatible versions"
| _ -> false
in
let ast =
diff --git a/driver/opterrors.ml b/driver/opterrors.ml
index 01b3f4dd4..a5910355d 100644
--- a/driver/opterrors.ml
+++ b/driver/opterrors.ml
@@ -24,9 +24,8 @@ let report_error exn =
Lexer.Error(err, start, stop) ->
Location.print {loc_start = start; loc_end = stop};
Lexer.report_error err
- | Parse.Error(start, stop) ->
- Location.print {loc_start = start; loc_end = stop};
- print_string "Syntax error"
+ | Syntaxerr.Error err ->
+ Syntaxerr.report_error err
| Env.Error err ->
Env.report_error err
| Typecore.Error(loc, err) ->
diff --git a/parsing/parse.ml b/parsing/parse.ml
index 02a9a56fa..a04571f01 100644
--- a/parsing/parse.ml
+++ b/parsing/parse.ml
@@ -13,7 +13,8 @@
(* Entry points in the parser *)
-exception Error of int * int (* Syntax error *)
+open Location
+
(* Skip tokens to the end of the phrase *)
let rec skip_phrase lexbuf =
@@ -43,12 +44,15 @@ let wrap parsing_fun lexbuf =
| Lexer.Error(_, _, _) as err ->
if !Location.input_name = "" then skip_phrase lexbuf;
raise err
+ | Syntaxerr.Error _ as err ->
+ if !Location.input_name = "" then maybe_skip_phrase lexbuf;
+ raise err
| Parsing.Parse_error ->
- let start = Lexing.lexeme_start lexbuf
- and stop = Lexing.lexeme_end lexbuf in
+ let loc = { loc_start = Lexing.lexeme_start lexbuf;
+ loc_end = Lexing.lexeme_end lexbuf } in
if !Location.input_name = ""
then maybe_skip_phrase lexbuf;
- raise(Error(start, stop))
+ raise(Syntaxerr.Error(Syntaxerr.Other loc))
let implementation = wrap Parser.implementation
and interface = wrap Parser.interface
diff --git a/parsing/parse.mli b/parsing/parse.mli
index ddd58daa1..2becb1271 100644
--- a/parsing/parse.mli
+++ b/parsing/parse.mli
@@ -18,4 +18,3 @@ val interface : Lexing.lexbuf -> Parsetree.signature
val toplevel_phrase : Lexing.lexbuf -> Parsetree.toplevel_phrase
val use_file : Lexing.lexbuf -> Parsetree.toplevel_phrase list
-exception Error of int * int (* Syntax error *)
diff --git a/parsing/parser.mly b/parsing/parser.mly
index 79a5ef3cf..74c90f1e7 100644
--- a/parsing/parser.mly
+++ b/parsing/parser.mly
@@ -96,6 +96,10 @@ let rec mkrangepat c1 c2 =
mkpat(Ppat_or(mkpat(Ppat_constant(Const_char c1)),
mkrangepat (Char.chr(Char.code c1 + 1)) c2))
+let unclosed opening_name opening_num closing_name closing_num =
+ raise(Syntaxerr.Error(Syntaxerr.Unclosed(rhs_loc opening_num, opening_name,
+ rhs_loc closing_num, closing_name)))
+
%}
/* Tokens */
@@ -277,15 +281,23 @@ module_expr:
{ mkmod(Pmod_ident $1) }
| STRUCT structure END
{ mkmod(Pmod_structure($2)) }
+ | STRUCT structure error
+ { unclosed "struct" 1 "end" 3 }
| FUNCTOR LPAREN UIDENT COLON module_type RPAREN MINUSGREATER module_expr
%prec prec_fun
{ mkmod(Pmod_functor($3, $5, $8)) }
| module_expr LPAREN module_expr RPAREN
{ mkmod(Pmod_apply($1, $3)) }
+ | module_expr LPAREN module_expr error
+ { unclosed "(" 2 ")" 4 }
| LPAREN module_expr COLON module_type RPAREN
{ mkmod(Pmod_constraint($2, $4)) }
+ | LPAREN module_expr COLON module_type error
+ { unclosed "(" 1 ")" 5 }
| LPAREN module_expr RPAREN
{ $2 }
+ | LPAREN module_expr error
+ { unclosed "(" 1 ")" 3 }
;
structure:
structure_tail { $1 }
@@ -317,6 +329,8 @@ structure_item:
{ mkstr(Pstr_open $2) }
| CLASS class_list END
{ mkstr(Pstr_class (List.rev $2)) }
+ | CLASS class_list error
+ { unclosed "class" 1 "end" 3 }
;
module_binding:
EQUAL module_expr
@@ -334,6 +348,8 @@ module_type:
{ mkmty(Pmty_ident $1) }
| SIG signature END
{ mkmty(Pmty_signature(List.rev $2)) }
+ | SIG signature error
+ { unclosed "sig" 1 "end" 3 }
| FUNCTOR LPAREN UIDENT COLON module_type RPAREN MINUSGREATER module_type
%prec prec_fun
{ mkmty(Pmty_functor($3, $5, $8)) }
@@ -341,6 +357,8 @@ module_type:
{ mkmty(Pmty_with($1, List.rev $3)) }
| LPAREN module_type RPAREN
{ $2 }
+ | LPAREN module_type error
+ { unclosed "(" 1 ")" 3 }
;
signature:
/* empty */ { [] }
@@ -391,6 +409,8 @@ expr:
{ mkexp(Pexp_apply($1, List.rev $2)) }
| LET rec_flag let_bindings IN seq_expr %prec prec_let
{ mkexp(Pexp_let($2, List.rev $3, $5)) }
+ | LET rec_flag let_bindings error %prec prec_let
+ { unclosed "let" 1 "in" 4 }
| PARSER opt_pat opt_bar parser_cases %prec prec_fun
{ Pstream.cparser ($2, List.rev $4) }
| FUNCTION opt_bar match_cases %prec prec_fun
@@ -403,6 +423,8 @@ expr:
{ mkexp(Pexp_apply(Pstream.cparser ($5, List.rev $7), [$2])) }
| TRY seq_expr WITH opt_bar match_cases %prec prec_try
{ mkexp(Pexp_try($2, List.rev $5)) }
+ | TRY seq_expr error %prec prec_try
+ { unclosed "try" 1 "with" 3 }
| expr_comma_list
{ mkexp(Pexp_tuple(List.rev $1)) }
| constr_longident simple_expr %prec prec_constr_appl
@@ -413,8 +435,12 @@ expr:
{ mkexp(Pexp_ifthenelse($2, $4, None)) }
| WHILE seq_expr DO seq_expr DONE
{ mkexp(Pexp_while($2, $4)) }
+ | WHILE seq_expr DO seq_expr error
+ { unclosed "while" 1 "done" 5 }
| FOR val_ident EQUAL seq_expr direction_flag seq_expr DO seq_expr DONE
{ mkexp(Pexp_for($2, $4, $6, $5, $8)) }
+ | FOR val_ident EQUAL seq_expr direction_flag seq_expr DO seq_expr error
+ { unclosed "for" 1 "done" 9 }
| expr COLONCOLON expr
{ mkexp(Pexp_construct(Lident "::", Some(mkexp(Pexp_tuple[$1;$3])), false)) }
| expr INFIXOP0 expr
@@ -471,30 +497,48 @@ simple_expr:
{ mkexp(Pexp_construct($1, None, false)) }
| LPAREN seq_expr RPAREN
{ $2 }
+ | LPAREN seq_expr error
+ { unclosed "(" 1 ")" 3 }
| BEGIN seq_expr END
{ $2 }
+ | BEGIN seq_expr error
+ { unclosed "begin" 1 "end" 3 }
| LPAREN seq_expr type_constraint RPAREN
{ let (t, t') = $3 in mkexp(Pexp_constraint($2, t, t')) }
+ | LPAREN seq_expr type_constraint error
+ { unclosed "(" 1 ")" 4 }
| simple_expr DOT label_longident
{ mkexp(Pexp_field($1, $3)) }
| simple_expr DOT LPAREN seq_expr RPAREN
{ mkexp(Pexp_apply(mkexp(Pexp_ident(array_function "Array" "get")),
[$1; $4])) }
+ | simple_expr DOT LPAREN seq_expr error
+ { unclosed "(" 3 ")" 5 }
| simple_expr DOT LBRACKET seq_expr RBRACKET
{ mkexp(Pexp_apply(mkexp(Pexp_ident(array_function "String" "get")),
[$1; $4])) }
+ | simple_expr DOT LBRACKET seq_expr error
+ { unclosed "[" 3 "]" 5 }
| LBRACE lbl_expr_list opt_semi RBRACE
{ mkexp(Pexp_record(List.rev $2)) }
+ | LBRACE lbl_expr_list opt_semi error
+ { unclosed "{" 1 "}" 4 }
| LBRACKETLESS stream_expr opt_semi GREATERRBRACKET
{ Pstream.cstream (List.rev $2) }
+ | LBRACKETLESS stream_expr opt_semi error
+ { unclosed "[<" 1 ">]" 4 }
| LBRACKETLESS GREATERRBRACKET
{ Pstream.cstream [] }
| LBRACKETBAR expr_semi_list opt_semi BARRBRACKET
{ mkexp(Pexp_array(List.rev $2)) }
+ | LBRACKETBAR expr_semi_list opt_semi error
+ { unclosed "[|" 1 "|]" 4 }
| LBRACKETBAR BARRBRACKET
{ mkexp(Pexp_array []) }
| LBRACKET expr_semi_list opt_semi RBRACKET
{ mklistexp(List.rev $2) }
+ | LBRACKET expr_semi_list opt_semi error
+ { unclosed "[" 1 "]" 4 }
| PREFIXOP simple_expr
{ mkexp(Pexp_apply(mkoperator $1 1, [$2])) }
| simple_expr SHARP label
@@ -503,6 +547,8 @@ simple_expr:
{ mkexp(Pexp_new($2)) }
| LBRACELESS label_expr_list opt_semi GREATERRBRACE
{ mkexp(Pexp_override(List.rev $2)) }
+ | LBRACELESS label_expr_list opt_semi error
+ { unclosed "{<" 1 ">}" 4 }
| LBRACELESS GREATERRBRACE
{ mkexp(Pexp_override []) }
| LPAREN SHARP label RPAREN
@@ -541,6 +587,8 @@ parser_case:
LBRACKETLESS stream_pattern opt_semi GREATERRBRACKET opt_pat
MINUSGREATER seq_expr
{ (List.rev $2, $5, $7) }
+ | LBRACKETLESS stream_pattern opt_semi error
+ { unclosed "[<" 1 ">]" 4 }
| LBRACKETLESS GREATERRBRACKET opt_pat MINUSGREATER seq_expr
{ ([], $3, $5) }
;
@@ -642,12 +690,20 @@ simple_pattern:
{ mkpat(Ppat_construct($1, None, false)) }
| LBRACE lbl_pattern_list opt_semi RBRACE
{ mkpat(Ppat_record(List.rev $2)) }
+ | LBRACE lbl_pattern_list opt_semi error
+ { unclosed "{" 1 "}" 4 }
| LBRACKET pattern_semi_list opt_semi RBRACKET
{ mklistpat(List.rev $2) }
+ | LBRACKET pattern_semi_list opt_semi error
+ { unclosed "{" 1 "}" 4 }
| LPAREN pattern RPAREN
{ $2 }
+ | LPAREN pattern error
+ { unclosed "(" 1 ")" 3 }
| LPAREN pattern COLON core_type RPAREN
{ mkpat(Ppat_constraint($2, $4)) }
+ | LPAREN pattern COLON core_type error
+ { unclosed "(" 1 ")" 5 }
;
pattern_comma_list:
diff --git a/parsing/syntaxerr.ml b/parsing/syntaxerr.ml
new file mode 100644
index 000000000..6b87819b0
--- /dev/null
+++ b/parsing/syntaxerr.ml
@@ -0,0 +1,47 @@
+(***********************************************************************)
+(* *)
+(* Objective Caml *)
+(* *)
+(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1997 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Auxiliary type for reporting syntax errors *)
+
+open Format
+
+type error =
+ Unclosed of Location.t * string * Location.t * string
+ | Other of Location.t
+
+exception Error of error
+
+let report_error = function
+ Unclosed(opening_loc, opening, closing_loc, closing) ->
+ if String.length !Location.input_name > 0 then begin
+ Location.print closing_loc;
+ print_string "Syntax error: missing '";
+ print_string closing;
+ print_string "'"; force_newline();
+ Location.print opening_loc;
+ print_string "This is the location of the unmatched '";
+ print_string opening;
+ print_string "'"
+ end else begin
+ Location.print opening_loc;
+ print_string "Syntax error: this '";
+ print_string opening;
+ print_string "' has no matching '";
+ print_string closing;
+ print_string "'"
+ end
+ | Other loc ->
+ Location.print loc;
+ print_string "Syntax error"
+
+
diff --git a/parsing/syntaxerr.mli b/parsing/syntaxerr.mli
new file mode 100644
index 000000000..dd69c8551
--- /dev/null
+++ b/parsing/syntaxerr.mli
@@ -0,0 +1,22 @@
+(***********************************************************************)
+(* *)
+(* Objective Caml *)
+(* *)
+(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1997 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Auxiliary type for reporting syntax errors *)
+
+type error =
+ Unclosed of Location.t * string * Location.t * string
+ | Other of Location.t
+
+exception Error of error
+
+val report_error: error -> unit
diff --git a/tools/Makefile b/tools/Makefile
index 017738958..3dc8800b8 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -35,7 +35,7 @@ beforedepend:: ocamldep.ml
CSLPROF=ocamlprof.cmo
CSLPROF_IMPORTS=misc.cmo config.cmo clflags.cmo terminfo.cmo \
linenum.cmo location.cmo longident.cmo pstream.cmo \
- parser.cmo lexer.cmo parse.cmo
+ syntaxerr.cmo parser.cmo lexer.cmo parse.cmo
ocamlprof: $(CSLPROF) profiling.cmo
$(CAMLC) $(LINKFLAGS) -o ocamlprof $(CSLPROF_IMPORTS) $(CSLPROF)
diff --git a/tools/Makefile.Mac b/tools/Makefile.Mac
index 154901a84..19f8647b2 100644
--- a/tools/Makefile.Mac
+++ b/tools/Makefile.Mac
@@ -33,7 +33,7 @@ beforedepend ÄÄ ocamldep
#CSLPROF = ocamlprof.cmo
#CSLPROF_IMPORTS = misc.cmo config.cmo clflags.cmo terminfo.cmo ¶
# linenum.cmo location.cmo longident.cmo pstream.cmo ¶
-# parser.cmo lexer.cmo parse.cmo
+# syntaxerr.cmo parser.cmo lexer.cmo parse.cmo
#
#ocamlprof Ä {CSLPROF} profiling.cmo
# {CAMLC} {LINKFLAGS} -o ocamlprof {CSLPROF_IMPORTS} {CSLPROF}
diff --git a/tools/Makefile.nt b/tools/Makefile.nt
index 135e42792..cf3a42d81 100644
--- a/tools/Makefile.nt
+++ b/tools/Makefile.nt
@@ -35,7 +35,7 @@ beforedepend:: ocamldep.ml
CSLPROF=ocamlprof.cmo
CSLPROF_IMPORTS=misc.cmo config.cmo clflags.cmo terminfo.cmo \
linenum.cmo location.cmo longident.cmo pstream.cmo \
- parser.cmo lexer.cmo parse.cmo
+ syntaxerr.cmo parser.cmo lexer.cmo parse.cmo
ocamlprof: $(CSLPROF) profiling.cmo
$(CAMLC) $(LINKFLAGS) -o ocamlprof $(CSLPROF_IMPORTS) $(CSLPROF)
diff --git a/tools/ocamlprof.ml b/tools/ocamlprof.ml
index a5ee31f5a..7011e3f97 100644
--- a/tools/ocamlprof.ml
+++ b/tools/ocamlprof.ml
@@ -376,9 +376,8 @@ let main () =
Lexer.Error(err, start, stop) ->
Location.print {loc_start = start; loc_end = stop};
Lexer.report_error err
- | Parse.Error(start, stop) ->
- Location.print {loc_start = start; loc_end = stop};
- print_string "Syntax error"
+ | Syntaxerr.Error err ->
+ Syntaxerr.report_error err
| Profiler msg ->
print_string msg
| Inversion(pos, next) ->