Commit 4cd330ad authored by POTTIER Francois's avatar POTTIER Francois
Browse files

In [Lr0], remove [new_numbering] and expose [Lr1stateAsOrderedType] instead....

In [Lr0], remove [new_numbering] and expose [Lr1stateAsOrderedType] instead. Use this to simplify [Lr1canonical].
parent c7a8c713
......@@ -275,6 +275,23 @@ let incoming_edges (c : node) : node list =
type lr1state =
node * TerminalSet.t array
(* A view of the type [lr1state] as an ordered type. This can be used in
conjuction with [Fix.Memoize], [Fix.Numbering], etc. E.g. a numbering
facility based on this mechanism is able to number 10000 states in
about 0.01s. *)
module Lr1StateAsOrderedType = struct
type t = lr1state
let compare (k1, toksr1) (k2, toksr2) =
let c = k1 - k2 in
if c <> 0 then c
else Generic.compare toksr1 toksr2
(* In principle, we should use [Array.compare TerminalSet.compare],
but the function [Array.compare] does not exist, and we happen
to know that [TerminalSet.compare] is OCaml's generic comparison,
so the whole comparison can be carried using generic comparison. *)
end
(* An encoded LR(1) state can be turned into a concrete representation,
that is, a mapping of items to concrete lookahead sets. *)
......@@ -423,28 +440,6 @@ let subsume ((k1, toksr1) as state1) ((k2, toksr2) as state2) =
in
loop (Array.length toksr1)
(* A memoizer for the type [lr1state]. This code is simple-minded, but its
efficiency is sufficient: 10000 states are numbered in about 0.01s. *)
module M =
Fix.Memoize.ForOrderedType(struct
type t = lr1state
let compare s1 s2 =
let c = core s1 - core s2 in
if c <> 0 then c else compare s1 s2
end)
(* A facility for assigning unique numbers to LR(1) states. *)
let new_numbering () =
let m = ref 0 in
let number : lr1state -> int =
M.memoize (fun (_ : lr1state) -> Misc.postincrement m)
and current () =
!m
in
number, current
(* This function determines whether two (core-equivalent) states are
compatible, according to a criterion that is close to Pager's weak
compatibility criterion.
......
......@@ -59,6 +59,13 @@ val outgoing_symbols: node -> Symbol.t list
type lr1state
(* A view of the type [lr1state] as an ordered type. *)
module Lr1StateAsOrderedType : sig
type t = lr1state
val compare: t -> t -> int
end
(* An encoded LR(1) state can be turned into a concrete representation,
that is, a mapping of items to concrete lookahead sets. *)
......@@ -114,13 +121,6 @@ val compare: lr1state -> lr1state -> int
val subsume: lr1state -> lr1state -> bool
(* A facility for assigning unique numbers to LR(1) states. The call
[new_numbering] returns a pair of functions [number, current], where
[number] maps LR(1) states to unique (freshly assigned) numbers and
[current] returns the next available number. *)
val new_numbering: unit -> (lr1state -> int) * (unit -> int)
(* A slightly modified version of Pager's weak compatibility
criterion. The two states must have the same core. *)
......
......@@ -141,47 +141,28 @@ let mu : lr0state -> P.property =
type node =
int
let (number : lr1state -> node), (current : unit -> node) =
Lr0.new_numbering()
module N =
Fix.Numbering.ForOrderedType(Lr0.Lr1StateAsOrderedType)
(* This yields [N.encode : lr1state -> node]
and [N.current : unit -> node]. *)
let start =
Array.make Lr0.n 0 (* dummy *)
(* TEMPORARY get rid of this array? *)
let n =
let () =
Misc.iteri Lr0.n (fun c ->
start.(c) <- current();
P.iter (fun s -> ignore (number s)) (mu c)
);
current()
let finish c =
if c + 1 < Lr0.n then
start.(c + 1)
else
n
(* -------------------------------------------------------------------------- *)
(* Expose the states of the LR(1) automaton. *)
start.(c) <- N.current();
P.iter (fun s -> ignore (N.encode s)) (mu c)
)
(* Manufacture a dummy state so as to initialize the [state] array. Ouch. *)
let dummy : lr1state =
let _prod, c = ProductionMap.choose Lr0.entry in
Lr0.start c
include N.Done()
(* This defines [n : int],
[encode : lr1state -> node],
[decode : node -> lr1state]. *)
let state : node -> lr1state =
(* Initialize an array of states. *)
let state = Array.make n dummy in
(* Populate this array. *)
Misc.iteri Lr0.n (fun c ->
mu c
|> P.iter (fun s ->
let i = number s in
state.(i) <- s
)
);
(* Provide read-only access to this array. *)
Array.get state
decode
(* -------------------------------------------------------------------------- *)
......@@ -191,7 +172,6 @@ let entry : node ProductionMap.t =
ProductionMap.map (fun (c : Lr0.node) ->
(* Exactly one state in the canonical LR(1) automaton corresponds to the
LR(0) state [c]. *)
assert (start.(c) + 1 = finish c);
start.(c)
) Lr0.entry
......@@ -200,7 +180,7 @@ let entry : node ProductionMap.t =
(* Expose the transitions of the LR(1) automaton. *)
let transition symbol (i : node) : node =
number (Lr0.transition symbol (state i))
encode (Lr0.transition symbol (state i))
let outgoing_symbols (i : node) =
Lr0.outgoing_symbols (Lr0.core (state i))
......
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