Skip to content

Commit 58ea5ad

Browse files
committed
[ #71 ] Fixed crash in DFAMin
DFA minimization used to crash on tokens of the form c* which produce automata with only accepting states. Considering the empty set of non-accepting states as an equivalence class caused minimization to crash with exception Prelude.head: empty list Now, DFA minimization succeeds. There is still a problem with nullable tokens like c*. Alex produces an infinite token sequence at the end of the input.
1 parent 833ff8c commit 58ea5ad

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

alex.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ extra-source-files:
109109
tests/posn_typeclass_bytestring.x
110110
tests/strict_typeclass.x
111111
tests/unicode.x
112+
tests/issue_71.x
112113

113114
source-repository head
114115
type: git

src/DFAMin.hs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ groupEquivStates DFA { dfa_states = statemap }
112112
accept_groups :: [EquivalenceClass]
113113
accept_groups = map IS.fromList (Map.elems accept_map)
114114

115-
init_p = nonaccepting_states : accept_groups
115+
init_p, init_q :: [EquivalenceClass]
116+
init_p -- Issue #71: each EquivalenceClass needs to be a non-empty set
117+
| IS.null nonaccepting_states = accept_groups
118+
| otherwise = nonaccepting_states : accept_groups
116119
init_q = accept_groups
117120

118121
-- map token T to

tests/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ TESTS = \
4040
basic_typeclass_bytestring.x \
4141
default_typeclass.x \
4242
gscan_typeclass.x \
43+
issue_71.x \
4344
monad_typeclass.x \
4445
monad_typeclass_bytestring.x \
4546
monadUserState_typeclass.x \

tests/issue_71.x

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
-- Issue #71
3+
-- reported 2015-10-20 by Ian Duncan
4+
-- fixed 2020-01-22 by Andreas Abel
5+
--
6+
-- Problem was:
7+
-- DFA minimization crashed with "Prelude head: empty list" because
8+
-- empty set of non-accepting states was treated as empty equivalence
9+
-- class of states.
10+
11+
module Main (main) where
12+
13+
import System.Exit
14+
}
15+
16+
%wrapper "posn"
17+
%token "Token"
18+
19+
$whitespace = [\ \n\t]
20+
@whitespaces = $whitespace*
21+
22+
:-
23+
24+
@whitespaces { \ _ _ -> Whitespaces }
25+
"a" { \ _ _ -> A }
26+
27+
{
28+
data Token = Whitespaces | A
29+
deriving (Eq, Show)
30+
31+
input = "aa \n\taa \t \n a"
32+
expected_result = [A,A,Whitespaces,A,A,Whitespaces,A]
33+
34+
main :: IO ()
35+
main
36+
-- Since the whitespaces token is nullable, Alex
37+
-- will recognize an infinite number of those
38+
-- at the end of file. This behavior is problematic,
39+
-- but we don't fix it here.
40+
-- We just test here whether the expected result
41+
-- is a prefix of the produced result.
42+
| take (length expected_result) result == expected_result = do
43+
exitWith ExitSuccess
44+
| otherwise = do
45+
print $ take 20 result
46+
exitFailure
47+
where
48+
result = alexScanTokens input
49+
}

0 commit comments

Comments
 (0)