Commit 0a077a78 authored by POTTIER Francois's avatar POTTIER Francois

Added the computation of the minimal length of each nonterminal.

This information is displayed at log level -lg 2.
Changed the display to not include the artificial start symbols.
parent 1eb50c49
(* The natural numbers, completed with [Infinity], and ordered towards
zero (i.e. [Infinity] is [bottom], [Finite 0] is [top]). *)
type t =
| Finite of int
| Infinity
type property =
t
let equal p1 p2 =
match p1, p2 with
| Finite i1, Finite i2 ->
i1 = i2
| Infinity, Infinity ->
true
| _, _ ->
false
let bottom =
Infinity
let is_maximal p =
match p with
| Finite 0 ->
true
| _ ->
false
let min p1 p2 =
match p1, p2 with
| Finite i1, Finite i2 ->
Finite (min i1 i2)
| p, Infinity
| Infinity, p ->
p
let min_lazy p1 p2 =
match p1 with
| Finite 0 ->
p1
| _ ->
min p1 (Lazy.force p2)
let add p1 p2 =
match p1, p2 with
| Finite i1, Finite i2 ->
Finite (i1 + i2)
| _, _ ->
Infinity
let add_lazy p1 p2 =
match p1 with
| Infinity ->
Infinity
| _ ->
add p1 (Lazy.force p2)
let print p =
match p with
| Finite i ->
string_of_int i
| Infinity ->
"infinity"
(* The natural numbers, completed with [Infinity], and ordered towards
zero (i.e. [Infinity] is [bottom], [Finite 0] is [top]). *)
type t =
| Finite of int
| Infinity
include Fix.PROPERTY with type property = t
val min: t -> t -> t
val add: t -> t -> t
val min_lazy: t -> t Lazy.t -> t
val add_lazy: t -> t Lazy.t -> t
val print: t -> string
......@@ -1013,20 +1013,49 @@ let () =
(Printf.sprintf "%s generates the empty language." (Nonterminal.print false nt));
done
(* ------------------------------------------------------------------------ *)
(* For every nonterminal symbol [nt], compute the minimal length of any word
generated by [nt]. This analysis subsumes [NONEMPTY] and [NULLABLE]. Indeed,
[nt] produces a nonempty language if only if the minimal length is finite;
[nt] is nullable if only if the minimal length is zero. *)
(* This analysis is more costly than the [NONEMPTY] and [NULLABLE], so it is
performed only on demand. *)
module MINIMAL =
GenericAnalysis
(CompletedNat)
(struct
open CompletedNat
(* A terminal symbol has length 1. *)
let terminal _ = Finite 1
(* The length of an alternative is the minimum length of any branch. *)
let disjunction = min_lazy
(* The length of a sequence is the sum of the lengths of the members. *)
let conjunction _ = add_lazy
(* The epsilon sequence has length 0. *)
let epsilon = Finite 0
end)
(* ------------------------------------------------------------------------ *)
(* Dump the analysis results. *)
let () =
Error.logG 2 (fun f ->
for nt = 0 to Nonterminal.n - 1 do
for nt = Nonterminal.start to Nonterminal.n - 1 do
Printf.fprintf f "nullable(%s) = %b\n"
(Nonterminal.print false nt)
(NULLABLE.nonterminal nt)
done;
for nt = 0 to Nonterminal.n - 1 do
for nt = Nonterminal.start to Nonterminal.n - 1 do
Printf.fprintf f "first(%s) = %s\n"
(Nonterminal.print false nt)
(TerminalSet.print (FIRST.nonterminal nt))
done;
for nt = Nonterminal.start to Nonterminal.n - 1 do
Printf.fprintf f "minimal(%s) = %s\n"
(Nonterminal.print false nt)
(CompletedNat.print (MINIMAL.nonterminal nt))
done
)
......@@ -1086,7 +1115,7 @@ let follow : Nonterminal.t -> TerminalSet.t =
let () =
Error.logG 2 (fun f ->
for nt = 0 to Nonterminal.n - 1 do
for nt = Nonterminal.start to Nonterminal.n - 1 do
Printf.fprintf f "follow(%s) = %s\n"
(Nonterminal.print false nt)
(TerminalSet.print (follow nt))
......
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