67 lines
No EOL
1.9 KiB
FSharp
67 lines
No EOL
1.9 KiB
FSharp
module DFA
|
|
|
|
open System
|
|
|
|
type State = { name: String }
|
|
|
|
///
|
|
/// A deterministic finite automaton
|
|
///
|
|
type DFA = {
|
|
/// All possible characters
|
|
sigma: Char list
|
|
/// All possible states
|
|
states: State list
|
|
/// All possible transitions
|
|
delta: State -> Char -> State
|
|
/// The state this DFA begins in
|
|
beginState: State
|
|
/// The states in which this DFA accepts
|
|
/// the word
|
|
acceptingStates: State list
|
|
}
|
|
|
|
/// Returns true if the DFA is valid, false otherwise
|
|
let validateDFA (dfa:DFA) =
|
|
|
|
let allAcceptingStatesAreStates =
|
|
dfa.acceptingStates
|
|
|> List.map (fun x -> List.contains x dfa.states)
|
|
|> List.filter not
|
|
|> List.length
|
|
|> (<) 1
|
|
|
|
let deltaIsComplete =
|
|
// Gets the cartesian product of states * sigma
|
|
dfa.states
|
|
|> List.collect (fun x -> dfa.sigma |> List.map (fun y -> (x, y)))
|
|
|
|
// Processes all tuples through delta
|
|
|> List.map (fun x -> dfa.delta (fst x) (snd x))
|
|
|
|
// Checks if there is any result from delta which is not
|
|
// a valid state
|
|
|> List.filter (fun x -> not (List.contains x dfa.states))
|
|
|> List.length
|
|
|> (<) 1
|
|
|
|
List.contains dfa.beginState dfa.states ||
|
|
allAcceptingStatesAreStates ||
|
|
deltaIsComplete
|
|
|
|
/// Returns the state the DFA is in after
|
|
/// reading this character
|
|
let processChar (dfa: DFA) (state: State) (char: Char) =
|
|
dfa.delta state char
|
|
|
|
/// Returns the state the DFA is in after
|
|
/// reading this character array
|
|
let rec processCharArray (dfa: DFA) (state: State) (charArr: Char list) =
|
|
match charArr with
|
|
| [] -> state
|
|
| head :: tail -> processCharArray dfa (processChar dfa state head) tail
|
|
|
|
/// Returns whether the DFA accepts this word
|
|
let acceptsWord (dfa: DFA) (word: String) =
|
|
dfa.acceptingStates
|
|
|> List.contains (processCharArray dfa dfa.beginState (Seq.toList word)) |