Compilerbauhome Compilerbau & Formale Sprachen: Nichtdeterministische endliche Automaten Prof. Dr. Uwe Schmidt FH Wedel

Nichtdeterministische endliche Automaten

weiter

weiter

Arbeitsweise nichtdeterministischer endlicher Automaten bei der lexikalischen Analyse

NFA
nichtdeterministischer endlicher Automat
nondeterministic finite automaton
Funktionsweise
erklärt in Haskell-Notation
weiter
Beispiel
Erkennen einer Folge von a's, deren Länge ein Vielfaches von 2 oder 3 ist.
weiter
.1
ohne epsilon-Übergänge
 
?
Gleichwertiger regulärer Ausdruck?
.2
mit epsilon-Übergängen
 
?
Gleichwertiger regulärer Ausdruck?
weiter

weiter

Datentypen und Arbeitsweise eines endlichen nichtdeterministischen Automaten:

   1module NFA
   2    ( I, Alphabet
   3    , Q, SetOfQ
   4    , Delta
   5    , Delta'
   6    , NFA
   7    , Token, Tokens
   8
   9    , epsilon
  10    , emptySet
  11    , singleSet
  12    , isEmptySet
  13    , card
  14    , extendDelta
  15    , epsilonClosure
  16    , containsFinalState
  17
  18    , run
  19    , accept
  20
  21    , dfaToNfa
  22    , showTokens
  23    )
  24where
  25
  26import DFA
  27    ( I, Alphabet
  28    , Q, SetOfQ
  29    , Input
  30    , Token
  31    , DFA
  32    )
  33
  34import DFAexample1
  35
  36import Data.Maybe
  37import Data.List
  38
  39type Delta      = Q -> Maybe I -> SetOfQ
  40                                -- Delta for DFA's extended
  41                                -- result is a set of states,
  42                                -- the emty set represents undefined in the DFA
  43                                -- input domain is extended: epsilon is represented by Nothing
  44
  45type Delta'     = SetOfQ -> Maybe I -> SetOfQ
  46                                -- Delta extended to work with sets of states
  47
  48type Tokens     = ([(SetOfQ, Token)], Input)
  49
  50type NFA        = (SetOfQ, Alphabet, Q, SetOfQ, Delta)
  51                                -- the complete automaton, consisting of start state,
  52                                -- set of final states and transition relation
  53
  54type NFAState   = (SetOfQ, Token, Input)
  55                                -- single state in DFA is extended to a set of all possible states
  56
  57-- auxiliary functions and predicates
  58
  59epsilon         :: Maybe I
  60epsilon         = Nothing
  61
  62emptySet        :: [a]
  63emptySet        = []
  64
  65singleSet       :: a -> [a]
  66singleSet q     = [q]
  67
  68isEmptySet      :: [a] -> Bool
  69isEmptySet      = null
  70
  71card            :: [a] -> Int
  72card            = length
  73
  74extendDelta     :: Delta -> Delta'
  75extendDelta delta qs c
  76    = foldr union emptySet . map (\ q' -> delta q' c) $ qs
  77
  78
  79epsilonClosure  :: Delta' -> SetOfQ -> SetOfQ
  80epsilonClosure delta' qs
  81    | card qs == card qs'
  82        = qs'
  83    | otherwise
  84        = epsilonClosure delta' qs'
  85    where
  86    qs' = qs `union` delta' qs epsilon
  87
  88containsFinalState      :: SetOfQ -> SetOfQ -> Bool
  89containsFinalState finalStates qs
  90        = not (isEmptySet (qs `intersect` finalStates))
  91
  92
  93-- the main function
  94
  95run :: NFA -> Input -> Tokens
  96
  97run (_allStates, _allSymbols, start, finalStates, delta) input
  98    | null input
  99      &&
 100      containsFinalState finalStates start'
 101        = ([(start', "")], "")
 102    | otherwise
 103        = loop input
 104    where
 105    start'      :: SetOfQ
 106    start'      = closure (singleSet start)
 107
 108    delta'      :: Delta'
 109    delta'      = extendDelta delta
 110
 111    closure     :: SetOfQ -> SetOfQ
 112    closure     = epsilonClosure delta'
 113
 114    -- the main loop
 115
 116    loop :: Input -> Tokens
 117    loop inp
 118        | null s
 119            = ([], inp)
 120        | null inp'
 121            = ([(qs,s)], "")
 122        | otherwise
 123            = let
 124              (ts, rest) = loop inp'
 125              in
 126              ((qs, s) : ts, rest)
 127        where
 128        init = (start', "", inp)
 129        (qs, s, inp') = symbol init init
 130
 131    -- scan one symbol
 132
 133    symbol :: NFAState -> NFAState -> NFAState
 134    symbol lastFinalState currState@(qs, s, i)
 135        | isFinalState && longestMatch          -- success: token recognized
 136            = currState
 137
 138        | isFinalState && not longestMatch      -- token may still be longer
 139            = symbol currState nextState
 140
 141        | not isFinalState && longestMatch      -- failure: restore last possible token
 142            = lastFinalState
 143
 144        | not isFinalState && not longestMatch  -- token not yet complete
 145            = symbol lastFinalState nextState
 146
 147        where
 148        isFinalState = containsFinalState finalStates qs
 149
 150        longestMatch = null i                   -- EOF or delta undefined
 151                       ||
 152                       isEmptySet (delta' qs nextChar')
 153
 154        nextChar     = head i
 155        nextChar'    = Just nextChar
 156                                                -- compute next state
 157                                                -- and read next input char
 158        nextState    = ( closure (delta' qs nextChar')
 159                       , s ++ [nextChar]
 160                       , tail i
 161                       )
 162
 163-- word test
 164
 165accept  :: NFA -> Input -> Bool
 166accept a
 167    = oneSymbol . run a
 168      where
 169      oneSymbol ([_], "") = True
 170      oneSymbol _         = False
 171
 172-- every DFA is also a NFA
 173
 174dfaToNfa        :: DFA -> NFA
 175dfaToNfa (states, alphabet, start, finalStates, delta)
 176    = (states, alphabet, start, finalStates, delta')
 177    where
 178    delta' _ Nothing    = []
 179    delta' q (Just c)   = maybeToList (delta q c)
 180
 181-- format result
 182
 183showTokens      :: Tokens -> String
 184showTokens (ts, rest)
 185    = concatMap showToken ts
 186      ++
 187      showRest rest
 188      where
 189      showToken (qs, s)
 190          = showStates qs ++ "\t: " ++ show s ++ "\n"
 191      showStates
 192          = foldr1 (\ s1 s2 -> s1 ++ "," ++ s2) . map show . sort
 193      showRest ""
 194          = ""
 195      showRest r
 196          = "input not accepted: " ++ show r ++ "\n"
weiter

weiter

Beispiel .1 mit Übergangstabelle und Endzustandsmenge

   1module NFAexample1 ( nfa1 )
   2where
   3
   4import NFA
   5
   6nfa1    :: NFA
   7nfa1
   8    = (states, alphabet, q0, f, delta)
   9    where
  10    states      = [1..6]
  11    alphabet    = "a"
  12    q0          = 1
  13    f           = [1,4,6]
  14    delta 1 (Just 'a') = [2,5]
  15    delta 2 (Just 'a') = [3]
  16    delta 3 (Just 'a') = [4]
  17    delta 4 (Just 'a') = [2]
  18    delta 5 (Just 'a') = [6]
  19    delta 6 (Just 'a') = [5]
  20    delta _ _          = []
weiter

weiter

Beispiel .2 mit Übergangstabelle und Endzustandsmenge

   1module NFAexample2 ( nfa2 )
   2where
   3
   4import NFA
   5
   6nfa2    :: NFA
   7nfa2
   8    = (states, alphabet, q0, f, delta)
   9    where
  10    states      = [1..6]
  11    alphabet    = "a"
  12    q0          = 1
  13    f           = [2,5]
  14    delta 1 Nothing    = [2,5]
  15    delta 2 (Just 'a') = [3]
  16    delta 3 (Just 'a') = [4]
  17    delta 4 (Just 'a') = [2]
  18    delta 5 (Just 'a') = [6]
  19    delta 6 (Just 'a') = [5]
  20    delta _ _          = []
weiter

weiter

Testläufe

mit .1
weiter
.1
./NFArun nfa1 ""
.2
./NFArun nfa1 "aa"
.3
./NFArun nfa1 "aaa"
.4
./NFArun nfa1 "aaaaaa"
.5
./NFArun nfa1 "a"
weiter
mit .2
weiter
.1
./NFArun nfa2 ""
.2
./NFArun nfa2 "aa"
.3
./NFArun nfa2 "aaa"
.4
./NFArun nfa2 "aaaaaa"
.5
./NFArun nfa2 "a"

Letzte Änderung: 14.02.2012
© Prof. Dr. Uwe Schmidt
Prof. Dr. Uwe Schmidt FH Wedel