sgf 0.1.3.1 → 0.1.3.2
raw patch · 3 files changed
+556/−334 lines, 3 filesdep ~encodingPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: encoding
API changes (from Hackage documentation)
- Data.SGF.Parse: errorDescription :: Error -> Maybe String
- Data.SGF.Parse: errorPosition :: Error -> SourcePos
- Data.SGF.Parse: errorType :: Error -> ErrorType
- Data.SGF.Parse: instance Bounded PropertyType
- Data.SGF.Parse: instance Enum PropertyType
- Data.SGF.Parse: instance Eq PropertyType
- Data.SGF.Parse: instance Ord PropertyType
- Data.SGF.Parse: instance Read PropertyType
- Data.SGF.Parse: instance Show PropertyType
- Data.SGF.Parse: name :: Property -> String
- Data.SGF.Parse: position :: Property -> SourcePos
- Data.SGF.Parse: values :: Property -> [[Word8]]
- Data.SGF.Types: action :: GameNode move stone ruleSet extraGameInfo extraAnnotation -> Either (Setup stone) (Move move)
- Data.SGF.Types: addBlack :: Setup stone -> Set stone
- Data.SGF.Types: addWhite :: Setup stone -> Set stone
- Data.SGF.Types: annotation :: GameNode move stone ruleSet extraGameInfo extraAnnotation -> Annotation extraAnnotation
- Data.SGF.Types: application :: Game -> Maybe (Application, Version)
- Data.SGF.Types: arrows :: Markup -> Set (Point, Point)
- Data.SGF.Types: comment :: Annotation extra -> Maybe String
- Data.SGF.Types: date :: GameInfo ruleSet extra -> Set PartialDate
- Data.SGF.Types: day :: PartialDate -> Integer
- Data.SGF.Types: dim :: Markup -> Maybe (Set Point)
- Data.SGF.Types: figure :: Markup -> Maybe Figure
- Data.SGF.Types: freeform :: GameInfo ruleSet extra -> Map GameInfoType String
- Data.SGF.Types: gameInfo :: GameNode move stone ruleSet extraGameInfo extraAnnotation -> Maybe (GameInfo ruleSet extraGameInfo)
- Data.SGF.Types: handicap :: GameInfoGo -> Maybe Integer
- Data.SGF.Types: hotspot :: Annotation extra -> Maybe Emphasis
- Data.SGF.Types: illegal :: Move move -> FuzzyBool
- Data.SGF.Types: initialPlacement :: GameInfoLinesOfAction -> InitialPlacement
- Data.SGF.Types: initialPositionLOA :: GameInfoLinesOfAction -> InitialPosition
- Data.SGF.Types: instance (Bounded k, Enum k, Ord k, Eq v) => Eq (k -> v)
- Data.SGF.Types: instance (Bounded k, Enum k, Ord k, Ord v) => Ord (k -> v)
- Data.SGF.Types: instance (Bounded k, Enum k, Ord k, Read k, Read v) => Read (k -> v)
- Data.SGF.Types: instance (Bounded k, Enum k, Ord k, Show k, Show v) => Show (k -> v)
- Data.SGF.Types: instance (Eq move, Eq stone, Eq ruleSet, Eq extraGameInfo, Eq extraAnnotation) => Eq (GameNode move stone ruleSet extraGameInfo extraAnnotation)
- Data.SGF.Types: instance (Eq ruleSet, Eq extra) => Eq (GameInfo ruleSet extra)
- Data.SGF.Types: instance (Ord move, Ord stone, Ord ruleSet, Ord extraGameInfo, Ord extraAnnotation) => Ord (GameNode move stone ruleSet extraGameInfo extraAnnotation)
- Data.SGF.Types: instance (Ord ruleSet, Ord extra) => Ord (GameInfo ruleSet extra)
- Data.SGF.Types: instance (Ord stone, Read move, Read stone, Read ruleSet, Read extraGameInfo, Read extraAnnotation) => Read (GameNode move stone ruleSet extraGameInfo extraAnnotation)
- Data.SGF.Types: instance (Ord stone, Read stone) => Read (Setup stone)
- Data.SGF.Types: instance (Read ruleSet, Read extra) => Read (GameInfo ruleSet extra)
- Data.SGF.Types: instance (Show move, Show stone, Show ruleSet, Show extraGameInfo, Show extraAnnotation) => Show (GameNode move stone ruleSet extraGameInfo extraAnnotation)
- Data.SGF.Types: instance (Show ruleSet, Show extra) => Show (GameInfo ruleSet extra)
- Data.SGF.Types: instance Bounded Certainty
- Data.SGF.Types: instance Bounded Color
- Data.SGF.Types: instance Bounded Emphasis
- Data.SGF.Types: instance Bounded FigureFlag
- Data.SGF.Types: instance Bounded FuzzyBool
- Data.SGF.Types: instance Bounded GameInfoType
- Data.SGF.Types: instance Bounded GameType
- Data.SGF.Types: instance Bounded InitialPlacement
- Data.SGF.Types: instance Bounded InitialPosition
- Data.SGF.Types: instance Bounded Judgment
- Data.SGF.Types: instance Bounded MajorVariation
- Data.SGF.Types: instance Bounded Mark
- Data.SGF.Types: instance Bounded Numbering
- Data.SGF.Types: instance Bounded RankScale
- Data.SGF.Types: instance Bounded RuleSetBackgammon
- Data.SGF.Types: instance Bounded RuleSetGo
- Data.SGF.Types: instance Bounded VariationType
- Data.SGF.Types: instance Bounded ViewerSetting
- Data.SGF.Types: instance Enum Certainty
- Data.SGF.Types: instance Enum Color
- Data.SGF.Types: instance Enum Emphasis
- Data.SGF.Types: instance Enum FigureFlag
- Data.SGF.Types: instance Enum FuzzyBool
- Data.SGF.Types: instance Enum GameInfoType
- Data.SGF.Types: instance Enum GameType
- Data.SGF.Types: instance Enum InitialPlacement
- Data.SGF.Types: instance Enum InitialPosition
- Data.SGF.Types: instance Enum Judgment
- Data.SGF.Types: instance Enum MajorVariation
- Data.SGF.Types: instance Enum Mark
- Data.SGF.Types: instance Enum Numbering
- Data.SGF.Types: instance Enum RankScale
- Data.SGF.Types: instance Enum RuleSetBackgammon
- Data.SGF.Types: instance Enum RuleSetGo
- Data.SGF.Types: instance Enum VariationType
- Data.SGF.Types: instance Enum ViewerSetting
- Data.SGF.Types: instance Eq Certainty
- Data.SGF.Types: instance Eq Color
- Data.SGF.Types: instance Eq Emphasis
- Data.SGF.Types: instance Eq Figure
- Data.SGF.Types: instance Eq FigureFlag
- Data.SGF.Types: instance Eq FuzzyBool
- Data.SGF.Types: instance Eq Game
- Data.SGF.Types: instance Eq GameInfoGo
- Data.SGF.Types: instance Eq GameInfoLinesOfAction
- Data.SGF.Types: instance Eq GameInfoOcti
- Data.SGF.Types: instance Eq GameInfoType
- Data.SGF.Types: instance Eq GameResult
- Data.SGF.Types: instance Eq GameTree
- Data.SGF.Types: instance Eq GameType
- Data.SGF.Types: instance Eq InitialPlacement
- Data.SGF.Types: instance Eq InitialPosition
- Data.SGF.Types: instance Eq Judgment
- Data.SGF.Types: instance Eq MajorVariation
- Data.SGF.Types: instance Eq Mark
- Data.SGF.Types: instance Eq Markup
- Data.SGF.Types: instance Eq MatchInfo
- Data.SGF.Types: instance Eq MinorVariation
- Data.SGF.Types: instance Eq MoveGo
- Data.SGF.Types: instance Eq Numbering
- Data.SGF.Types: instance Eq PartialDate
- Data.SGF.Types: instance Eq Quality
- Data.SGF.Types: instance Eq Rank
- Data.SGF.Types: instance Eq RankScale
- Data.SGF.Types: instance Eq Round
- Data.SGF.Types: instance Eq RuleSetBackgammon
- Data.SGF.Types: instance Eq RuleSetGo
- Data.SGF.Types: instance Eq RuleSetOcti
- Data.SGF.Types: instance Eq VariationType
- Data.SGF.Types: instance Eq ViewerSetting
- Data.SGF.Types: instance Eq Void
- Data.SGF.Types: instance Eq WinType
- Data.SGF.Types: instance Eq a => Eq (RuleSet a)
- Data.SGF.Types: instance Eq extra => Eq (Annotation extra)
- Data.SGF.Types: instance Eq move => Eq (Move move)
- Data.SGF.Types: instance Eq stone => Eq (Setup stone)
- Data.SGF.Types: instance Ord Certainty
- Data.SGF.Types: instance Ord Color
- Data.SGF.Types: instance Ord Emphasis
- Data.SGF.Types: instance Ord Figure
- Data.SGF.Types: instance Ord FigureFlag
- Data.SGF.Types: instance Ord FuzzyBool
- Data.SGF.Types: instance Ord GameInfoGo
- Data.SGF.Types: instance Ord GameInfoLinesOfAction
- Data.SGF.Types: instance Ord GameInfoOcti
- Data.SGF.Types: instance Ord GameInfoType
- Data.SGF.Types: instance Ord GameResult
- Data.SGF.Types: instance Ord GameType
- Data.SGF.Types: instance Ord InitialPlacement
- Data.SGF.Types: instance Ord InitialPosition
- Data.SGF.Types: instance Ord Judgment
- Data.SGF.Types: instance Ord MajorVariation
- Data.SGF.Types: instance Ord Mark
- Data.SGF.Types: instance Ord Markup
- Data.SGF.Types: instance Ord MatchInfo
- Data.SGF.Types: instance Ord MinorVariation
- Data.SGF.Types: instance Ord MoveGo
- Data.SGF.Types: instance Ord Numbering
- Data.SGF.Types: instance Ord PartialDate
- Data.SGF.Types: instance Ord Quality
- Data.SGF.Types: instance Ord Rank
- Data.SGF.Types: instance Ord RankScale
- Data.SGF.Types: instance Ord Round
- Data.SGF.Types: instance Ord RuleSetBackgammon
- Data.SGF.Types: instance Ord RuleSetGo
- Data.SGF.Types: instance Ord RuleSetOcti
- Data.SGF.Types: instance Ord VariationType
- Data.SGF.Types: instance Ord ViewerSetting
- Data.SGF.Types: instance Ord Void
- Data.SGF.Types: instance Ord WinType
- Data.SGF.Types: instance Ord a => Ord (RuleSet a)
- Data.SGF.Types: instance Ord extra => Ord (Annotation extra)
- Data.SGF.Types: instance Ord move => Ord (Move move)
- Data.SGF.Types: instance Ord stone => Ord (Setup stone)
- Data.SGF.Types: instance Read Certainty
- Data.SGF.Types: instance Read Color
- Data.SGF.Types: instance Read Emphasis
- Data.SGF.Types: instance Read Figure
- Data.SGF.Types: instance Read FigureFlag
- Data.SGF.Types: instance Read FuzzyBool
- Data.SGF.Types: instance Read Game
- Data.SGF.Types: instance Read GameInfoGo
- Data.SGF.Types: instance Read GameInfoLinesOfAction
- Data.SGF.Types: instance Read GameInfoOcti
- Data.SGF.Types: instance Read GameInfoType
- Data.SGF.Types: instance Read GameResult
- Data.SGF.Types: instance Read GameTree
- Data.SGF.Types: instance Read GameType
- Data.SGF.Types: instance Read InitialPlacement
- Data.SGF.Types: instance Read InitialPosition
- Data.SGF.Types: instance Read Judgment
- Data.SGF.Types: instance Read MajorVariation
- Data.SGF.Types: instance Read Mark
- Data.SGF.Types: instance Read Markup
- Data.SGF.Types: instance Read MatchInfo
- Data.SGF.Types: instance Read MinorVariation
- Data.SGF.Types: instance Read MoveGo
- Data.SGF.Types: instance Read Numbering
- Data.SGF.Types: instance Read PartialDate
- Data.SGF.Types: instance Read Quality
- Data.SGF.Types: instance Read Rank
- Data.SGF.Types: instance Read RankScale
- Data.SGF.Types: instance Read Round
- Data.SGF.Types: instance Read RuleSetBackgammon
- Data.SGF.Types: instance Read RuleSetGo
- Data.SGF.Types: instance Read RuleSetOcti
- Data.SGF.Types: instance Read VariationType
- Data.SGF.Types: instance Read ViewerSetting
- Data.SGF.Types: instance Read Void
- Data.SGF.Types: instance Read WinType
- Data.SGF.Types: instance Read a => Read (RuleSet a)
- Data.SGF.Types: instance Read extra => Read (Annotation extra)
- Data.SGF.Types: instance Read move => Read (Move move)
- Data.SGF.Types: instance Show Certainty
- Data.SGF.Types: instance Show Color
- Data.SGF.Types: instance Show Emphasis
- Data.SGF.Types: instance Show Figure
- Data.SGF.Types: instance Show FigureFlag
- Data.SGF.Types: instance Show FuzzyBool
- Data.SGF.Types: instance Show Game
- Data.SGF.Types: instance Show GameInfoGo
- Data.SGF.Types: instance Show GameInfoLinesOfAction
- Data.SGF.Types: instance Show GameInfoOcti
- Data.SGF.Types: instance Show GameInfoType
- Data.SGF.Types: instance Show GameResult
- Data.SGF.Types: instance Show GameTree
- Data.SGF.Types: instance Show GameType
- Data.SGF.Types: instance Show InitialPlacement
- Data.SGF.Types: instance Show InitialPosition
- Data.SGF.Types: instance Show Judgment
- Data.SGF.Types: instance Show MajorVariation
- Data.SGF.Types: instance Show Mark
- Data.SGF.Types: instance Show Markup
- Data.SGF.Types: instance Show MatchInfo
- Data.SGF.Types: instance Show MinorVariation
- Data.SGF.Types: instance Show MoveGo
- Data.SGF.Types: instance Show Numbering
- Data.SGF.Types: instance Show PartialDate
- Data.SGF.Types: instance Show Quality
- Data.SGF.Types: instance Show Rank
- Data.SGF.Types: instance Show RankScale
- Data.SGF.Types: instance Show Round
- Data.SGF.Types: instance Show RuleSetBackgammon
- Data.SGF.Types: instance Show RuleSetGo
- Data.SGF.Types: instance Show RuleSetOcti
- Data.SGF.Types: instance Show VariationType
- Data.SGF.Types: instance Show ViewerSetting
- Data.SGF.Types: instance Show Void
- Data.SGF.Types: instance Show WinType
- Data.SGF.Types: instance Show a => Show (RuleSet a)
- Data.SGF.Types: instance Show extra => Show (Annotation extra)
- Data.SGF.Types: instance Show move => Show (Move move)
- Data.SGF.Types: instance Show stone => Show (Setup stone)
- Data.SGF.Types: invertYAxis :: GameInfoLinesOfAction -> Bool
- Data.SGF.Types: judgment :: Annotation extra -> Maybe (Judgment, Emphasis)
- Data.SGF.Types: komi :: GameInfoGo -> Maybe Rational
- Data.SGF.Types: labels :: Markup -> Map Point String
- Data.SGF.Types: lines :: Markup -> Set (Point, Point)
- Data.SGF.Types: marks :: Markup -> Map Point Mark
- Data.SGF.Types: markup :: GameNode move stone ruleSet extraGameInfo extraAnnotation -> Markup
- Data.SGF.Types: month :: PartialDate -> Integer
- Data.SGF.Types: move :: Move move -> Maybe (Color, move)
- Data.SGF.Types: name :: Annotation extra -> Maybe String
- Data.SGF.Types: number :: Move move -> Maybe Integer
- Data.SGF.Types: numbering :: Markup -> Maybe Numbering
- Data.SGF.Types: otherAnnotation :: Annotation extra -> extra
- Data.SGF.Types: otherGameInfo :: GameInfo ruleSet extra -> extra
- Data.SGF.Types: overtimeMovesBlack :: Move move -> Maybe Integer
- Data.SGF.Types: overtimeMovesWhite :: Move move -> Maybe Integer
- Data.SGF.Types: prongs :: GameInfoOcti -> Integer
- Data.SGF.Types: quality :: Move move -> Maybe Quality
- Data.SGF.Types: rankBlack :: GameInfo ruleSet extra -> Maybe Rank
- Data.SGF.Types: rankWhite :: GameInfo ruleSet extra -> Maybe Rank
- Data.SGF.Types: remove :: Setup stone -> Set Point
- Data.SGF.Types: reserve :: GameInfoOcti -> Integer
- Data.SGF.Types: result :: GameInfo ruleSet extra -> Maybe GameResult
- Data.SGF.Types: round :: GameInfo ruleSet extra -> Maybe Round
- Data.SGF.Types: ruleSet :: GameInfo ruleSet extra -> Maybe (RuleSet ruleSet)
- Data.SGF.Types: size :: Game -> Maybe (Integer, Integer)
- Data.SGF.Types: squaresBlack :: GameInfoOcti -> Set Point
- Data.SGF.Types: squaresWhite :: GameInfoOcti -> Set Point
- Data.SGF.Types: superProngs :: GameInfoOcti -> Integer
- Data.SGF.Types: timeBlack :: Move move -> Maybe Rational
- Data.SGF.Types: timeLimit :: GameInfo ruleSet extra -> Maybe Rational
- Data.SGF.Types: timeWhite :: Move move -> Maybe Rational
- Data.SGF.Types: toPlay :: Setup stone -> Maybe Color
- Data.SGF.Types: tree :: Game -> GameTree
- Data.SGF.Types: unknown :: GameNode move stone ruleSet extraGameInfo extraAnnotation -> Map String [[Word8]]
- Data.SGF.Types: value :: Annotation extra -> Maybe Rational
- Data.SGF.Types: variationType :: Game -> Maybe (VariationType, AutoMarkup)
- Data.SGF.Types: visible :: Markup -> Maybe (Set Point)
- Data.SGF.Types: year :: PartialDate -> Integer
+ Data.SGF: collection :: Stream s m Word8 => ParsecT s u m (Collection, [Warning])
+ Data.SGF: runParser :: GenParser tok st a -> st -> SourceName -> [tok] -> Either ParseError a
+ Data.SGF.Parse: [errorDescription] :: Error -> Maybe String
+ Data.SGF.Parse: [errorPosition] :: Error -> SourcePos
+ Data.SGF.Parse: [errorType] :: Error -> ErrorType
+ Data.SGF.Parse: [name] :: Property -> String
+ Data.SGF.Parse: [position] :: Property -> SourcePos
+ Data.SGF.Parse: [values] :: Property -> [[Word8]]
+ Data.SGF.Parse: instance Control.Monad.Fail.MonadFail (Data.Either.Either Data.SGF.Parse.Util.Error)
+ Data.SGF.Parse: instance GHC.Classes.Eq Data.SGF.Parse.PropertyType
+ Data.SGF.Parse: instance GHC.Classes.Ord Data.SGF.Parse.PropertyType
+ Data.SGF.Parse: instance GHC.Enum.Bounded Data.SGF.Parse.PropertyType
+ Data.SGF.Parse: instance GHC.Enum.Enum Data.SGF.Parse.PropertyType
+ Data.SGF.Parse: instance GHC.Read.Read Data.SGF.Parse.PropertyType
+ Data.SGF.Parse: instance GHC.Show.Show Data.SGF.Parse.PropertyType
+ Data.SGF.Types: [action] :: GameNode move stone ruleSet extraGameInfo extraAnnotation -> Either (Setup stone) (Move move)
+ Data.SGF.Types: [addBlack] :: Setup stone -> Set stone
+ Data.SGF.Types: [addWhite] :: Setup stone -> Set stone
+ Data.SGF.Types: [annotation] :: GameNode move stone ruleSet extraGameInfo extraAnnotation -> Annotation extraAnnotation
+ Data.SGF.Types: [application] :: Game -> Maybe (Application, Version)
+ Data.SGF.Types: [arrows] :: Markup -> Set (Point, Point)
+ Data.SGF.Types: [comment] :: Annotation extra -> Maybe String
+ Data.SGF.Types: [date] :: GameInfo ruleSet extra -> Set PartialDate
+ Data.SGF.Types: [day] :: PartialDate -> Integer
+ Data.SGF.Types: [dim] :: Markup -> Maybe (Set Point)
+ Data.SGF.Types: [figure] :: Markup -> Maybe Figure
+ Data.SGF.Types: [freeform] :: GameInfo ruleSet extra -> Map GameInfoType String
+ Data.SGF.Types: [gameInfo] :: GameNode move stone ruleSet extraGameInfo extraAnnotation -> Maybe (GameInfo ruleSet extraGameInfo)
+ Data.SGF.Types: [handicap] :: GameInfoGo -> Maybe Integer
+ Data.SGF.Types: [hotspot] :: Annotation extra -> Maybe Emphasis
+ Data.SGF.Types: [illegal] :: Move move -> FuzzyBool
+ Data.SGF.Types: [initialPlacement] :: GameInfoLinesOfAction -> InitialPlacement
+ Data.SGF.Types: [initialPositionLOA] :: GameInfoLinesOfAction -> InitialPosition
+ Data.SGF.Types: [invertYAxis] :: GameInfoLinesOfAction -> Bool
+ Data.SGF.Types: [judgment] :: Annotation extra -> Maybe (Judgment, Emphasis)
+ Data.SGF.Types: [komi] :: GameInfoGo -> Maybe Rational
+ Data.SGF.Types: [labels] :: Markup -> Map Point String
+ Data.SGF.Types: [lines] :: Markup -> Set (Point, Point)
+ Data.SGF.Types: [marks] :: Markup -> Map Point Mark
+ Data.SGF.Types: [markup] :: GameNode move stone ruleSet extraGameInfo extraAnnotation -> Markup
+ Data.SGF.Types: [month] :: PartialDate -> Integer
+ Data.SGF.Types: [move] :: Move move -> Maybe (Color, move)
+ Data.SGF.Types: [name] :: Annotation extra -> Maybe String
+ Data.SGF.Types: [number] :: Move move -> Maybe Integer
+ Data.SGF.Types: [numbering] :: Markup -> Maybe Numbering
+ Data.SGF.Types: [otherAnnotation] :: Annotation extra -> extra
+ Data.SGF.Types: [otherGameInfo] :: GameInfo ruleSet extra -> extra
+ Data.SGF.Types: [overtimeMovesBlack] :: Move move -> Maybe Integer
+ Data.SGF.Types: [overtimeMovesWhite] :: Move move -> Maybe Integer
+ Data.SGF.Types: [prongs] :: GameInfoOcti -> Integer
+ Data.SGF.Types: [quality] :: Move move -> Maybe Quality
+ Data.SGF.Types: [rankBlack] :: GameInfo ruleSet extra -> Maybe Rank
+ Data.SGF.Types: [rankWhite] :: GameInfo ruleSet extra -> Maybe Rank
+ Data.SGF.Types: [remove] :: Setup stone -> Set Point
+ Data.SGF.Types: [reserve] :: GameInfoOcti -> Integer
+ Data.SGF.Types: [result] :: GameInfo ruleSet extra -> Maybe GameResult
+ Data.SGF.Types: [round] :: GameInfo ruleSet extra -> Maybe Round
+ Data.SGF.Types: [ruleSet] :: GameInfo ruleSet extra -> Maybe (RuleSet ruleSet)
+ Data.SGF.Types: [size] :: Game -> Maybe (Integer, Integer)
+ Data.SGF.Types: [squaresBlack] :: GameInfoOcti -> Set Point
+ Data.SGF.Types: [squaresWhite] :: GameInfoOcti -> Set Point
+ Data.SGF.Types: [superProngs] :: GameInfoOcti -> Integer
+ Data.SGF.Types: [timeBlack] :: Move move -> Maybe Rational
+ Data.SGF.Types: [timeLimit] :: GameInfo ruleSet extra -> Maybe Rational
+ Data.SGF.Types: [timeWhite] :: Move move -> Maybe Rational
+ Data.SGF.Types: [toPlay] :: Setup stone -> Maybe Color
+ Data.SGF.Types: [tree] :: Game -> GameTree
+ Data.SGF.Types: [unknown] :: GameNode move stone ruleSet extraGameInfo extraAnnotation -> Map String [[Word8]]
+ Data.SGF.Types: [value] :: Annotation extra -> Maybe Rational
+ Data.SGF.Types: [variationType] :: Game -> Maybe (VariationType, AutoMarkup)
+ Data.SGF.Types: [visible] :: Markup -> Maybe (Set Point)
+ Data.SGF.Types: [year] :: PartialDate -> Integer
+ Data.SGF.Types: instance (GHC.Classes.Eq ruleSet, GHC.Classes.Eq extra) => GHC.Classes.Eq (Data.SGF.Types.GameInfo ruleSet extra)
+ Data.SGF.Types: instance (GHC.Classes.Eq ruleSet, GHC.Classes.Eq extraGameInfo, GHC.Classes.Eq stone, GHC.Classes.Eq move, GHC.Classes.Eq extraAnnotation) => GHC.Classes.Eq (Data.SGF.Types.GameNode move stone ruleSet extraGameInfo extraAnnotation)
+ Data.SGF.Types: instance (GHC.Classes.Ord ruleSet, GHC.Classes.Ord extra) => GHC.Classes.Ord (Data.SGF.Types.GameInfo ruleSet extra)
+ Data.SGF.Types: instance (GHC.Classes.Ord ruleSet, GHC.Classes.Ord extraGameInfo, GHC.Classes.Ord stone, GHC.Classes.Ord move, GHC.Classes.Ord extraAnnotation) => GHC.Classes.Ord (Data.SGF.Types.GameNode move stone ruleSet extraGameInfo extraAnnotation)
+ Data.SGF.Types: instance (GHC.Classes.Ord stone, GHC.Read.Read ruleSet, GHC.Read.Read extraGameInfo, GHC.Read.Read stone, GHC.Read.Read move, GHC.Read.Read extraAnnotation) => GHC.Read.Read (Data.SGF.Types.GameNode move stone ruleSet extraGameInfo extraAnnotation)
+ Data.SGF.Types: instance (GHC.Enum.Bounded k, GHC.Enum.Enum k, GHC.Classes.Ord k, GHC.Classes.Eq v) => GHC.Classes.Eq (k -> v)
+ Data.SGF.Types: instance (GHC.Enum.Bounded k, GHC.Enum.Enum k, GHC.Classes.Ord k, GHC.Classes.Ord v) => GHC.Classes.Ord (k -> v)
+ Data.SGF.Types: instance (GHC.Enum.Bounded k, GHC.Enum.Enum k, GHC.Classes.Ord k, GHC.Read.Read k, GHC.Read.Read v) => GHC.Read.Read (k -> v)
+ Data.SGF.Types: instance (GHC.Enum.Bounded k, GHC.Enum.Enum k, GHC.Classes.Ord k, GHC.Show.Show k, GHC.Show.Show v) => GHC.Show.Show (k -> v)
+ Data.SGF.Types: instance (GHC.Read.Read ruleSet, GHC.Read.Read extra) => GHC.Read.Read (Data.SGF.Types.GameInfo ruleSet extra)
+ Data.SGF.Types: instance (GHC.Read.Read stone, GHC.Classes.Ord stone) => GHC.Read.Read (Data.SGF.Types.Setup stone)
+ Data.SGF.Types: instance (GHC.Show.Show ruleSet, GHC.Show.Show extra) => GHC.Show.Show (Data.SGF.Types.GameInfo ruleSet extra)
+ Data.SGF.Types: instance (GHC.Show.Show ruleSet, GHC.Show.Show extraGameInfo, GHC.Show.Show stone, GHC.Show.Show move, GHC.Show.Show extraAnnotation) => GHC.Show.Show (Data.SGF.Types.GameNode move stone ruleSet extraGameInfo extraAnnotation)
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Certainty
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Color
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Emphasis
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Figure
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.FigureFlag
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.FuzzyBool
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Game
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.GameInfoGo
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.GameInfoLinesOfAction
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.GameInfoOcti
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.GameInfoType
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.GameResult
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.GameTree
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.GameType
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.InitialPlacement
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.InitialPosition
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Judgment
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.MajorVariation
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Mark
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Markup
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.MatchInfo
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.MinorVariation
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.MoveGo
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Numbering
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.PartialDate
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Quality
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Rank
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.RankScale
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Round
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.RuleSetBackgammon
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.RuleSetGo
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.RuleSetOcti
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.VariationType
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.ViewerSetting
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.Void
+ Data.SGF.Types: instance GHC.Classes.Eq Data.SGF.Types.WinType
+ Data.SGF.Types: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.SGF.Types.RuleSet a)
+ Data.SGF.Types: instance GHC.Classes.Eq extra => GHC.Classes.Eq (Data.SGF.Types.Annotation extra)
+ Data.SGF.Types: instance GHC.Classes.Eq move => GHC.Classes.Eq (Data.SGF.Types.Move move)
+ Data.SGF.Types: instance GHC.Classes.Eq stone => GHC.Classes.Eq (Data.SGF.Types.Setup stone)
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Certainty
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Color
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Emphasis
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Figure
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.FigureFlag
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.FuzzyBool
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.GameInfoGo
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.GameInfoLinesOfAction
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.GameInfoOcti
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.GameInfoType
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.GameResult
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.GameType
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.InitialPlacement
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.InitialPosition
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Judgment
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.MajorVariation
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Mark
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Markup
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.MatchInfo
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.MinorVariation
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.MoveGo
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Numbering
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.PartialDate
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Quality
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Rank
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.RankScale
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Round
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.RuleSetBackgammon
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.RuleSetGo
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.RuleSetOcti
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.VariationType
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.ViewerSetting
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.Void
+ Data.SGF.Types: instance GHC.Classes.Ord Data.SGF.Types.WinType
+ Data.SGF.Types: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.SGF.Types.RuleSet a)
+ Data.SGF.Types: instance GHC.Classes.Ord extra => GHC.Classes.Ord (Data.SGF.Types.Annotation extra)
+ Data.SGF.Types: instance GHC.Classes.Ord move => GHC.Classes.Ord (Data.SGF.Types.Move move)
+ Data.SGF.Types: instance GHC.Classes.Ord stone => GHC.Classes.Ord (Data.SGF.Types.Setup stone)
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.Certainty
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.Color
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.Emphasis
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.FigureFlag
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.FuzzyBool
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.GameInfoType
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.GameType
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.InitialPlacement
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.InitialPosition
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.Judgment
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.MajorVariation
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.Mark
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.Numbering
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.RankScale
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.RuleSetBackgammon
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.RuleSetGo
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.VariationType
+ Data.SGF.Types: instance GHC.Enum.Bounded Data.SGF.Types.ViewerSetting
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.Certainty
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.Color
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.Emphasis
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.FigureFlag
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.FuzzyBool
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.GameInfoType
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.GameType
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.InitialPlacement
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.InitialPosition
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.Judgment
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.MajorVariation
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.Mark
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.Numbering
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.RankScale
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.RuleSetBackgammon
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.RuleSetGo
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.VariationType
+ Data.SGF.Types: instance GHC.Enum.Enum Data.SGF.Types.ViewerSetting
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Certainty
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Color
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Emphasis
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Figure
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.FigureFlag
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.FuzzyBool
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Game
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.GameInfoGo
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.GameInfoLinesOfAction
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.GameInfoOcti
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.GameInfoType
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.GameResult
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.GameTree
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.GameType
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.InitialPlacement
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.InitialPosition
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Judgment
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.MajorVariation
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Mark
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Markup
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.MatchInfo
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.MinorVariation
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.MoveGo
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Numbering
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.PartialDate
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Quality
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Rank
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.RankScale
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Round
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.RuleSetBackgammon
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.RuleSetGo
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.RuleSetOcti
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.VariationType
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.ViewerSetting
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.Void
+ Data.SGF.Types: instance GHC.Read.Read Data.SGF.Types.WinType
+ Data.SGF.Types: instance GHC.Read.Read a => GHC.Read.Read (Data.SGF.Types.RuleSet a)
+ Data.SGF.Types: instance GHC.Read.Read extra => GHC.Read.Read (Data.SGF.Types.Annotation extra)
+ Data.SGF.Types: instance GHC.Read.Read move => GHC.Read.Read (Data.SGF.Types.Move move)
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Certainty
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Color
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Emphasis
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Figure
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.FigureFlag
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.FuzzyBool
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Game
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.GameInfoGo
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.GameInfoLinesOfAction
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.GameInfoOcti
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.GameInfoType
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.GameResult
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.GameTree
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.GameType
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.InitialPlacement
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.InitialPosition
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Judgment
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.MajorVariation
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Mark
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Markup
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.MatchInfo
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.MinorVariation
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.MoveGo
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Numbering
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.PartialDate
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Quality
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Rank
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.RankScale
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Round
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.RuleSetBackgammon
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.RuleSetGo
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.RuleSetOcti
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.VariationType
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.ViewerSetting
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.Void
+ Data.SGF.Types: instance GHC.Show.Show Data.SGF.Types.WinType
+ Data.SGF.Types: instance GHC.Show.Show a => GHC.Show.Show (Data.SGF.Types.RuleSet a)
+ Data.SGF.Types: instance GHC.Show.Show extra => GHC.Show.Show (Data.SGF.Types.Annotation extra)
+ Data.SGF.Types: instance GHC.Show.Show move => GHC.Show.Show (Data.SGF.Types.Move move)
+ Data.SGF.Types: instance GHC.Show.Show stone => GHC.Show.Show (Data.SGF.Types.Setup stone)
- Data.SGF.Parse: InvalidDatesClipped :: (Set PartialDate) -> Warning
+ Data.SGF.Parse: InvalidDatesClipped :: Set PartialDate -> Warning
- Data.SGF.Types: OctiRuleSet :: MajorVariation -> (Set MinorVariation) -> RuleSetOcti
+ Data.SGF.Types: OctiRuleSet :: MajorVariation -> Set MinorVariation -> RuleSetOcti
- Data.SGF.Types: Ranked :: Integer -> RankScale -> (Maybe Certainty) -> Rank
+ Data.SGF.Types: Ranked :: Integer -> RankScale -> Maybe Certainty -> Rank
Files
- Data/SGF/Parse.hs +518/−309
- Data/SGF/Parse/Encodings.hs +34/−18
- sgf.cabal +4/−7
Data/SGF/Parse.hs view
@@ -1,21 +1,29 @@+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+ -- TODO: check that every occurrence of "die" should really be a death, and not just a "fix-it-up-and-warn" -- boilerplate {{{-{-# LANGUAGE NoMonomorphismRestriction, FlexibleContexts #-}-module Data.SGF.Parse (- collection,- clipDate,- PropertyType(..),- properties,- extraProperties,- Property(..),- Warning(..),- ErrorType(..),- Error(..)-) where+-- TODO: check that every occurrence of "die" should really be a death, and not just a "fix-it-up-and-warn"+-- boilerplate {{{+module Data.SGF.Parse+ ( collection+ , clipDate+ , PropertyType(..)+ , properties+ , extraProperties+ , Property(..)+ , Warning(..)+ , ErrorType(..)+ , Error(..)+ ) where import Control.Applicative import Control.Arrow import Control.Monad+import Control.Monad.Fail import Control.Monad.Reader import Control.Monad.State import Control.Monad.Writer@@ -25,32 +33,40 @@ import Data.Function import Data.List import Data.List.Split+import qualified Data.Map as Map import Data.Maybe import Data.Ord+import Data.SGF.Parse.Encodings+import Data.SGF.Parse.Raw hiding (collection)+import qualified Data.SGF.Parse.Raw as Raw+import Data.SGF.Parse.Util+import Data.SGF.Types (Game(Game), GameNode(GameNode))+import Data.SGF.Types hiding+ ( Game(..)+ , GameInfo(..)+ , GameNode(..)+ , Move(..)+ , Setup(..)+ )+import qualified Data.SGF.Types as T+import qualified Data.Set as Set import Data.Time.Calendar import Data.Tree import Data.Word-import Prelude hiding (round)+import Prelude hiding (round) import Text.Parsec hiding (newline)-import Text.Parsec.Pos (newPos)+import Text.Parsec.Pos (newPos) -import qualified Data.Map as Map-import qualified Data.Set as Set+instance MonadFail (Either Error) where+ fail :: String -> Either Error a+ fail msg = Left (UnknownError (Just msg)) -import Data.SGF.Parse.Encodings-import Data.SGF.Parse.Raw hiding (collection)-import Data.SGF.Types hiding (Game(..), GameInfo(..), GameNode(..), Setup(..), Move(..))-import Data.SGF.Types (Game(Game), GameNode(GameNode))-import Data.SGF.Parse.Util-import qualified Data.SGF.Parse.Raw as Raw-import qualified Data.SGF.Types as T--- }}}--- top level/testing {{{-translate trans state = case runStateT (runWriterT trans) state of- Left (UnknownError Nothing ) -> fail ""- Left (UnknownError (Just e)) -> fail e- Left e -> setPosition (errorPosition e) >> fail (show e)- Right ((a, warnings), _) -> return (a, warnings)+translate trans state =+ case runStateT (runWriterT trans) state of+ Left (UnknownError Nothing) -> fail ""+ Left (UnknownError (Just e)) -> fail e+ Left e -> setPosition (errorPosition e) >> fail (show e)+ Right ((a, warnings), _) -> return (a, warnings) -- TODO: delete "test" test = runParser collection () "<interactive>" . map enum@@ -62,7 +78,9 @@ -- accumulated in the ['Warning'] return) and unrecoverable ones (which will -- result in parse errors). collection :: Stream s m Word8 => ParsecT s u m (Collection, [Warning])-collection = second concat . unzip <$> (mapM (translate gameTree) =<< Raw.collection)+collection =+ second concat . unzip <$> (mapM (translate gameTree) =<< Raw.collection)+ gameTree = do hea <- parseHeader app <- application hea@@ -70,162 +88,212 @@ var <- variationType siz <- size gam fmap (Game app var siz) (parse hea gam siz False)- where- parse h g s = case g of- Go -> fmap TreeGo . nodeGo h s- Backgammon -> fmap TreeBackgammon . nodeBackgammon h- LinesOfAction -> fmap TreeLinesOfAction . nodeLinesOfAction h- Hex -> gameHex h- Octi -> fmap TreeOcti . nodeOcti h- other -> fmap (TreeOther other) . nodeOther h+ where+ parse h g s =+ case g of+ Go -> fmap TreeGo . nodeGo h s+ Backgammon -> fmap TreeBackgammon . nodeBackgammon h+ LinesOfAction -> fmap TreeLinesOfAction . nodeLinesOfAction h+ Hex -> gameHex h+ Octi -> fmap TreeOcti . nodeOcti h+ other -> fmap (TreeOther other) . nodeOther h+ -- }}}-warnAll w ps = mapM_ (\p -> maybe (return ()) (tell . (:[]) . w) =<< consume p) ps-dieEarliest e ps = dieWith e . head . sortBy (comparing position) . catMaybes =<< mapM consume ps+warnAll w ps =+ mapM_ (\p -> maybe (return ()) (tell . (: []) . w) =<< consume p) ps++dieEarliest e ps =+ dieWith e . head . sortBy (comparing position) . catMaybes =<<+ mapM consume ps+ -- game header information {{{-getFormat = do+getFormat = do prop <- consumeSingle "FF"- ff <- maybe (return 1) number prop- when (ff /= 4) (dieWithPos FormatUnsupported (maybe (newPos "FF_missing" 1 1) position prop))+ ff <- maybe (return 1) number prop+ when+ (ff /= 4)+ (dieWithPos+ FormatUnsupported+ (maybe (newPos "FF_missing" 1 1) position prop)) return ff getEncoding = do ws <- consumeSingle "CA" case maybe [encodingFromString "latin1"] (guessEncoding . head . values) ws of- [encoding] -> return encoding- [] -> dieWithJust UnknownEncoding ws- _ -> dieWithJust AmbiguousEncoding ws -- pretty much guaranteed not to happen+ [encoding] -> return encoding+ [] -> dieWithJust UnknownEncoding ws+ _ -> dieWithJust AmbiguousEncoding ws -- pretty much guaranteed not to happen parseHeader = liftM2 Header getFormat getEncoding application = flip transMap "AP" . join compose . simple-gameType = do++gameType = do property <- consumeSingle "GM" gameType <- maybe (return 1) number property- if enum (minBound :: GameType) <= gameType && gameType <= enum (maxBound :: GameType)+ if enum (minBound :: GameType) <= gameType &&+ gameType <= enum (maxBound :: GameType) then return (enum gameType) else dieWithJust OutOfBounds property-variationType = transMap (\p -> number p >>= variationType' p) "ST" where- variationType' property 0 = return (T.Children, True )- variationType' property 1 = return (T.Siblings, True )++variationType = transMap (\p -> number p >>= variationType' p) "ST"+ where+ variationType' property 0 = return (T.Children, True)+ variationType' property 1 = return (T.Siblings, True) variationType' property 2 = return (T.Children, False) variationType' property 3 = return (T.Siblings, False) variationType' property _ = dieWith OutOfBounds property+ size gameType = do property <- consumeSingle "SZ" case property of Nothing -> return $ lookup gameType defaultSize- Just p -> if enum ':' `elem` head (values p)- then do- (m, n) <- join compose number p- when (m == n) . tell . return . SquareSizeSpecifiedAsRectangle . position $ p- checkValidity gameType m n property- else do- m <- number p- checkValidity gameType m m property- where- invalid t m n = or [t == Go && (m > 52 || n > 52), m < 1, n < 1]- checkValidity t m n p = when (invalid t m n) (dieWithJust OutOfBounds p) >> return (Just (m, n))+ Just p ->+ if enum ':' `elem` head (values p)+ then do+ (m, n) <- join compose number p+ when (m == n) .+ tell .+ return . SquareSizeSpecifiedAsRectangle . position $+ p+ checkValidity gameType m n property+ else do+ m <- number p+ checkValidity gameType m m property+ where+ invalid t m n = or [t == Go && (m > 52 || n > 52), m < 1, n < 1]+ checkValidity t m n p =+ when (invalid t m n) (dieWithJust OutOfBounds p) >> return (Just (m, n))+ -- }}} -- game-info properties {{{ gameInfo header =- consumeFreeformGameInfo header- >>= consumeUpdateGameInfo rank (\g v -> g { T.rankBlack = v }) "BR" header- >>= consumeUpdateGameInfo rank (\g v -> g { T.rankWhite = v }) "WR" header- >>= consumeUpdateGameInfo round (\g v -> g { T.round = v }) "RO" header- >>= consumeUpdateGameInfoMaybe result (\g v -> g { T.result = v }) "RE" header- >>= consumeUpdateGameInfoMaybe date dateUpdate "DT" header- >>= warnClipDate- >>= timeLimit+ consumeFreeformGameInfo header >>=+ consumeUpdateGameInfo rank (\g v -> g {T.rankBlack = v}) "BR" header >>=+ consumeUpdateGameInfo rank (\g v -> g {T.rankWhite = v}) "WR" header >>=+ consumeUpdateGameInfo round (\g v -> g {T.round = v}) "RO" header >>=+ consumeUpdateGameInfoMaybe result (\g v -> g {T.result = v}) "RE" header >>=+ consumeUpdateGameInfoMaybe date dateUpdate "DT" header >>=+ warnClipDate >>=+ timeLimit -freeformGameInfo = [- ("AN", T.Annotator ),- ("BT", T.TeamName Black ),- ("CP", T.Copyright ),- ("EV", T.Event ),- ("GN", T.GameName ),- ("GC", T.Context ),- ("ON", T.Opening ),- ("OT", T.Overtime ),- ("PB", T.PlayerName Black),- ("PC", T.Location ),- ("PW", T.PlayerName White),- ("SO", T.Source ),- ("US", T.User ),- ("WT", T.TeamName White )+freeformGameInfo =+ [ ("AN", T.Annotator)+ , ("BT", T.TeamName Black)+ , ("CP", T.Copyright)+ , ("EV", T.Event)+ , ("GN", T.GameName)+ , ("GC", T.Context)+ , ("ON", T.Opening)+ , ("OT", T.Overtime)+ , ("PB", T.PlayerName Black)+ , ("PC", T.Location)+ , ("PW", T.PlayerName White)+ , ("SO", T.Source)+ , ("US", T.User)+ , ("WT", T.TeamName White) ]-consumeFreeformGameInfo header = fmap gameInfo tagValues where++consumeFreeformGameInfo header = fmap gameInfo tagValues+ where (tags, types) = unzip freeformGameInfo- tagValues = mapM (transMap (simple header)) tags- gameInfo vals = (\m -> emptyGameInfo { T.freeform = m })- . Map.fromList . catMaybes- $ zipWith (fmap . (,)) types vals+ tagValues = mapM (transMap (simple header)) tags+ gameInfo vals =+ (\m -> emptyGameInfo {T.freeform = m}) . Map.fromList . catMaybes $+ zipWith (fmap . (,)) types vals consumeUpdateGameInfo = consumeUpdateGameInfoMaybe . (return .)+ consumeUpdateGameInfoMaybe fromString update property header gameInfo = do- maybeProp <- consumeSingle property+ maybeProp <- consumeSingle property maybeString <- transMap' (simple header) maybeProp case (maybeProp, maybeString >>= fromString) of (Nothing, _) -> return gameInfo (_, Nothing) -> dieWithJust BadlyFormattedValue maybeProp- (_, v) -> return (update gameInfo v)+ (_, v) -> return (update gameInfo v) abbreviateList xs = xs >>= \(n, v) -> [(n, v), (take 1 n, v)]+ -- TODO: can we unify this with the other implementation of reading a rational?-readRational s = liftM3 (\s n d -> s * (fromInteger n + d)) maybeSign maybeNum maybeDen where- (sign, rest) = span (`elem` "+-") s+readRational s =+ liftM3 (\s n d -> s * (fromInteger n + d)) maybeSign maybeNum maybeDen+ where+ (sign, rest) = span (`elem` "+-") s (numerator, rest') = span isDigit rest- denominator' = drop 1 rest' ++ "0"- denominator = fromInteger (read denominator') / 10 ^ length denominator'-+ denominator' = drop 1 rest' ++ "0"+ denominator = fromInteger (read denominator') / 10 ^ length denominator' maybeSign = lookup sign [("", 1), ("+", 1), ("-", -1)]- maybeNum = listToMaybe numerator >> return (read numerator)- maybeDen = guard (take 1 rest' `isPrefixOf` "." && all isDigit denominator') >> return denominator+ maybeNum = listToMaybe numerator >> return (read numerator)+ maybeDen =+ guard (take 1 rest' `isPrefixOf` "." && all isDigit denominator') >>+ return denominator -rank s = fromMaybe (OtherRank s) maybeRanked where- (rank, rest) = span isDigit s- (scale, certainty) = span isAlpha rest- maybeRank = listToMaybe rank >> return (read rank)- maybeScale = lookup (map toLower scale) scales- maybeCertainty = lookup certainty certainties+rank s = fromMaybe (OtherRank s) maybeRanked+ where+ (rank, rest) = span isDigit s+ (scale, certainty) = span isAlpha rest+ maybeRank = listToMaybe rank >> return (read rank)+ maybeScale = lookup (map toLower scale) scales+ maybeCertainty = lookup certainty certainties maybeRanked = liftM3 Ranked maybeRank maybeScale maybeCertainty certainties = [("", Nothing), ("?", Just Uncertain), ("*", Just Certain)]- scales = abbreviateList [("kyu", Kyu), ("dan", Dan), ("pro", Pro)]--result (c:'+':score) = liftM2 Win maybeColor maybeWinType where- maybeColor = lookup (toLower c) [('b', Black), ('w', White)]- maybeWinType = lookup (map toLower score) winTypes `mplus` fmap Score (readRational score)- winTypes = abbreviateList [("", OtherWinType), ("forfeit", Forfeit), ("time", Time), ("resign", Resign)]+ scales = abbreviateList [("kyu", Kyu), ("dan", Dan), ("pro", Pro)] -result s = lookup (map toLower s) [("0", Draw), ("draw", Draw), ("void", Void), ("?", Unknown)]+result (c:'+':score) = liftM2 Win maybeColor maybeWinType+ where+ maybeColor = lookup (toLower c) [('b', Black), ('w', White)]+ maybeWinType =+ lookup (map toLower score) winTypes `mplus`+ fmap Score (readRational score)+ winTypes =+ abbreviateList+ [ ("", OtherWinType)+ , ("forfeit", Forfeit)+ , ("time", Time)+ , ("resign", Resign)+ ]+result s =+ lookup+ (map toLower s)+ [("0", Draw), ("draw", Draw), ("void", Void), ("?", Unknown)] -timeLimit gameInfo = fmap (\v -> gameInfo { T.timeLimit = v }) (transMap real "TM")+timeLimit gameInfo =+ fmap (\v -> gameInfo {T.timeLimit = v}) (transMap real "TM") -date = expect [] . splitWhen (== ',') where+date = expect [] . splitWhen (== ',')+ where expect parsers [] = return [] expect parsers (pd:pds) = do- parsed <- msum . sequence ([parseYMD, parseYM, parseY] ++ parsers) . splitWhen (== '-') $ pd- liftM (parsed:) . ($ pds) $ case parsed of- Year {} -> expect []- Month { year = y } -> expect [parseMD y, parseM y]- Day { year = y, month = m } -> expect [parseMD y, parseD y m]-+ parsed <-+ msum .+ sequence ([parseYMD, parseYM, parseY] ++ parsers) .+ splitWhen (== '-') $+ pd+ liftM (parsed :) . ($ pds) $+ case parsed of+ Year {} -> expect []+ Month {year = y} -> expect [parseMD y, parseM y]+ Day {year = y, month = m} -> expect [parseMD y, parseD y m] ensure p x = guard (p x) >> return x- hasLength n xs = n >= 0 && hasLength' n xs where- hasLength' n [] = n == 0+ hasLength n xs = n >= 0 && hasLength' n xs+ where+ hasLength' n [] = n == 0 hasLength' 0 (x:xs) = False- hasLength' n (x:xs) = hasLength' (n-1) xs+ hasLength' n (x:xs) = hasLength' (n - 1) xs ensureLength = ensure . hasLength-- parseYMD ss = ensureLength 3 ss >>= \[y, m, d] -> liftM3 Day (checkY y) (checkMD m) (checkMD d)- parseYM ss = ensureLength 2 ss >>= \[y, m ] -> liftM2 Month (checkY y) (checkMD m)- parseY ss = ensureLength 1 ss >>= \[y ] -> liftM Year (checkY y)- parseMD y ss = ensureLength 2 ss >>= \[ m, d] -> liftM2 (Day y) (checkMD m) (checkMD d)- parseM y ss = ensureLength 1 ss >>= \[ m ] -> liftM (Month y) (checkMD m)- parseD y m ss = ensureLength 1 ss >>= \[ d] -> liftM (Day y m) (checkMD d)-- checkY y = ensureLength 4 y >>= readM+ parseYMD ss =+ ensureLength 3 ss >>= \[y, m, d] ->+ liftM3 Day (checkY y) (checkMD m) (checkMD d)+ parseYM ss =+ ensureLength 2 ss >>= \[y, m] -> liftM2 Month (checkY y) (checkMD m)+ parseY ss = ensureLength 1 ss >>= \[y] -> liftM Year (checkY y)+ parseMD y ss =+ ensureLength 2 ss >>= \[m, d] -> liftM2 (Day y) (checkMD m) (checkMD d)+ parseM y ss = ensureLength 1 ss >>= \[m] -> liftM (Month y) (checkMD m)+ parseD y m ss = ensureLength 1 ss >>= \[d] -> liftM (Day y m) (checkMD d)+ checkY y = ensureLength 4 y >>= readM checkMD md = ensureLength 2 md >>= readM- readM = listToMaybe . map fst . filter (null . snd) . reads+ readM = listToMaybe . map fst . filter (null . snd) . reads -- | -- Clip to a valid, representable date. Years are clipped to the 0000-9999@@ -235,65 +303,102 @@ -- -- If a parsed date is changed by this function, a warning is emitted. clipDate :: PartialDate -> PartialDate-clipDate (y@Year {}) = Year . min 9999 . max 0 . year $ y-clipDate (Month { year = y, month = m }) = Month {- year = year . clipDate . Year $ y,- month = min 12 . max 1 $ m- }-clipDate (Day { year = y, month = m, day = d }) = let m' = clipDate (Month y m) in Day {- year = year m', month = month m',- day = max 1 . min (fromIntegral (gregorianMonthLength (year m') (fromIntegral (month m')))) $ d- }+clipDate (y@Year {}) = Year . min 9999 . max 0 . year $ y+clipDate (Month {year = y, month = m}) =+ Month {year = year . clipDate . Year $ y, month = min 12 . max 1 $ m}+clipDate (Day {year = y, month = m, day = d}) =+ let m' = clipDate (Month y m)+ in Day+ { year = year m'+ , month = month m'+ , day =+ max 1 .+ min+ (fromIntegral+ (gregorianMonthLength+ (year m')+ (fromIntegral (month m')))) $+ d+ } -warnClipDate gameInfo@(T.GameInfo { T.date = d }) = let d' = Set.map clipDate d in do- when (d /= d') (tell [InvalidDatesClipped d])- return gameInfo { T.date = d' }+warnClipDate gameInfo@(T.GameInfo {T.date = d}) =+ let d' = Set.map clipDate d+ in do when (d /= d') (tell [InvalidDatesClipped d])+ return gameInfo {T.date = d'} -dateUpdate g v = g { T.date = maybe Set.empty Set.fromList v }+dateUpdate g v = g {T.date = maybe Set.empty Set.fromList v} -round s = case words s of- [roundNumber@(_:_)] | all isDigit roundNumber- -> SimpleRound (read roundNumber)- [roundNumber@(_:_), '(':roundType] | all isDigit roundNumber && last roundType == ')'- -> FormattedRound (read roundNumber) (init roundType)- _ -> OtherRound s+round s =+ case words s of+ [roundNumber@(_:_)]+ | all isDigit roundNumber -> SimpleRound (read roundNumber)+ [roundNumber@(_:_), '(':roundType]+ | all isDigit roundNumber && last roundType == ')' ->+ FormattedRound (read roundNumber) (init roundType)+ _ -> OtherRound s+ -- }}} -- move properties {{{ move move = do- color_ <- mapM has ["B", "W"]- [number_, overtimeMovesBlack_, overtimeMovesWhite_] <- mapM (transMap number) ["MN", "OB", "OW"]- [timeBlack_, timeWhite_] <- mapM (transMap real ) ["BL", "WL"]- let partialMove = emptyMove {- T.number = number_,- T.timeBlack = timeBlack_,- T.timeWhite = timeWhite_,- T.overtimeMovesBlack = overtimeMovesBlack_,- T.overtimeMovesWhite = overtimeMovesWhite_- }+ color_ <- mapM has ["B", "W"]+ [number_, overtimeMovesBlack_, overtimeMovesWhite_] <-+ mapM (transMap number) ["MN", "OB", "OW"]+ [timeBlack_, timeWhite_] <- mapM (transMap real) ["BL", "WL"]+ let partialMove =+ emptyMove+ { T.number = number_+ , T.timeBlack = timeBlack_+ , T.timeWhite = timeWhite_+ , T.overtimeMovesBlack = overtimeMovesBlack_+ , T.overtimeMovesWhite = overtimeMovesWhite_+ } case color_ of- [False, False] -> warnAll MovelessAnnotationOmitted ["KO", "BM", "DO", "IT", "TE"] >> return partialMove- [True , True ] -> dieEarliest ConcurrentBlackAndWhiteMove ["B", "W"]- [black, white] -> let color = if black then Black else White in do- Just move <- fmap msum . mapM (transMap move) $ ["B", "W"]- illegal <- fmap (maybe Possibly (const Definitely)) (transMap none "KO")- annotations <- mapM has ["BM", "DO", "IT", "TE"]- quality <- case annotations of- [False, False, False, False] -> return Nothing- [True , False, False, False] -> fmap (fmap Bad ) (transMap double "BM")- [False, False, False, True ] -> fmap (fmap Good) (transMap double "TE")- [False, True , False, False] -> transMap none "DO" >> return (Just Doubtful )- [False, False, True , False] -> transMap none "IT" >> return (Just Interesting)- _ -> dieEarliest ConcurrentAnnotations ["BM", "DO", "IT", "TE"]- return partialMove { T.move = Just (color, move), T.illegal = illegal, T.quality = quality }+ [False, False] ->+ warnAll MovelessAnnotationOmitted ["KO", "BM", "DO", "IT", "TE"] >>+ return partialMove+ [True, True] -> dieEarliest ConcurrentBlackAndWhiteMove ["B", "W"]+ [black, white] ->+ let color =+ if black+ then Black+ else White+ in do Just move <- fmap msum . mapM (transMap move) $ ["B", "W"]+ illegal <-+ fmap+ (maybe Possibly (const Definitely))+ (transMap none "KO")+ annotations <- mapM has ["BM", "DO", "IT", "TE"]+ quality <-+ case annotations of+ [False, False, False, False] -> return Nothing+ [True, False, False, False] ->+ fmap (fmap Bad) (transMap double "BM")+ [False, False, False, True] ->+ fmap (fmap Good) (transMap double "TE")+ [False, True, False, False] ->+ transMap none "DO" >> return (Just Doubtful)+ [False, False, True, False] ->+ transMap none "IT" >> return (Just Interesting)+ _ ->+ dieEarliest+ ConcurrentAnnotations+ ["BM", "DO", "IT", "TE"]+ return+ partialMove+ { T.move = Just (color, move)+ , T.illegal = illegal+ , T.quality = quality+ }+ -- }}} -- setup properties {{{ setupPoint point = do points <- mapM (transMapList (listOfPoint point)) ["AB", "AW", "AE"] let [addBlack, addWhite, remove] = map Set.fromList points- allPoints = addBlack `Set.union` addWhite `Set.union` remove+ allPoints = addBlack `Set.union` addWhite `Set.union` remove duplicates = concat points \\ Set.elems allPoints- addWhite' = addWhite Set.\\ addBlack- remove' = remove Set.\\ (addBlack `Set.union` addWhite')+ addWhite' = addWhite Set.\\ addBlack+ remove' = remove Set.\\ (addBlack `Set.union` addWhite') unless (null duplicates) (tell [DuplicateSetupOperationsOmitted duplicates]) setupFinish addBlack addWhite' remove' @@ -301,72 +406,81 @@ -- addWhite, and remove specify disjoint sets of points -- TODO: what, really, cannot? even if we allow ourselves a class constraint or something? setupPointStone point stone = do- addBlack <- transMapList (listOf stone) "AB"- addWhite <- transMapList (listOf stone) "AW"- remove <- transMapList (listOfPoint point) "AE"- setupFinish (Set.fromList addBlack) (Set.fromList addWhite) (Set.fromList remove)+ addBlack <- transMapList (listOf stone) "AB"+ addWhite <- transMapList (listOf stone) "AW"+ remove <- transMapList (listOfPoint point) "AE"+ setupFinish+ (Set.fromList addBlack)+ (Set.fromList addWhite)+ (Set.fromList remove) setupFinish addBlack addWhite remove = liftM (T.Setup addBlack addWhite remove) (transMap color "PL")+ -- }}} -- none properties {{{ annotation header = do- comment <- transMap (text header) "C"- name <- transMap (simple header) "N"- hotspot <- transMap double "HO"- value <- transMap real "V"- judgments' <- mapM (transMap double) ["GW", "GB", "DM", "UC"]+ comment <- transMap (text header) "C"+ name <- transMap (simple header) "N"+ hotspot <- transMap double "HO"+ value <- transMap real "V"+ judgments' <- mapM (transMap double) ["GW", "GB", "DM", "UC"] let judgments = [(j, e) | (j, Just e) <- zip [GoodForWhite ..] judgments'] tell . map ExtraPositionalJudgmentOmitted . drop 1 $ judgments- return emptyAnnotation {- T.comment = comment,- T.name = name,- T.hotspot = hotspot,- T.value = value,- T.judgment = listToMaybe judgments- }+ return+ emptyAnnotation+ { T.comment = comment+ , T.name = name+ , T.hotspot = hotspot+ , T.value = value+ , T.judgment = listToMaybe judgments+ } -addMarks marks (mark, points) = tell warning >> return result where+addMarks marks (mark, points) = tell warning >> return result+ where (ignored, inserted) = partition (`Map.member` marks) points warning = map (DuplicateMarkupOmitted . (,) mark) ignored- result = marks `Map.union` Map.fromList [(i, mark) | i <- inserted]+ result = marks `Map.union` Map.fromList [(i, mark) | i <- inserted] markup header point = do- markedPoints <- mapM (transMapList (listOfPoint point)) ["CR", "MA", "SL", "SQ", "TR"]- marks <- foldM addMarks Map.empty . zip [Circle ..] $ markedPoints- labels <- transMapList (listOf (compose point (simple header))) "LB"- arrows <- consumePointPairs "AR"- lines <- consumePointPairs "LN"- dim <- transMapMulti ( listOfPoint point) "DD"- visible <- transMapMulti (elistOfPoint point) "VW"- numbering <- transMap number "PM"- figure <- transMap (figurePTranslator header) "FG"-+ markedPoints <-+ mapM (transMapList (listOfPoint point)) ["CR", "MA", "SL", "SQ", "TR"]+ marks <- foldM addMarks Map.empty . zip [Circle ..] $ markedPoints+ labels <- transMapList (listOf (compose point (simple header))) "LB"+ arrows <- consumePointPairs "AR"+ lines <- consumePointPairs "LN"+ dim <- transMapMulti (listOfPoint point) "DD"+ visible <- transMapMulti (elistOfPoint point) "VW"+ numbering <- transMap number "PM"+ figure <- transMap (figurePTranslator header) "FG" tell . map DuplicateLabelOmitted $ labels \\ nubBy (on (==) fst) labels tell [UnknownNumberingIgnored n | Just n <- [numbering], n < 0 || n > 2]- -- TODO: some kind of warning when omitting arrows and lines-- return Markup {- T.marks = marks,- T.labels = Map.fromList labels,- T.arrows = prune arrows,- T.lines = prune . map canonicalize $ lines,- T.dim = fmap Set.fromList dim,- T.visible = fmap Set.fromList visible,- T.numbering = numbering >>= flip lookup (zip [0..] [Unnumbered ..]),- T.figure = figure- }- where+ -- TODO: some kind of warning when omitting arrows and lines+ return+ Markup+ { T.marks = marks+ , T.labels = Map.fromList labels+ , T.arrows = prune arrows+ , T.lines = prune . map canonicalize $ lines+ , T.dim = fmap Set.fromList dim+ , T.visible = fmap Set.fromList visible+ , T.numbering =+ numbering >>= flip lookup (zip [0 ..] [Unnumbered ..])+ , T.figure = figure+ }+ where consumePointPairs = transMapList (listOf (join compose point)) prune = Set.fromList . filter (uncurry (/=)) canonicalize (x, y) = (min x y, max x y) -figurePTranslator header (Property { values = [[]] }) = return DefaultFigure+figurePTranslator header (Property {values = [[]]}) = return DefaultFigure figurePTranslator header p = do (flags, name) <- compose number (simple header) p- return $ if testBit flags 16- then NamedDefaultFigure name- else NamedFigure name (not . testBit flags . fromEnum)+ return $+ if testBit flags 16+ then NamedDefaultFigure name+ else NamedFigure name (not . testBit flags . fromEnum)+ -- }}} -- known properties list {{{ -- |@@ -376,128 +490,223 @@ | Setup | Root | GameInfo- | Inherit -- ^- -- Technically, these properties have type \"none\" and- -- /attribute/ \"inherit\", but the property index lists them as- -- properties of type \"inherit\" with no attributes, so we- -- follow that lead.+ -- |+ -- Technically, these properties have type \"none\" and+ -- /attribute/ \"inherit\", but the property index lists them as+ -- properties of type \"inherit\" with no attributes, so we+ -- follow that lead.+ | Inherit | None deriving (Eq, Ord, Show, Read, Enum, Bounded) -- | -- All properties of each type listed in the SGF specification. properties :: GameType -> PropertyType -> [String]-properties = liftM2 (++) properties' . extraProperties where- properties' Move = ["B", "KO", "MN", "W", "BM", "DO", "IT", "TE", "BL", "OB", "OW", "WL"]- properties' Setup = ["AB", "AE", "AW", "PL"]- properties' Root = ["AP", "CA", "FF", "GM", "ST", "SZ"]- properties' GameInfo = ["AN", "BR", "BT", "CP", "DT", "EV", "GN", "GC", "ON", "OT", "PB", "PC", "PW", "RE", "RO", "RU", "SO", "TM", "US", "WR", "WT"]- properties' Inherit = ["DD", "PM", "VW"]- properties' None = ["C", "DM", "GB", "GW", "HO", "N", "UC", "V", "AR", "CR", "LB", "LN", "MA", "SL", "SQ", "TR", "FG"]+properties = liftM2 (++) properties' . extraProperties+ where+ properties' Move =+ ["B", "KO", "MN", "W", "BM", "DO", "IT", "TE", "BL", "OB", "OW", "WL"]+ properties' Setup = ["AB", "AE", "AW", "PL"]+ properties' Root = ["AP", "CA", "FF", "GM", "ST", "SZ"]+ properties' GameInfo =+ [ "AN"+ , "BR"+ , "BT"+ , "CP"+ , "DT"+ , "EV"+ , "GN"+ , "GC"+ , "ON"+ , "OT"+ , "PB"+ , "PC"+ , "PW"+ , "RE"+ , "RO"+ , "RU"+ , "SO"+ , "TM"+ , "US"+ , "WR"+ , "WT"+ ]+ properties' Inherit = ["DD", "PM", "VW"]+ properties' None =+ [ "C"+ , "DM"+ , "GB"+ , "GW"+ , "HO"+ , "N"+ , "UC"+ , "V"+ , "AR"+ , "CR"+ , "LB"+ , "LN"+ , "MA"+ , "SL"+ , "SQ"+ , "TR"+ , "FG"+ ]+ -- }}} -- game-specific stuff {{{-defaultSize = [- (Go , (19, 19)),- (Chess , ( 8, 8)),- (LinesOfAction , ( 8, 8)),- (Hex , (11, 11)),- (Amazons , (10, 10)),- (Gess , (20, 20))+defaultSize =+ [ (Go, (19, 19))+ , (Chess, (8, 8))+ , (LinesOfAction, (8, 8))+ , (Hex, (11, 11))+ , (Amazons, (10, 10))+ , (Gess, (20, 20)) ] -ruleSetLookup rs = flip lookup rs . map toLower-ruleSetGo = ruleSetLookup [- ("aga" , AGA),- ("goe" , GOE),- ("chinese" , Chinese),- ("japanese" , Japanese),- ("nz" , NewZealand)- ]-ruleSetBackgammon = ruleSetLookup [- ("crawford" , Crawford),- ("crawford:crawfordgame" , CrawfordGame),- ("jacoby" , Jacoby)- ]-ruleSetOcti s = case break (== ':') s of- (major, ':':minors) -> liftM (flip OctiRuleSet (minorVariations minors )) (majorVariation major )- (majorOrMinors, "") -> liftM (flip OctiRuleSet (Set.empty )) (majorVariation majorOrMinors)- `mplus` return (OctiRuleSet Full (minorVariations majorOrMinors))- where- majorVariation = ruleSetLookup [("full", Full), ("fast", Fast), ("kids", Kids)]- minorVariation s = fromMaybe (OtherMinorVariation s) . ruleSetLookup [("edgeless", Edgeless), ("superprong", Superprong)] $ s- minorVariations = Set.fromList . map minorVariation . splitWhen (== ',')+ruleSetLookup rs = flip lookup rs . map toLower +ruleSetGo =+ ruleSetLookup+ [ ("aga", AGA)+ , ("goe", GOE)+ , ("chinese", Chinese)+ , ("japanese", Japanese)+ , ("nz", NewZealand)+ ]++ruleSetBackgammon =+ ruleSetLookup+ [ ("crawford", Crawford)+ , ("crawford:crawfordgame", CrawfordGame)+ , ("jacoby", Jacoby)+ ]++ruleSetOcti s =+ case break (== ':') s of+ (major, ':':minors) ->+ liftM+ (flip OctiRuleSet (minorVariations minors))+ (majorVariation major)+ (majorOrMinors, "") ->+ liftM (flip OctiRuleSet (Set.empty)) (majorVariation majorOrMinors) `mplus`+ return (OctiRuleSet Full (minorVariations majorOrMinors))+ where+ majorVariation =+ ruleSetLookup [("full", Full), ("fast", Fast), ("kids", Kids)]+ minorVariation s =+ fromMaybe (OtherMinorVariation s) .+ ruleSetLookup [("edgeless", Edgeless), ("superprong", Superprong)] $+ s+ minorVariations = Set.fromList . map minorVariation . splitWhen (== ',')+ ruleSet read maybeDefault header = do maybeRulesetString <- transMap (simple header) "RU"- return $ case (maybeRulesetString, maybeRulesetString >>= read) of- (Nothing, _ ) -> fmap Known maybeDefault- (Just s , Nothing) -> Just (OtherRuleSet s)- (_ , Just rs) -> Just (Known rs)+ return $+ case (maybeRulesetString, maybeRulesetString >>= read) of+ (Nothing, _) -> fmap Known maybeDefault+ (Just s, Nothing) -> Just (OtherRuleSet s)+ (_, Just rs) -> Just (Known rs) ruleSetDefault = ruleSet (const Nothing) Nothing -- | -- Just the properties associated with specific games. extraProperties :: GameType -> PropertyType -> [String]-extraProperties Go GameInfo = ["HA", "KM"]-extraProperties Go None = ["TB", "TW"]-extraProperties Backgammon Setup = ["CO", "CV", "DI"]-extraProperties Backgammon GameInfo = ["MI", "RE", "RU"]+extraProperties Go GameInfo = ["HA", "KM"]+extraProperties Go None = ["TB", "TW"]+extraProperties Backgammon Setup = ["CO", "CV", "DI"]+extraProperties Backgammon GameInfo = ["MI", "RE", "RU"] extraProperties LinesOfAction GameInfo = ["IP", "IY", "SU"]-extraProperties LinesOfAction None = ["AS", "SE"]-extraProperties Hex Root = ["IS"]-extraProperties Hex GameInfo = ["IP"]-extraProperties Amazons Setup = ["AA"]-extraProperties Octi Setup = ["RP"]-extraProperties Octi GameInfo = ["BO", "WO", "NP", "NR", "NS"]-extraProperties Octi None = ["AS", "CS", "MS", "SS", "TS"]-extraProperties _ _ = []+extraProperties LinesOfAction None = ["AS", "SE"]+extraProperties Hex Root = ["IS"]+extraProperties Hex GameInfo = ["IP"]+extraProperties Amazons Setup = ["AA"]+extraProperties Octi Setup = ["RP"]+extraProperties Octi GameInfo = ["BO", "WO", "NP", "NR", "NS"]+extraProperties Octi None = ["AS", "CS", "MS", "SS", "TS"]+extraProperties _ _ = [] gameInfoGo = liftM2 GameInfoGo (transMap number "HA") (transMap real "KM") -pointGo (Property { values = [[x, y]] }) | valid x && valid y = return (translate x, translate y)- where- valid x = (enum 'a' <= x && x <= enum 'z') || (enum 'A' <= x && x <= enum 'Z')- translate x = enum x - enum (if x < enum 'a' then 'A' else 'a')+pointGo (Property {values = [[x, y]]})+ | valid x && valid y = return (translate x, translate y)+ where+ valid x =+ (enum 'a' <= x && x <= enum 'z') || (enum 'A' <= x && x <= enum 'Z')+ translate x =+ enum x -+ enum+ (if x < enum 'a'+ then 'A'+ else 'a') pointGo p = dieWith BadlyFormattedValue p -moveGo _ (Property { values = [[]] }) = return Pass-moveGo (Just (w, h)) p = pointGo p >>= \v@(x, y) -> return $ if x >= w || y >= h then Pass else Play v-moveGo _ p = fmap Play (pointGo p)+moveGo _ (Property {values = [[]]}) = return Pass+moveGo (Just (w, h)) p =+ pointGo p >>= \v@(x, y) ->+ return $+ if x >= w || y >= h+ then Pass+ else Play v+moveGo _ p = fmap Play (pointGo p) annotationGo = do territories <- mapM (transMap (elistOfPoint pointGo)) ["TB", "TW"]- return . Map.fromList $ [(c, Set.fromList t) | (c, Just t) <- zip [Black, White] territories]+ return . Map.fromList $+ [(c, Set.fromList t) | (c, Just t) <- zip [Black, White] territories] gameHex header seenGameInfo = fmap (TreeHex []) (nodeHex header seenGameInfo) nodeGo header size seenGameInfo = do- [hasGameInfo, hasRoot, hasSetup, hasMove] <- mapM (hasAny . properties Go) [GameInfo, Root, Setup, Move]- let setGameInfo = hasGameInfo && not seenGameInfo+ [hasGameInfo, hasRoot, hasSetup, hasMove] <-+ mapM (hasAny . properties Go) [GameInfo, Root, Setup, Move]+ let setGameInfo = hasGameInfo && not seenGameInfo duplicateGameInfo = hasGameInfo && seenGameInfo when (hasSetup && hasMove) dieSetupAndMove when duplicateGameInfo warnGameInfo- when hasRoot warnRoot-- mGameInfo <- liftM (\x -> guard setGameInfo >> Just x) (gameInfo header)- otherGameInfo <- gameInfoGo- ruleSet_ <- ruleSet ruleSetGo Nothing header- action_ <- if hasMove then liftM Right $ move (moveGo size) else liftM Left $ setupPoint pointGo- annotation_ <- annotation header+ when hasRoot warnRoot+ mGameInfo <- liftM (\x -> guard setGameInfo >> Just x) (gameInfo header)+ otherGameInfo <- gameInfoGo+ ruleSet_ <- ruleSet ruleSetGo Nothing header+ action_ <-+ if hasMove+ then liftM Right $ move (moveGo size)+ else liftM Left $ setupPoint pointGo+ annotation_ <- annotation header otherAnnotation <- annotationGo- markup_ <- markup header pointGo- unknown_ <- unknownProperties- children <- gets subForest >>= mapM (\s -> put s >> nodeGo header size (seenGameInfo || hasGameInfo))+ markup_ <- markup header pointGo+ unknown_ <- unknownProperties+ children <-+ gets subForest >>=+ mapM (\s -> put s >> nodeGo header size (seenGameInfo || hasGameInfo))+ return+ (Node+ (GameNode+ (fmap+ (\gi ->+ gi+ { T.ruleSet = ruleSet_+ , T.otherGameInfo = otherGameInfo+ })+ mGameInfo)+ action_+ annotation_ {T.otherAnnotation = otherAnnotation}+ markup_+ unknown_)+ children)+ where+ dieSetupAndMove =+ dieEarliest ConcurrentMoveAndSetup (properties Go =<< [Setup, Move])+ warnGameInfo = warnAll ExtraGameInfoOmitted (properties Go GameInfo)+ warnRoot = warnAll NestedRootPropertyOmitted (properties Go Root) - return (Node (GameNode (fmap (\gi -> gi { T.ruleSet = ruleSet_, T.otherGameInfo = otherGameInfo }) mGameInfo) action_ annotation_ { T.otherAnnotation = otherAnnotation } markup_ unknown_) children)- where- dieSetupAndMove = dieEarliest ConcurrentMoveAndSetup (properties Go =<< [Setup, Move])- warnGameInfo = warnAll ExtraGameInfoOmitted (properties Go GameInfo)- warnRoot = warnAll NestedRootPropertyOmitted (properties Go Root)+nodeBackgammon = nodeOther -- TODO -nodeBackgammon = nodeOther -- TODO nodeLinesOfAction = nodeOther -- TODO-nodeHex = nodeOther -- TODO-nodeOcti = nodeOther -- TODO++nodeHex = nodeOther -- TODO++nodeOcti = nodeOther -- TODO+ nodeOther header seenGameInfo = return (Node emptyGameNode []) -- TODO -- }}}
Data/SGF/Parse/Encodings.hs view
@@ -1,36 +1,47 @@-{-# LANGUAGE FlexibleInstances, FlexibleContexts, GeneralizedNewtypeDeriving #-}-module Data.SGF.Parse.Encodings (guessEncoding, decodeWordStringExplicit) where+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE InstanceSigs #-} +module Data.SGF.Parse.Encodings+ ( guessEncoding+ , decodeWordStringExplicit+ ) where++import Control.Applicative (Applicative(..)) import Control.Exception.Extensible+import Control.Monad (ap, liftM) import Control.Monad.State-import Control.Applicative (Applicative(..))-import Control.Monad (liftM,ap) import Control.Throws import Data.Encoding import Data.Word type MyIHateGHC = MyEither DecodingException (String, [Word8])-newtype MyEither a b = MyEither (Either a b) deriving (Throws a) +newtype MyEither a b =+ MyEither (Either a b)+ deriving (Throws a)+ instance Functor (MyEither a) where fmap = liftM instance Applicative (MyEither a) where- pure = return + pure :: a2 -> MyEither a1 a2+ pure x = return x -- note that an eta reduced version of this trips the type checker for non-canonical "pure = return"+ (<*>) :: MyEither a1 (a2 -> b) -> MyEither a1 a2 -> MyEither a1 b (<*>) = ap instance Monad (MyEither a) where- return = MyEither . Right (MyEither (Right x)) >>= f = f x- (MyEither (Left x)) >>= f = MyEither (Left x)+ (MyEither (Left x)) >>= f = MyEither (Left x) instance ByteSource (StateT [Word8] (MyEither DecodingException)) where sourceEmpty = gets null- fetchWord8 = do+ fetchWord8 = do s <- get case s of- [] -> throwException UnexpectedEnd- c:cs -> put cs >> return c+ [] -> throwException UnexpectedEnd+ c:cs -> put cs >> return c fetchAhead m = do s <- get v <- m@@ -39,10 +50,13 @@ -- some ones that we know satisfy our invariant (see SGF.Parse.Raw) encodings = map encodingFromString ["latin1", "utf-8", "ascii"]-guess ws encoding = case runStateT (decode encoding) ws :: MyIHateGHC of- (MyEither (Right (s, []))) -> encodingFromStringExplicit s == Just encoding- _ -> False +guess ws encoding =+ case runStateT (decode encoding) ws :: MyIHateGHC of+ (MyEither (Right (s, []))) ->+ encodingFromStringExplicit s == Just encoding+ _ -> False+ -- | -- Try decoding the given word string with each of the known-good encodings to -- see if the decoded name names the encoding used to decode. It should be@@ -52,7 +66,9 @@ -- | -- A simple wrapper around the encoding package's 'decode' function.-decodeWordStringExplicit :: Encoding e => e -> [Word8] -> Either DecodingException String-decodeWordStringExplicit e ws = case runStateT (decode e) ws :: MyIHateGHC of- (MyEither (Right (s,_))) -> Right s- (MyEither (Left ex )) -> Left ex+decodeWordStringExplicit ::+ Encoding e => e -> [Word8] -> Either DecodingException String+decodeWordStringExplicit e ws =+ case runStateT (decode e) ws :: MyIHateGHC of+ (MyEither (Right (s, _))) -> Right s+ (MyEither (Left ex)) -> Left ex
sgf.cabal view
@@ -1,5 +1,5 @@ name: sgf-version: 0.1.3.1+version: 0.1.3.2 author: Daniel Wagner daniel@wagner-home.com maintainer: Toni Cebrián ancechu@gmail.com homepage: https://github.com/tonicebrian/sgf@@ -14,20 +14,17 @@ category: Data license: BSD3 license-file: LICENSE-cabal-version: >= 1.6+cabal-version: >= 1.10 build-type: Simple library- ghc-options: -Werror-+ default-language: Haskell2010 exposed-modules: Data.SGF Data.SGF.Parse Data.SGF.Types- other-modules: Data.SGF.Parse.Encodings Data.SGF.Parse.Raw Data.SGF.Parse.Util- build-depends: base >=3 && < 5, containers, extensible-exceptions,@@ -35,7 +32,7 @@ time>=1, parsec>=3, split,- encoding>=0.6,+ encoding>=0.8, transformers>=0.4 source-repository head