isabelle-hacks/fxp/src/Parser/Dfa/dfaOptions.sml

98 lines
3.2 KiB
Standard ML

signature DfaOptions =
sig
val O_DFA_INITIAL_WIDTH : int Unsynchronized.ref
val O_DFA_MAX_STATES : int Unsynchronized.ref
val O_DFA_WARN_TOO_LARGE : bool Unsynchronized.ref
val setDfaDefaults : unit -> unit
val setDfaOptions : Options.Option list * (string -> unit) -> Options.Option list
val dfaUsage : Options.Usage
end
functor DfaOptions () : DfaOptions =
struct
open Options UtilInt
val O_DFA_INITIAL_WIDTH = Unsynchronized.ref 4
val O_DFA_MAX_STATES = Unsynchronized.ref 256
val O_DFA_WARN_TOO_LARGE = Unsynchronized.ref true
fun setDfaDefaults() =
let
val _ = O_DFA_INITIAL_WIDTH := 4
val _ = O_DFA_MAX_STATES := 256
val _ = O_DFA_WARN_TOO_LARGE := true
in ()
end
val dfaUsage =
[U_ITEM(["--dfa-initial-size=n"],"Initial size of DFA transition tables (16)"),
U_ITEM(["--dfa-initial-width=n"],"Same as --dfa-initial-size=2^n (4)"),
U_ITEM(["--dfa-max-size=n"],"Maximal size of DFAs for ambiguous content models (256)"),
U_ITEM(["--dfa-warn-size[=(yes|no)]"],"Warn about too large DFAs (yes)")
]
fun setDfaOptions(opts,doError) =
let
exception Failed of string option
fun getNat str =
if str="" then raise Failed NONE
else let val cs = String.explode str
in foldl (fn (c,n) => if #"0">c orelse #"9"<c then raise Failed NONE
else 10*n+ord c-48) 0 cs
handle Overflow => raise Failed
(SOME("number "^str^" is too large for this system"))
end
val yesNo = "'yes' or 'no'"
fun tooLarge n = String.concat ["number ",n," is too large for this system"]
fun mustHave key = String.concat ["option --",key," must have an argument"]
fun mustBe key what = String.concat
["the argument to option --",key," must be ",what]
fun do_yesno(key,valOpt,flag) =
case valOpt
of NONE => flag := true
| SOME "yes" => flag := true
| SOME "no" => flag := false
| SOME s => doError (mustBe key yesNo)
fun do_num(key,valOpt,flag) =
case valOpt
of NONE => doError (mustHave key)
| SOME s => flag := getNat s
handle Failed NONE => doError (mustBe key "a number")
| Failed (SOME s) => doError s
fun do_dfa_ts(key,valOpt,toWidth) =
case valOpt
of NONE => doError (mustHave key)
| SOME s => O_DFA_INITIAL_WIDTH := toWidth (getNat s)
handle Failed NONE => doError (mustBe key "a number")
| Failed (SOME s) => doError s
fun do_long(key,valOpt) =
case key
of "dfa-initial-size" => true before do_dfa_ts(key,valOpt,nextPowerTwo)
| "dfa-initial-width" => true before do_dfa_ts(key,valOpt,fn i => i)
| "dfa-max-size" => true before do_num(key,valOpt,O_DFA_MAX_STATES)
| "dfa-warn-size" => true before do_yesno(key,valOpt,O_DFA_WARN_TOO_LARGE)
| _ => false
and doit nil = nil
| doit (opt::opts) =
case opt
of OPT_NOOPT => opts
| OPT_LONG(key,value) => if do_long(key,value) then doit opts
else opt::doit opts
| OPT_NEG _ => opt::doit opts
| OPT_SHORT _ => opt::doit opts
| OPT_STRING _ => opt::doit opts
in doit opts
end
end