Skip to content

Commit 14d6a9b

Browse files
authored
Merge pull request #58 from CSchank/dev
first official release! export as TikZ and advanced DFA / NFA validation features
2 parents 8058f5f + 4fdb0fa commit 14d6a9b

File tree

9 files changed

+1199
-365
lines changed

9 files changed

+1199
-365
lines changed

elm.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,22 @@
77
"dependencies": {
88
"direct": {
99
"MacCASOutreach/graphicsvg": "6.1.0",
10+
"billstclair/elm-sha256": "1.0.8",
1011
"elm/browser": "1.0.1",
1112
"elm/core": "1.0.2",
1213
"elm/html": "1.0.0",
1314
"elm/http": "1.0.0",
1415
"elm/json": "1.1.2",
1516
"elm/random": "1.0.0",
17+
"elm/time": "1.0.0",
1618
"elm/url": "1.0.0",
1719
"elm-community/undo-redo": "3.0.0"
1820
},
1921
"indirect": {
22+
"elm/regex": "1.0.0",
2023
"elm/svg": "1.0.1",
21-
"elm/time": "1.0.0",
22-
"elm/virtual-dom": "1.0.2"
24+
"elm/virtual-dom": "1.0.2",
25+
"elm-community/list-extra": "8.1.0"
2326
}
2427
},
2528
"test-dependencies": {

src/Building.elm

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ update env msg ( model, pModel, sModel ) =
414414
newMachine =
415415
{ oldMachine
416416
| q = Set.insert newId oldMachine.q
417+
, delta = Dict.insert newId Dict.empty oldMachine.delta
417418
, statePositions = Dict.insert newId ( x, y ) oldMachine.statePositions
418419
, stateNames = Dict.insert newId ("q_{" ++ String.fromInt newId ++ "}") oldMachine.stateNames
419420
}
@@ -670,11 +671,6 @@ view env ( model, pModel, sModel ) =
670671
]
671672

672673

673-
roundTo : Float -> Float -> Float
674-
roundTo n m =
675-
toFloat (round (m + n / 2) // round n * round n)
676-
677-
678674
updateStatePos : StateID -> ( Float, Float ) -> StatePositions -> StatePositions
679675
updateStatePos st ( x, y ) pos =
680676
Dict.update st

src/Error.elm

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
module Error exposing (DFAErrorType(..), Error(..), contextHasError, errorIcon, errorMenu, machineCheck)
2+
3+
-- This module serves to export checks and exception handling of finite state machines.
4+
-- When we add support for other machine types, we can extend this module as well.
5+
6+
import Array exposing (Array)
7+
import Dict exposing (Dict)
8+
import Environment exposing (Environment)
9+
import GraphicSVG exposing (..)
10+
import Helpers exposing (..)
11+
import Machine exposing (Machine, StateID, TransitionID)
12+
import Set exposing (Set)
13+
import SharedModel exposing (..)
14+
import Tuple exposing (first, second)
15+
16+
17+
type Error
18+
= NoError
19+
| DFAError DFAErrorType StateID
20+
| EpsTransError
21+
| DuplicateStates (Set StateID)
22+
23+
24+
type DFAErrorType
25+
= HasEpsilon
26+
| Incomplete
27+
| Nondeterministic
28+
| Unsure -- Good for debugging?
29+
30+
31+
contextHasError : Error -> MachineType -> Bool
32+
contextHasError err mtype =
33+
case mtype of
34+
DFA ->
35+
if err == NoError then
36+
False
37+
38+
else
39+
True
40+
41+
NFA ->
42+
case err of
43+
EpsTransError ->
44+
True
45+
46+
DuplicateStates _ ->
47+
True
48+
49+
_ ->
50+
False
51+
52+
53+
machineCheck : SharedModel -> Error
54+
machineCheck sModel =
55+
let
56+
mac =
57+
sModel.machine
58+
59+
tMistakes =
60+
sModel.machine.transitionMistakes
61+
62+
allTransitionLabels =
63+
List.sort <| Set.toList <| Set.remove "\\epsilon" <| List.foldr Set.union Set.empty <| Dict.values mac.transitionNames
64+
65+
catch : Maybe (Set String) -> List String
66+
catch ms =
67+
case ms of
68+
Nothing ->
69+
[]
70+
71+
Just s ->
72+
Set.toList s
73+
74+
getTrans : Dict TransitionID StateID -> List String
75+
getTrans d =
76+
(List.concatMap (\e -> Dict.get e mac.transitionNames |> catch) <| Dict.keys d) |> List.sort
77+
78+
foldingFunc : ( StateID, Dict TransitionID StateID ) -> Error -> Error
79+
foldingFunc sTuple err =
80+
case err of
81+
DFAError errType x ->
82+
DFAError errType x
83+
84+
NoError ->
85+
let
86+
transitions =
87+
getTrans <| second sTuple
88+
89+
stId =
90+
first sTuple
91+
in
92+
if transitions == allTransitionLabels then
93+
NoError
94+
95+
else if List.member "\\epsilon" transitions then
96+
DFAError HasEpsilon stId
97+
98+
else
99+
case compare (List.length transitions) (List.length allTransitionLabels) of
100+
LT ->
101+
DFAError Incomplete stId
102+
103+
EQ ->
104+
DFAError Incomplete stId
105+
106+
-- e.g. compare [1,1,2] [1,2,3], can be Nondeterministic too
107+
GT ->
108+
DFAError Nondeterministic stId
109+
110+
otherErr ->
111+
otherErr
112+
in
113+
if tMistakes /= Nothing then
114+
EpsTransError
115+
116+
else
117+
List.foldr (\x acc -> foldingFunc x acc) NoError <| Dict.toList mac.delta
118+
119+
120+
errorIcon : Color -> Color -> Shape msg
121+
errorIcon backclr shapeclrs =
122+
group
123+
[ triangle 20 |> filled backclr |> rotate 22.5
124+
, roundedRect 7.5 10 5 |> filled shapeclrs |> move ( 0, 7.5 )
125+
, circle 3 |> filled shapeclrs |> move ( 0, -2.5 )
126+
]
127+
128+
129+
errorMenu : Error -> Machine -> Float -> Float -> Shape msg
130+
errorMenu err mac winX winY =
131+
let
132+
errStId =
133+
case err of
134+
DFAError _ stId ->
135+
case Dict.get stId mac.stateNames of
136+
Just name ->
137+
name
138+
139+
Nothing ->
140+
""
141+
142+
_ ->
143+
""
144+
145+
errorHeader txt =
146+
group
147+
[ errorIcon red white
148+
, text txt
149+
|> size 20
150+
|> fixedwidth
151+
|> filled darkRed
152+
|> move ( 20, 0 )
153+
]
154+
|> scale 0.75
155+
|> move ( 0, -20 )
156+
157+
errorReason =
158+
group
159+
[ circle 3 |> filled red
160+
, (text <|
161+
case err of
162+
DFAError HasEpsilon _ ->
163+
"Possible cause: There are epsilon transitions"
164+
165+
DFAError Incomplete _ ->
166+
"Possible cause: There are missing transitions"
167+
168+
DFAError Nondeterministic _ ->
169+
"Possible cause: There are extraneous transitions"
170+
171+
EpsTransError ->
172+
"Cause: Epsilon transitions are mixed with normal transitions"
173+
174+
_ ->
175+
"You might have missed something somewhere?"
176+
)
177+
|> size 12
178+
|> fixedwidth
179+
|> filled darkRed
180+
|> move ( 15, -5 )
181+
]
182+
|> move ( 0, -40 )
183+
184+
errorHint =
185+
group
186+
[ circle 3 |> filled red
187+
, (text <|
188+
case err of
189+
DFAError HasEpsilon _ ->
190+
"Hint: Try removing all your epsilon transitions"
191+
192+
DFAError Incomplete _ ->
193+
"Hint: Check states for missing transitions"
194+
195+
DFAError Nondeterministic _ ->
196+
"Hint: Find and remove extra transitions"
197+
198+
EpsTransError ->
199+
"Hint: Switch to Build mode and fix transitions in red"
200+
201+
_ ->
202+
""
203+
)
204+
|> size 12
205+
|> fixedwidth
206+
|> filled darkRed
207+
|> move ( 15, -5 )
208+
]
209+
|> move ( 0, -60 )
210+
211+
errorState =
212+
group
213+
[ circle 3 |> filled red
214+
, text "Hint: Check state "
215+
|> size 12
216+
|> fixedwidth
217+
|> filled darkRed
218+
|> move ( 15, -5 )
219+
, latex 50 12 "blank" errStId AlignLeft |> move ( 150, 3 )
220+
]
221+
|> move ( 0, -80 )
222+
223+
actionHint =
224+
group
225+
[ circle 3 |> filled red
226+
, text "Go to Build mode to fix your machine, or use a NFA"
227+
|> size 12
228+
|> fixedwidth
229+
|> filled darkRed
230+
|> move ( 15, -5 )
231+
]
232+
|> move ( 0, -100 )
233+
in
234+
case err of
235+
DFAError _ _ ->
236+
group [ errorHeader "DFA error: Your machine has a problem!", errorReason, errorHint, errorState, actionHint ]
237+
238+
EpsTransError ->
239+
group [ errorHeader "Error: You have invalid state transitions!", errorReason, errorHint ]
240+
241+
NoError ->
242+
group []
243+
244+
-- TODO: Add error handling for duplicate state names
245+
DuplicateStates _ ->
246+
group []

0 commit comments

Comments
 (0)