summaryrefslogtreecommitdiffstats
path: root/parsing/parser.mly
diff options
context:
space:
mode:
Diffstat (limited to 'parsing/parser.mly')
-rw-r--r--parsing/parser.mly175
1 files changed, 101 insertions, 74 deletions
diff --git a/parsing/parser.mly b/parsing/parser.mly
index 4348d733a..d6dabc057 100644
--- a/parsing/parser.mly
+++ b/parsing/parser.mly
@@ -50,7 +50,7 @@ let mkoperator name pos =
not to instrument them.
Every grammar rule that generates an element with a location must
- make exaclty one non-ghost element, the topmost one.
+ make exactly one non-ghost element, the topmost one.
*)
let ghexp d = { pexp_desc = d; pexp_loc = symbol_gloc () };;
let ghpat d = { ppat_desc = d; ppat_loc = symbol_gloc () };;
@@ -271,34 +271,64 @@ let bigarray_set arr arg newval =
%token WHILE
%token WITH
-/* Precedences and associativities. Lower precedences come first. */
-
-%right prec_let /* let ... in ... */
-%right prec_type_def /* = in type definitions */
-%right SEMI /* e1; e2 (sequence) */
-%right prec_fun prec_match prec_try /* match ... with ... */
-%right prec_list /* e1; e2 (list, array, record) */
-%right prec_if /* if ... then ... else ... */
-%right COLONEQUAL LESSMINUS /* assignments */
-%left AS /* as in patterns */
-%left BAR /* | in patterns */
-%nonassoc p_comma_list /* must be lower than COMMA */
-%left COMMA /* , in expressions, patterns, types */
-%right MINUSGREATER /* -> in type expressions */
-%right OR BARBAR /* or */
-%right AMPERSAND AMPERAMPER /* & */
-%left INFIXOP0 EQUAL LESS GREATER /* = < > etc */
-%right INFIXOP1 /* @ ^ etc */
-%right COLONCOLON /* :: */
-%left INFIXOP2 PLUS MINUS MINUSDOT /* + - */
-%left INFIXOP3 STAR /* * / */
-%right INFIXOP4 /* ** */
-%right prec_unary_minus /* - unary */
-%left prec_appl /* function application */
-%right prec_constr_appl /* constructor application */
-%right SHARP /* method call */
-%left DOT /* record access, array access */
-%right PREFIXOP /* ! */
+/* Precedences and associativities.
+
+Tokens and rules have precedences. A reduce/reduce conflict is resolved
+by comparing the precedences of the two rules. A shift/reduce conflict
+is resolved by comparing the precedence of the token to be shifted with
+the rule to be reduced.
+
+By default, a rule has the precedence of its rightmost terminal (if any).
+
+When there is a shift/reduce conflict between a rule and a token that
+have the same precedence, it is resolved using the associativity:
+if the token is left-associative, the parser will reduce; if
+right-associative, the parser will shift; if non-associative,
+the parser will declare a syntax error.
+
+We will only use associativities with operators of the kind x * x -> x
+for example, in the rules of the form expr: expr BINOP expr
+in all other cases, we define two precedences if needed to resolve
+conflicts.
+
+The precedences must be listed from low to high.
+*/
+
+%nonassoc IN
+%nonassoc below_SEMI
+%nonassoc SEMI /* below EQUAL ({lbl=...; lbl=...}) */
+%nonassoc LET /* above SEMI ( ...; let ... in ...) */
+%nonassoc below_WITH
+%nonassoc FUNCTION WITH /* below BAR (match ... with ...) */
+%nonassoc THEN /* below ELSE (if ... then ...) */
+%nonassoc ELSE /* (if ... then ... else ...) */
+%nonassoc LESSMINUS /* below COLONEQUAL (lbl <- x := e) */
+%right COLONEQUAL /* expr (e := e := e) */
+%nonassoc AS
+%left BAR /* pattern (p|p|p) */
+%nonassoc below_COMMA
+%left COMMA /* expr/expr_comma_list (e,e,e) */
+%right MINUSGREATER /* core_type2 (t -> t -> t) */
+%right OR BARBAR /* expr (e || e || e) */
+%right AMPERSAND AMPERAMPER /* expr (e && e && e) */
+%nonassoc below_EQUAL
+%left INFIXOP0 EQUAL LESS GREATER /* expr (e OP e OP e) */
+%right INFIXOP1 /* expr (e OP e OP e) */
+%right COLONCOLON /* expr (e :: e :: e) */
+%left INFIXOP2 PLUS MINUS MINUSDOT /* expr (e OP e OP e) */
+%left INFIXOP3 STAR /* expr (e OP e OP e) */
+%right INFIXOP4 /* expr (e OP e OP e) */
+%nonassoc prec_unary_minus /* unary - */
+%nonassoc prec_constant_constructor /* cf. simple_expr (C versus C x) */
+%nonassoc prec_constr_appl /* above AS BAR COLONCOLON COMMA */
+%nonassoc below_SHARP
+%nonassoc SHARP /* simple_expr/toplevel_directive */
+%nonassoc below_DOT
+%nonassoc DOT
+/* Finally, the first tokens of simple_expr are above everything else. */
+%nonassoc BACKQUOTE BEGIN CHAR FALSE FLOAT INT LBRACE LBRACELESS LBRACKET
+ LBRACKETBAR LIDENT LPAREN NEW PREFIXOP STRING TRUE UIDENT
+
/* Entry points */
@@ -355,7 +385,6 @@ module_expr:
| 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)) }
@@ -426,7 +455,7 @@ module_type:
| SIG signature error
{ unclosed "sig" 1 "end" 3 }
| FUNCTOR LPAREN UIDENT COLON module_type RPAREN MINUSGREATER module_type
- %prec prec_fun
+ %prec below_WITH
{ mkmty(Pmty_functor($3, $5, $8)) }
| module_type WITH with_constraints
{ mkmty(Pmty_with($1, List.rev $3)) }
@@ -683,7 +712,7 @@ class_type_declaration:
/* Core expressions */
seq_expr:
- | expr %prec SEMI { $1 }
+ | expr %prec below_SEMI { $1 }
| expr SEMI { $1 }
| expr SEMI seq_expr { mkexp(Pexp_sequence($1, $3)) }
;
@@ -728,33 +757,33 @@ let_pattern:
{ mkpat(Ppat_constraint($1, $3)) }
;
expr:
- simple_expr %prec SHARP
+ simple_expr %prec below_SHARP
{ $1 }
- | simple_expr simple_labeled_expr_list %prec prec_appl
+ | simple_expr simple_labeled_expr_list
{ mkexp(Pexp_apply($1, List.rev $2)) }
- | LET rec_flag let_bindings IN seq_expr %prec prec_let
+ | LET rec_flag let_bindings IN seq_expr
{ mkexp(Pexp_let($2, List.rev $3, $5)) }
- | LET MODULE UIDENT module_binding IN seq_expr %prec prec_let
+ | LET MODULE UIDENT module_binding IN seq_expr
{ mkexp(Pexp_letmodule($3, $4, $6)) }
- | FUNCTION opt_bar match_cases %prec prec_fun
+ | FUNCTION opt_bar match_cases
{ mkexp(Pexp_function("", None, List.rev $3)) }
- | FUN labeled_simple_pattern fun_def %prec prec_fun
+ | FUN labeled_simple_pattern fun_def
{ let (l,o,p) = $2 in mkexp(Pexp_function(l, o, [p, $3])) }
- | MATCH seq_expr WITH opt_bar match_cases %prec prec_match
+ | MATCH seq_expr WITH opt_bar match_cases
{ mkexp(Pexp_match($2, List.rev $5)) }
- | TRY seq_expr WITH opt_bar match_cases %prec prec_try
+ | TRY seq_expr WITH opt_bar match_cases
{ mkexp(Pexp_try($2, List.rev $5)) }
- | TRY seq_expr WITH error %prec prec_try
+ | TRY seq_expr WITH error
{ syntax_error() }
- | expr_comma_list %prec p_comma_list
+ | expr_comma_list %prec below_COMMA
{ mkexp(Pexp_tuple(List.rev $1)) }
- | constr_longident simple_expr %prec prec_constr_appl
+ | constr_longident simple_expr %prec below_SHARP
{ mkexp(Pexp_construct($1, Some $2, false)) }
- | name_tag simple_expr %prec prec_constr_appl
+ | name_tag simple_expr %prec below_SHARP
{ mkexp(Pexp_variant($1, Some $2)) }
- | IF seq_expr THEN expr ELSE expr %prec prec_if
+ | IF seq_expr THEN expr ELSE expr
{ mkexp(Pexp_ifthenelse($2, $4, Some $6)) }
- | IF seq_expr THEN expr %prec prec_if
+ | IF seq_expr THEN expr
{ mkexp(Pexp_ifthenelse($2, $4, None)) }
| WHILE seq_expr DO seq_expr DONE
{ mkexp(Pexp_while($2, $4)) }
@@ -822,9 +851,9 @@ expr:
loc_ghost = false } },
List.rev $4)) }
*/
- | ASSERT simple_expr %prec prec_appl
+ | ASSERT simple_expr %prec below_SHARP
{ mkassert $2 }
- | LAZY simple_expr %prec prec_appl
+ | LAZY simple_expr %prec below_SHARP
{ mkexp (Pexp_lazy ($2)) }
;
simple_expr:
@@ -832,9 +861,9 @@ simple_expr:
{ mkexp(Pexp_ident $1) }
| constant
{ mkexp(Pexp_constant $1) }
- | constr_longident %prec prec_constr_appl
+ | constr_longident %prec prec_constant_constructor
{ mkexp(Pexp_construct($1, None, false)) }
- | name_tag
+ | name_tag %prec prec_constant_constructor
{ mkexp(Pexp_variant($1, None)) }
| LPAREN seq_expr RPAREN
{ $2 }
@@ -898,19 +927,19 @@ simple_labeled_expr_list:
{ $2 :: $1 }
;
labeled_simple_expr:
- simple_expr %prec SHARP
+ simple_expr %prec below_SHARP
{ ("", $1) }
| label_expr
{ $1 }
;
label_expr:
- LABEL simple_expr %prec SHARP
+ LABEL simple_expr %prec below_SHARP
{ ($1, $2) }
| TILDE label_ident
{ $2 }
| QUESTION label_ident
{ ("?" ^ fst $2, snd $2) }
- | OPTLABEL simple_expr %prec SHARP
+ | OPTLABEL simple_expr %prec below_SHARP
{ ("?" ^ $1, $2) }
;
label_ident:
@@ -931,13 +960,13 @@ let_bindings:
let_binding:
val_ident fun_binding
{ ({ppat_desc = Ppat_var $1; ppat_loc = rhs_loc 1}, $2) }
- | pattern EQUAL seq_expr %prec prec_let
+ | pattern EQUAL seq_expr
{ ($1, $3) }
;
fun_binding:
- EQUAL seq_expr %prec prec_let
+ EQUAL seq_expr
{ $2 }
- | type_constraint EQUAL seq_expr %prec prec_let
+ | type_constraint EQUAL seq_expr
{ let (t, t') = $1 in mkexp(Pexp_constraint($3, t, t')) }
| labeled_simple_pattern fun_binding
{ let (l, o, p) = $1 in mkexp(Pexp_function(l, o, [p, $2])) }
@@ -964,20 +993,20 @@ record_expr:
| lbl_expr_list opt_semi { (None, List.rev $1) }
;
lbl_expr_list:
- label_longident EQUAL expr %prec prec_list
+ label_longident EQUAL expr
{ [$1,$3] }
- | lbl_expr_list SEMI label_longident EQUAL expr %prec prec_list
+ | lbl_expr_list SEMI label_longident EQUAL expr
{ ($3, $5) :: $1 }
;
field_expr_list:
- label EQUAL expr %prec prec_list
+ label EQUAL expr
{ [$1,$3] }
- | field_expr_list SEMI label EQUAL expr %prec prec_list
+ | field_expr_list SEMI label EQUAL expr
{ ($3, $5) :: $1 }
;
expr_semi_list:
- expr %prec prec_list { [$1] }
- | expr_semi_list SEMI expr %prec prec_list { $3 :: $1 }
+ expr { [$1] }
+ | expr_semi_list SEMI expr { $3 :: $1 }
;
type_constraint:
COLON core_type { (Some $2, None) }
@@ -994,7 +1023,7 @@ pattern:
{ $1 }
| pattern AS val_ident
{ mkpat(Ppat_alias($1, $3)) }
- | pattern_comma_list %prec p_comma_list
+ | pattern_comma_list %prec below_COMMA
{ mkpat(Ppat_tuple(List.rev $1)) }
| constr_longident pattern %prec prec_constr_appl
{ mkpat(Ppat_construct($1, Some $2, false)) }
@@ -1007,7 +1036,7 @@ pattern:
{ mkpat(Ppat_or($1, $3)) }
;
simple_pattern:
- val_ident %prec prec_let
+ val_ident %prec below_EQUAL
{ mkpat(Ppat_var $1) }
| UNDERSCORE
{ mkpat(Ppat_any) }
@@ -1089,7 +1118,7 @@ constraints:
type_kind:
/*empty*/
{ (Ptype_abstract, None) }
- | EQUAL core_type %prec prec_type_def
+ | EQUAL core_type
{ (Ptype_abstract, Some $2) }
| EQUAL constructor_declarations
{ (Ptype_variant(List.rev $2), None) }
@@ -1097,10 +1126,9 @@ type_kind:
{ (Ptype_variant(List.rev $3), None) }
| EQUAL LBRACE label_declarations opt_semi RBRACE
{ (Ptype_record(List.rev $3), None) }
- | EQUAL core_type EQUAL opt_bar constructor_declarations %prec prec_type_def
+ | EQUAL core_type EQUAL opt_bar constructor_declarations
{ (Ptype_variant(List.rev $5), Some $2) }
| EQUAL core_type EQUAL LBRACE label_declarations opt_semi RBRACE
- %prec prec_type_def
{ (Ptype_record(List.rev $5), Some $2) }
;
type_parameters:
@@ -1186,9 +1214,9 @@ core_type2:
;
simple_core_type:
- simple_core_type2 %prec SHARP
+ simple_core_type2 %prec below_SHARP
{ $1 }
- | LPAREN core_type_comma_list RPAREN %prec SHARP /* FIXME duh ?? */
+ | LPAREN core_type_comma_list RPAREN %prec below_SHARP
{ match $2 with [sty] -> sty | _ -> raise Parse_error }
;
simple_core_type2:
@@ -1198,9 +1226,9 @@ simple_core_type2:
{ mktyp(Ptyp_any) }
| type_longident
{ mktyp(Ptyp_constr($1, [])) }
- | simple_core_type2 type_longident %prec prec_constr_appl
+ | simple_core_type2 type_longident
{ mktyp(Ptyp_constr($2, [$1])) }
- | LPAREN core_type_comma_list RPAREN type_longident %prec prec_constr_appl
+ | LPAREN core_type_comma_list RPAREN type_longident
{ mktyp(Ptyp_constr($4, List.rev $2)) }
| LESS meth_list GREATER
{ mktyp(Ptyp_object $2) }
@@ -1208,10 +1236,9 @@ simple_core_type2:
{ mktyp(Ptyp_object []) }
| SHARP class_longident opt_present
{ mktyp(Ptyp_class($2, [], $3)) }
- | simple_core_type2 SHARP class_longident opt_present %prec prec_constr_appl
+ | simple_core_type2 SHARP class_longident opt_present
{ mktyp(Ptyp_class($3, [$1], $4)) }
| LPAREN core_type_comma_list RPAREN SHARP class_longident opt_present
- %prec prec_constr_appl
{ mktyp(Ptyp_class($5, List.rev $2, $6)) }
| LBRACKET tag_field RBRACKET
{ mktyp(Ptyp_variant([$2], true, None)) }
@@ -1347,7 +1374,7 @@ val_longident:
| mod_longident DOT val_ident { Ldot($1, $3) }
;
constr_longident:
- mod_longident %prec prec_constr_appl { $1 }
+ mod_longident %prec below_DOT { $1 }
| LBRACKET RBRACKET { Lident "[]" }
| LPAREN RPAREN { Lident "()" }
| FALSE { Lident "false" }