Commit ae92904a authored by POTTIER Francois's avatar POTTIER Francois

Optimized the hoisting of anonymous rules out of parameterized rules

by removing redundant (unused) parameters.
parent 36de77c3
2016/05/18:
Anonymous rules now work also when used inside a parameterized rule.
(This did not work until now.)
(This did not work until now.) When an anonymous rule is hoisted out
of a parameterized rule, it may itself become parameterized. Menhir
parameterizes it only over the parameters that it actually needs.
2016/05/04:
In the Coq backend, split the largest definitions into smaller
......
......@@ -2,7 +2,7 @@
anonymous rules nested in anonymous rules. */
%token<int> A B C D EOF
%start<int list> phrase
%start<int> phrase
%%
......
......@@ -7,7 +7,7 @@ recommend switching on --infer in order to avoid obscure type error messages.
%token <int> B
%token <int> A
%type <int list> phrase
%type <int> phrase
%%
foo:
......
Warning: you are using the standard library and/or the %inline keyword. We
recommend switching on --infer in order to avoid obscure type error messages.
/* Test of the new anonymous rule syntax, inside
a parameterized definition, whose parameters
are NOT used by the anonymous rule. */
%{ type ('a, 'b) either = Left of 'a | Right of 'b %}
%token<int> A B C D EOF
%start<(int, int) either> phrase
%start<unit> other
%%
%inline mixed_list(X, Y, Z):
Z
list(
x = X { Left x }
| y = Y { Right y }
) { $1 }
phrase:
xs = mixed_list(A, B, C)
ys = mixed_list(A, B, D)
(* We should obtain only ONE anonymous symbol because
Z is unused in the anonymous rule above. *)
EOF
{ xs @ ys }
other:
seplist(A) EOF {}
(* A list of X's, separated with C's or D's. We should
obtain a definition of a symbol that expands to C or
D and is NOT parameterized over X. *)
seplist(X):
X {}
| X embedded(C {} | D {}) seplist(X) {}
Warning: you are using the standard library and/or the %inline keyword. We
recommend switching on --infer in order to avoid obscure type error messages.
%{ type ('a, 'b) either = Left of 'a | Right of 'b %}
%start other
%start phrase
%token <int> EOF
%token <int> D
%token <int> C
%token <int> B
%token <int> A
%type <unit> other
%type <(int, int) either> phrase
%%
phrase:
_10 = C _20 = list___anonymous_0_A_B__ _11 = D _21 = list___anonymous_0_A_B__ _3 = EOF
{let ys =
let _2 = _21 in
let _1 = _11 in
( _1 )
in
let xs =
let _2 = _20 in
let _1 = _10 in
( _1 )
in
( xs @ ys )}
other:
_1 = seplist_A_ _2 = EOF
{ ()}
seplist_A_:
_1 = A
{ ()}
| _1 = A _2 = embedded___anonymous_1_ _3 = seplist_A_
{ ()}
embedded___anonymous_1_:
_10 = C
{let x =
let _1 = _10 in
()
in
( x )}
| _10 = D
{let x =
let _1 = _10 in
()
in
( x )}
list___anonymous_0_A_B__:
{ ( [] )}
| x0 = A xs = list___anonymous_0_A_B__
{let x =
let x = x0 in
( Left x )
in
( x :: xs )}
| y0 = B xs = list___anonymous_0_A_B__
{let x =
let y = y0 in
( Right y )
in
( x :: xs )}
%%
Warning: you are using the standard library and/or the %inline keyword. We
recommend switching on --infer in order to avoid obscure type error messages.
/* Test of the new anonymous rule syntax, inside
a parameterized definition. */
%{ type ('a, 'b) either = Left of 'a | Right of 'b %}
%token<int> A B C D EOF
%start<(int, int) either> phrase
%%
mixed_list(X, Y):
list(
x = X { Left x }
| y = Y { Right y }
) { $1 }
phrase:
xs = mixed_list(A, B)
ys = mixed_list(C, D)
EOF
{ xs @ ys }
Warning: you are using the standard library and/or the %inline keyword. We
recommend switching on --infer in order to avoid obscure type error messages.
%{ type ('a, 'b) either = Left of 'a | Right of 'b %}
%start phrase
%token <int> EOF
%token <int> D
%token <int> C
%token <int> B
%token <int> A
%type <(int, int) either> phrase
%%
mixed_list_C_D_:
_1 = list___anonymous_0_C_D__
{ ( _1 )}
mixed_list_A_B_:
_1 = list___anonymous_0_A_B__
{ ( _1 )}
phrase:
xs = mixed_list_A_B_ ys = mixed_list_C_D_ _3 = EOF
{ ( xs @ ys )}
list___anonymous_0_C_D__:
{ ( [] )}
| x0 = C xs = list___anonymous_0_C_D__
{let x =
let x = x0 in
( Left x )
in
( x :: xs )}
| y0 = D xs = list___anonymous_0_C_D__
{let x =
let y = y0 in
( Right y )
in
( x :: xs )}
list___anonymous_0_A_B__:
{ ( [] )}
| x0 = A xs = list___anonymous_0_A_B__
{let x =
let x = x0 in
( Left x )
in
( x :: xs )}
| y0 = B xs = list___anonymous_0_A_B__
{let x =
let y = y0 in
( Right y )
in
( x :: xs )}
%%
......@@ -7,6 +7,28 @@ open Syntax
(* ------------------------------------------------------------------------ *)
(* Computing the free names of some syntactic categories. *)
let rec fn_parameter accu p =
(* [p] cannot be [ParameterAnonymous _]. *)
let x, ps = Parameters.unapp p in
let accu = StringSet.add (Positions.value x) accu in
fn_parameters accu ps
and fn_parameters accu ps =
List.fold_left fn_parameter accu ps
let fn_producer accu (_, p) =
fn_parameter accu p
let fn_branch accu branch =
List.fold_left fn_producer accu branch.pr_producers
let fn_branches accu branches =
List.fold_left fn_branch accu branches
(* ------------------------------------------------------------------------ *)
(* This functor makes it easy to share mutable internal state between
the functions that follow. *)
......@@ -42,6 +64,14 @@ let var (symbol : symbol) : parameter =
ParameterVar (Positions.with_pos Positions.dummy symbol)
let anonymous pos (parameters : symbol list) (branches : parameterized_branch list) : parameter =
(* Compute the free symbols of [branches]. They should form a subset
of [parameters], although we have not yet checked this. We create
a definition that is parameterized only over the parameters that
actually occur free in the definition -- i.e., a definition without
useless parameters. This seems important, as (in some situations)
it avoids duplication and leads to fewer states in the automaton. *)
let used = fn_branches StringSet.empty branches in
let parameters = List.filter (fun x -> StringSet.mem x used) parameters in
(* Generate a fresh non-terminal symbol. *)
let symbol = fresh() in
(* Construct its definition. Note that it is implicitly marked %inline. *)
......@@ -57,7 +87,6 @@ let anonymous pos (parameters : symbol list) (branches : parameterized_branch li
rules := rule :: !rules;
(* Return the symbol that stands for it. *)
Parameters.app (Positions.with_pos pos symbol) (List.map var parameters)
(* TEMPORARY should use as few parameters as possible *)
(* ------------------------------------------------------------------------ *)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment