Commit f687555e by POTTIER Francois

[InspectionTableInterpreter.Make] now has access to the basic tables

and the inspection tables. The sub-module [Shared] in the generated
code is no longer necessary.
Defined [n2i] in [TableInterpreter] (another unsafe cast!).
Used it to implement [nullable], which is now exposed to the user.
parent 0a44f5e6
......@@ -188,6 +188,12 @@ module type INSPECTION = sig
val items: 'a lr1state -> item list
(* [nullable nt] tells whether the non-terminal symbol [nt] is nullable.
That is, it is true if and only if this symbol produces the empty
word [epsilon]. *)
val nullable: 'a nonterminal -> bool
end
(* This signature combines the incremental API and the inspection API. *)
......
......@@ -21,9 +21,8 @@ module type TABLES = sig
val terminal: int -> xsymbol
val nonterminal: int -> xsymbol
(* The left-hand side of every production. (Same as in [TableFormat.TABLES].) *)
val lhs: PackedIntArray.t
(* The left-hand side of every production already appears in the
signature [TableFormat.TABLES], so we need not repeat it here. *)
(* The right-hand side of every production. This a linearized array
of arrays of integers, whose [data] and [entry] components have
......
......@@ -27,10 +27,11 @@ end
(* The code functor. *)
module Make (
T : InspectionTableFormat.TABLES
with type 'a lr1state = int
) = struct
module Make
(B : TableFormat.TABLES)
(T : InspectionTableFormat.TABLES
with type 'a lr1state = int)
= struct
(* Including [T] is an easy way of inheriting the definitions of the types
[symbol] and [xsymbol]. *)
......@@ -62,8 +63,19 @@ module Make (
else
T.nonterminal symbol
(* The function [incoming_symbol] goes through the tables [lr0_core] and
[lr0_incoming]. This yields a representation of type [xsymbol], out of
(* This auxiliary function converts a nonterminal symbol to its integer
code. For speed and for convenience, we use an unsafe type cast. This
relies on the fact that the data constructors of the [nonterminal] GADT
are declared in an order that reflects their internal code. We add
[start] to account for the presence of the start symbols. *)
let n2i (nt : 'a T.nonterminal) : int =
let answer = B.start + Obj.magic nt in
assert (T.nonterminal answer = X (N nt)); (* TEMPORARY roundtrip *)
answer
(* The function [incoming_symbol] goes through the tables [T.lr0_core] and
[T.lr0_incoming]. This yields a representation of type [xsymbol], out of
which we strip the [X] quantifier, so as to get a naked symbol. This last
step is ill-typed and potentially dangerous. It is safe only because this
function is used at type ['a lr1state -> 'a symbol], which forces an
......@@ -76,20 +88,20 @@ module Make (
| T.X symbol ->
Obj.magic symbol
(* The function [lhs] reads the table [lhs] and uses [T.nonterminal]
(* The function [lhs] reads the table [B.lhs] and uses [T.nonterminal]
to decode the symbol. *)
let lhs prod =
T.nonterminal (PackedIntArray.get T.lhs prod)
T.nonterminal (PackedIntArray.get B.lhs prod)
(* The function [rhs] reads the table [rhs] and uses [decode_symbol]
(* The function [rhs] reads the table [T.rhs] and uses [decode_symbol]
to decode the symbol. *)
let rhs prod =
List.map decode_symbol (read_packed_linearized T.rhs prod)
(* The function [items] maps the LR(1) state [s] to its LR(0) core,
then uses [core] as an index into the table [lr0_items]. The
then uses [core] as an index into the table [T.lr0_items]. The
items are then decoded by the function [export] below, which is
essentially a copy of [Item.export]. *)
......@@ -102,7 +114,14 @@ module Make (
let items s =
(* Map [s] to its LR(0) core. *)
let core = PackedIntArray.get T.lr0_core s in
(* Now use [core] to look up the [lr0_items] table. *)
(* Now use [core] to look up the table [T.lr0_items]. *)
List.map export (read_packed_linearized T.lr0_items core)
(* The function [nullable] maps the nonterminal symbol [nt] to its
integer code, which it uses to look up the array [T.nullable].
This yields 0 or 1, which we map back to a Boolean result. *)
let nullable nt =
PackedIntArray.get1 T.nullable (n2i nt) = 1
end
......@@ -17,8 +17,10 @@ end)
constructs the inspection API on top of the inspection tables described in
[InspectionTableFormat]. *)
module Make (T : InspectionTableFormat.TABLES
with type 'a lr1state = int)
module Make
(B : TableFormat.TABLES)
(T : InspectionTableFormat.TABLES
with type 'a lr1state = int)
: IncrementalEngine.INSPECTION
with type 'a terminal := 'a T.terminal
......
......@@ -30,7 +30,8 @@ let nonterminalgadtdef grammar =
to respect the internal ordering (as determined by [nonterminals]
in [UnparameterizedSyntax]) of the nonterminal symbols. This may
be exploited in the table back-end to allow an unsafe conversion
of a data constructor to an integer code. *)
of a data constructor to an integer code. See [n2i] in
[InspectionTableInterpreter]. *)
"The indexed type of nonterminal symbols.",
List.map (fun nt ->
......
......@@ -72,9 +72,6 @@ let tables =
let symbols =
"Symbols"
let shared =
"Shared"
let ti =
"TI"
......@@ -961,22 +958,11 @@ let program =
(* Define the tables. *)
SIModuleDef (shared,
MStruct [
SIValDefs (false, [
lhs;
])
]
) ::
SIModuleDef (tables,
MStruct [
(* The internal sub-module [basics] contains the definitions of the
exception [Error] and of the type [token]. *)
SIInclude (MVar basics);
(* The internal sub-module [shared] contains the tables that are
used both in normal mode and in [--inspection] mode. *)
SIInclude (MVar shared);
(* This is a non-recursive definition, so none of the names
defined here are visible in the semantic actions. *)
......@@ -988,7 +974,7 @@ let program =
error;
start_def;
action;
(* [lhs] is part of [shared] *)
lhs;
goto;
semantic_action;
trace;
......@@ -1018,7 +1004,7 @@ let program =
SIInclude (MVar symbols) ::
SIInclude (MApp (MVar make_inspection, MStruct (
SIInclude (MApp (MApp (MVar make_inspection, MVar tables), MStruct (
(* This module must satisfy [InspectionTableFormat.TABLES]. *)
(* [lr1state] *)
SIInclude (MVar ti) ::
......@@ -1028,8 +1014,6 @@ let program =
in terms of the types [terminal] and [nonterminal]. This saves
us the trouble of generating these definitions. *)
SIInclude (MApp (MVar make_symbol, MVar symbols)) ::
(* [lhs] *)
SIInclude (MVar shared) ::
SIValDefs (false,
terminal() ::
nonterminal() ::
......
......@@ -94,8 +94,10 @@ module type TABLES = sig
val goto: PackedIntArray.t * PackedIntArray.t
(* The number of start productions. A production [prod] is a start production
if and only if [prod < start] holds. *)
(* The number of start productions. A production [prod] is a start
production if and only if [prod < start] holds. This is also the
number of start symbols. A nonterminal symbol [nt] is a start
symbol if and only if [nt < start] holds. *)
val start: int
......
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