integer = lexeme L.integer
symbol = L.symbol sc
fullstop = symbol "."
+colon = symbol ":"
+dash = symbol "-"
-commandP = between (symbol "-") fullstop
+machineDescriptionP = machineify <$> startStateP <*> stepsP <*> manyStateRulesP
+ where machineify initial limit rules =
+ ( emptyMachine { tState = initial, stepsRemaining = limit }
+ , rules
+ )
-writeValueP = (symbol "1" *> pure True) <|> (symbol "0" *> pure False)
-writeP = commandP ((symbol "Write the value") *> writeValueP)
+startStateP = (symbol "Begin in state") *> stateP <* fullstop
+stepsP = (symbol "Perform a diagnostic checksum after") *> integer <* (symbol "steps") <* fullstop
+
+manyStateRulesP = M.unions <$> (stateRulesP `sepBy` space)
-directionP = (symbol "left" *> pure -1) <|> (symbol "right" *> pure 1)
-tapeMovementP = commandP ((symbol "Move one slot to the") *> directionP)
+stateRulesP = rulify <$> stateDefP <*> (stateWhenP `sepBy` space)
+ where rulify s ts = M.fromList $ map (\(v, t) -> ((s, v), t)) ts
-newStateP = commandP ((symbol "Continue with state") *> (some letterChar))
+stateWhenP = (,) <$> currentValueP <*> stateTransitionP
+
+stateDefP = (symbol "In state") *> stateP <* colon
+currentValueP = (symbol "If the current value is") *> writeValueP <* colon
stateTransitionP = stify <$> writeP <*> tapeMovementP <*> newStateP
where stify w t s = StateTransition {writeValue = w, newState = s, tapeMovement = t}
-
-currentValueP = (symbol "If the current value is") *> writeValueP <* (symbol ":")
-
-stateWhenP = (,) <$> currentValueP <*> stateTransitionP
-
-stateDefP = (symbol "In state") *> (some letterChar) <* (symbol ":")
-
-stateRulesP = rulify <$> stateDefP <*> (stateWhenP `sepBy` space)
- where rulify s ts = M.fromList $ map (\(v, t) -> ((s, v), t)) ts
-
-manyStateRulesP = M.unions <$> (stateRulesP `sepBy` space)
-startStateP = (symbol "Begin in state") *> (some letterChar) <* fullstop
-stepsP = (symbol "Perform a diagnostic checksum after") *> integer <* (symbol "steps") <* fullstop
+commandP = between dash fullstop
+
+writeP = commandP ((symbol "Write the value") *> writeValueP)
+tapeMovementP = commandP ((symbol "Move one slot to the") *> directionP)
+newStateP = commandP ((symbol "Continue with state") *> stateP)
+
+stateP = some letterChar
+directionP = (symbol "left" *> pure -1) <|> (symbol "right" *> pure 1)
+writeValueP = (symbol "1" *> pure True) <|> (symbol "0" *> pure False)
-machineDescriptionP = machineify <$> startStateP <*> stepsP <*> manyStateRulesP
- where machineify initial limit rules =
- ( emptyMachine { tState = initial, stepsRemaining = limit }
- , rules
- )
successfulParse :: Text -> (Machine, Rules)
successfulParse input =