Commit 4f4a9807 authored by POTTIER Francois's avatar POTTIER Francois

Integrated the loop on [z] inside [E.query],

instead of leaving it to the caller. This offers more flexibility
to the implementor of [E], and already allows a speed gain (due to
the loop interchange, I think).
parent cdcbb98d
......@@ -817,13 +817,14 @@ module E : sig
quadruple [s, nt, a, z] is new. The symbol [z] cannot be [any]. *)
val register: Lr1.node -> Nonterminal.t -> W.word -> Terminal.t -> bool
(* [query s nt a z] enumerates all words [w] such that, in state [s], the
outgoing edge labeled [nt] can be taken by consuming the word [w], under
the assumption that the next symbol is [z], and the first symbol of the
word [w.z] is [a]. The symbol [a] can be [any]. The symbol [z] cannot be
[any]. *)
val query: Lr1.node -> Nonterminal.t -> Terminal.t -> Terminal.t ->
(W.word -> unit) -> unit
(* [query s nt a otarget] enumerates all words [w] and all real symbols [z]
such that, in state [s], the outgoing edge labeled [nt] can be taken by
consuming the word [w], under the assumption that the next symbol is [z],
and the first symbol of the word [w.z] is [a]. The symbol [a] can be [any].
If the state [otarget] is provided, then only the symbols [z] that cannot
cause an error in this state are listed. *)
val query: Lr1.node -> Nonterminal.t -> Terminal.t -> Lr1.node option ->
(W.word -> Terminal.t -> unit) -> unit
(* [size()] returns the number of edges currently stored in the set. *)
val size: unit -> int
......@@ -879,25 +880,33 @@ end = struct
true
end
let rec query s nt a z f =
assert (Terminal.real z);
let rec query s nt a target f =
if Terminal.equal a any then begin
(* If [a] is [any], we query the table for every real symbol [a].
We can limit ourselves to symbols that do not cause an error
in state [s]. Those that do certainly do not have an entry;
see the assertion in [register] above. *)
foreach_terminal_not_causing_an_error s (fun a ->
query s nt a z f
query s nt a target f
)
end
else begin
let i = index s in
let m = table.(i) in
let key = pack nt a z in
match H.find m key with
| w -> f w
| exception Not_found -> ()
end
else
let foreach =
match target with
| None ->
foreach_terminal
| Some target ->
foreach_terminal_not_causing_an_error target
in
foreach (fun z ->
assert (Terminal.real z);
let i = index s in
let m = table.(i) in
let key = pack nt a z in
match H.find m key with
| w -> f w z
| exception Not_found -> ()
)
let size () =
!count
......@@ -1032,17 +1041,10 @@ let new_fact fact =
However, allowing [z] to be [any] in [E.query], and taking
advantage of this to increase performance, seems difficult. *)
(* Remark by Jacques-Henri Jourdan: we could remove the outer loop
on [z], remove the parameter [z] to [E.query], and let [E.query]
itself enumerate all values of [z]. Potentially this could allow
a more efficient implementation of the data structure [E]. *)
foreach_terminal_not_causing_an_error target (fun z ->
E.query current nt lookahead z (fun w ->
assert (compatible lookahead (W.first w z));
let word = W.append word w in
enqueue child word z
)
E.query current nt lookahead (Some target) (fun w z ->
assert (compatible lookahead (W.first w z));
let word = W.append word w in
enqueue child word z
)
);
......@@ -1225,10 +1227,8 @@ module A = Astar.Make(struct
of the word [w.z'] is [z]. For every [z'] and [w] that
fulfill these requirements, we have an edge to [s', z'],
labeled with the word [w]. *)
foreach_terminal (fun z' ->
E.query s nt z z' (fun w ->
edge w (W.length w) (s', z')
)
E.query s nt z None (fun w z' ->
edge w (W.length w) (s', z')
)
)
......
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