aboutsummaryrefslogtreecommitdiff
path: root/src/nbc/parse-state.sml
diff options
context:
space:
mode:
Diffstat (limited to 'src/nbc/parse-state.sml')
-rw-r--r--src/nbc/parse-state.sml89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/nbc/parse-state.sml b/src/nbc/parse-state.sml
new file mode 100644
index 0000000..8b30a67
--- /dev/null
+++ b/src/nbc/parse-state.sml
@@ -0,0 +1,89 @@
+signature PARSE_STATE = sig
+ type ('argument, 'result) state
+ val create: unit -> ('argument, 'result) state
+ type ('argument, 'result) handler =
+ TextIO.instream * 'argument -> 'result
+ datatype whichCharacters = These of char list | Any
+ val build: {
+ state: ('argument, 'result) state
+ , characters:
+ (whichCharacters * ('argument, 'result) handler) list
+ , endOfFile: ('argument, 'result) handler
+ } -> unit
+ val enter:
+ ('argument, 'result) state
+ * TextIO.instream
+ * 'argument
+ -> 'result
+end
+
+structure ParseState :> PARSE_STATE = struct
+ type ('argument, 'result) handler =
+ TextIO.instream * 'argument -> 'result
+ datatype whichCharacters = These of char list | Any
+ type ('argument, 'result) state = {
+ byCharacter: Int8.int vector ref
+ , byIndex: ('argument, 'result) handler vector ref
+ , endOfFile: ('argument, 'result) handler option ref
+ }
+ fun create () = {
+ byCharacter = ref (Vector.fromList nil)
+ , byIndex = ref (Vector.fromList nil)
+ , endOfFile = ref NONE
+ }
+ fun build {
+ state = {byCharacter, byIndex, endOfFile}
+ , characters
+ , endOfFile = newEndOfFile
+ } =
+ let
+ val characters = vector characters
+ fun equal (one: char) (two: char) =
+ one = two
+ fun shallHandle ((whichToHandle, _), char) =
+ case whichToHandle of
+ Any => true
+ | These charactersToHandle =>
+ List.exists (equal char)
+ charactersToHandle
+ fun charToIndex char =
+ case
+ Vector.findi (fn (_, handler) =>
+ shallHandle (handler, char)
+ ) characters
+ of
+ NONE => raise Fail (
+ "ParseState.build: "
+ ^ Char.toString char
+ ^ " not found"
+ ) | SOME (index, _) =>
+ Int8.fromInt index
+ fun handlerToFunction (_, function) = function
+ fun indexToFunction index = handlerToFunction (
+ Vector.sub (characters, index)
+ )
+ in
+ byCharacter := Vector.tabulate (
+ Char.maxOrd + 1
+ , charToIndex o chr
+ ); byIndex :=
+ Vector.map (fn (_, function) =>
+ function
+ ) characters
+ ; endOfFile := SOME newEndOfFile
+ end
+ fun enter (
+ {
+ byCharacter = ref byCharacter
+ , byIndex = ref byIndex
+ , endOfFile = ref endOfFile
+ }
+ , instream
+ , argument
+ ) = case TextIO.input1 instream of
+ NONE => (valOf endOfFile) (instream, argument)
+ | SOME char => Vector.sub (
+ byIndex
+ , Int8.toInt (Vector.sub (byCharacter, ord char))
+ ) (instream, argument)
+end