packages feed

kicad-data 0.4.0 → 0.5.0

raw patch · 14 files changed

+708/−370 lines, 14 filesdep +HUnitdep +charsetdetectdep +encodingdep −parsec-numbersdep ~basedep ~ieee754dep ~lens-familyPVP ok

version bump matches the API change (PVP)

Dependencies added: HUnit, charsetdetect, encoding, test-framework-hunit

Dependencies removed: parsec-numbers

Dependency ranges changed: base, ieee754, lens-family, parsec, test-framework-quickcheck2

API changes (from Hackage documentation)

- Data.Kicad.PcbnewExpr.PcbnewExpr: fpArcAngle :: PcbnewItem -> Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: fpPolyPts :: PcbnewItem -> [V2Double]
- Data.Kicad.PcbnewExpr.PcbnewExpr: fpTextHide :: PcbnewItem -> Bool
- Data.Kicad.PcbnewExpr.PcbnewExpr: fpTextItalic :: PcbnewItem -> Bool
- Data.Kicad.PcbnewExpr.PcbnewExpr: fpTextJustify_ :: PcbnewItem -> [PcbnewJustifyT]
- Data.Kicad.PcbnewExpr.PcbnewExpr: fpTextStr :: PcbnewItem -> String
- Data.Kicad.PcbnewExpr.PcbnewExpr: fpTextThickness :: PcbnewItem -> Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: fpTextType :: PcbnewItem -> PcbnewFpTextTypeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance AEq PcbnewAtT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance AEq PcbnewAttribute
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance AEq PcbnewDrillT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance AEq PcbnewExpr
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance AEq PcbnewItem
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance AEq PcbnewModule
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Bounded PcbnewFpTextTypeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Bounded PcbnewJustifyT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Bounded PcbnewLayerT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Bounded PcbnewPadShapeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Bounded PcbnewPadTypeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Enum PcbnewFpTextTypeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Enum PcbnewJustifyT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Enum PcbnewLayerT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Enum PcbnewPadShapeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Enum PcbnewPadTypeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewAtT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewAttribute
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewDrillT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewExpr
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewFpTextTypeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewItem
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewJustifyT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewLayerT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewModule
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewPadShapeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Eq PcbnewPadTypeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Num V2Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance SExpressable PcbnewAttribute
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance SExpressable PcbnewExpr
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance SExpressable PcbnewItem
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance SExpressable PcbnewModule
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewAtT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewAttribute
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewDrillT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewExpr
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewFpTextTypeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewItem
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewJustifyT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewLayerT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewModule
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewPadShapeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: instance Show PcbnewPadTypeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: itemAt :: PcbnewItem -> PcbnewAtT
- Data.Kicad.PcbnewExpr.PcbnewExpr: itemEnd :: PcbnewItem -> V2Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: itemLayer :: PcbnewItem -> PcbnewLayerT
- Data.Kicad.PcbnewExpr.PcbnewExpr: itemSize :: PcbnewItem -> V2Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: itemStart :: PcbnewItem -> V2Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: itemWidth :: PcbnewItem -> Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: padAttributes_ :: PcbnewItem -> [PcbnewAttribute]
- Data.Kicad.PcbnewExpr.PcbnewExpr: padLayers :: PcbnewItem -> [PcbnewLayerT]
- Data.Kicad.PcbnewExpr.PcbnewExpr: padNumber :: PcbnewItem -> String
- Data.Kicad.PcbnewExpr.PcbnewExpr: padShape :: PcbnewItem -> PcbnewPadShapeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: padType :: PcbnewItem -> PcbnewPadTypeT
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewAtOrientation :: PcbnewAtT -> Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewAtPoint :: PcbnewAtT -> V2Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewDrillOffset :: PcbnewDrillT -> Maybe V2Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewDrillOval :: PcbnewDrillT -> Bool
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewDrillSize :: PcbnewDrillT -> Maybe V2Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewFontItalic :: PcbnewAttribute -> Bool
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewFontSize :: PcbnewAttribute -> V2Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewFontThickness :: PcbnewAttribute -> Double
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewModelAt :: PcbnewAttribute -> PcbnewXyzT
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewModelPath :: PcbnewAttribute -> String
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewModelRotate :: PcbnewAttribute -> PcbnewXyzT
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewModelScale :: PcbnewAttribute -> PcbnewXyzT
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewModuleAttrs :: PcbnewModule -> [PcbnewAttribute]
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewModuleItems :: PcbnewModule -> [PcbnewItem]
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewModuleLayer :: PcbnewModule -> PcbnewLayerT
- Data.Kicad.PcbnewExpr.PcbnewExpr: pcbnewModuleName :: PcbnewModule -> String
- Data.Kicad.SExpr: AtomDbl :: Double -> SExpr
- Data.Kicad.SExpr: AtomKey :: Keyword -> SExpr
- Data.Kicad.SExpr: AtomStr :: String -> SExpr
- Data.Kicad.SExpr: KeyAngle :: Keyword
- Data.Kicad.SExpr: KeyAt :: Keyword
- Data.Kicad.SExpr: KeyAttr :: Keyword
- Data.Kicad.SExpr: KeyAutoplaceCost180 :: Keyword
- Data.Kicad.SExpr: KeyAutoplaceCost90 :: Keyword
- Data.Kicad.SExpr: KeyCenter :: Keyword
- Data.Kicad.SExpr: KeyClearance :: Keyword
- Data.Kicad.SExpr: KeyDescr :: Keyword
- Data.Kicad.SExpr: KeyDrill :: Keyword
- Data.Kicad.SExpr: KeyEffects :: Keyword
- Data.Kicad.SExpr: KeyEnd :: Keyword
- Data.Kicad.SExpr: KeyFont :: Keyword
- Data.Kicad.SExpr: KeyFpArc :: Keyword
- Data.Kicad.SExpr: KeyFpCircle :: Keyword
- Data.Kicad.SExpr: KeyFpLine :: Keyword
- Data.Kicad.SExpr: KeyFpPoly :: Keyword
- Data.Kicad.SExpr: KeyFpText :: Keyword
- Data.Kicad.SExpr: KeyJustify :: Keyword
- Data.Kicad.SExpr: KeyLayer :: Keyword
- Data.Kicad.SExpr: KeyLayers :: Keyword
- Data.Kicad.SExpr: KeyModel :: Keyword
- Data.Kicad.SExpr: KeyModule :: Keyword
- Data.Kicad.SExpr: KeyOffset :: Keyword
- Data.Kicad.SExpr: KeyPad :: Keyword
- Data.Kicad.SExpr: KeyPath :: Keyword
- Data.Kicad.SExpr: KeyPts :: Keyword
- Data.Kicad.SExpr: KeyRectDelta :: Keyword
- Data.Kicad.SExpr: KeyRotate :: Keyword
- Data.Kicad.SExpr: KeyRoundrectRratio :: Keyword
- Data.Kicad.SExpr: KeyScale :: Keyword
- Data.Kicad.SExpr: KeySize :: Keyword
- Data.Kicad.SExpr: KeySolderMaskMargin :: Keyword
- Data.Kicad.SExpr: KeySolderPasteMargin :: Keyword
- Data.Kicad.SExpr: KeySolderPasteMarginRatio :: Keyword
- Data.Kicad.SExpr: KeySolderPasteRatio :: Keyword
- Data.Kicad.SExpr: KeyStart :: Keyword
- Data.Kicad.SExpr: KeyTags :: Keyword
- Data.Kicad.SExpr: KeyTedit :: Keyword
- Data.Kicad.SExpr: KeyThermalGap :: Keyword
- Data.Kicad.SExpr: KeyThermalWidth :: Keyword
- Data.Kicad.SExpr: KeyThickness :: Keyword
- Data.Kicad.SExpr: KeyWidth :: Keyword
- Data.Kicad.SExpr: KeyXy :: Keyword
- Data.Kicad.SExpr: KeyXyz :: Keyword
- Data.Kicad.SExpr: KeyZoneConnect :: Keyword
- Data.Kicad.SExpr: data Keyword
- Data.Kicad.SExpr: writeKeyword :: Keyword -> String
- Data.Kicad.SExpr.SExpr: AtomDbl :: Double -> SExpr
- Data.Kicad.SExpr.SExpr: AtomKey :: Keyword -> SExpr
- Data.Kicad.SExpr.SExpr: AtomStr :: String -> SExpr
- Data.Kicad.SExpr.SExpr: KeyAngle :: Keyword
- Data.Kicad.SExpr.SExpr: KeyAt :: Keyword
- Data.Kicad.SExpr.SExpr: KeyAttr :: Keyword
- Data.Kicad.SExpr.SExpr: KeyAutoplaceCost180 :: Keyword
- Data.Kicad.SExpr.SExpr: KeyAutoplaceCost90 :: Keyword
- Data.Kicad.SExpr.SExpr: KeyCenter :: Keyword
- Data.Kicad.SExpr.SExpr: KeyClearance :: Keyword
- Data.Kicad.SExpr.SExpr: KeyDescr :: Keyword
- Data.Kicad.SExpr.SExpr: KeyDrill :: Keyword
- Data.Kicad.SExpr.SExpr: KeyEffects :: Keyword
- Data.Kicad.SExpr.SExpr: KeyEnd :: Keyword
- Data.Kicad.SExpr.SExpr: KeyFont :: Keyword
- Data.Kicad.SExpr.SExpr: KeyFpArc :: Keyword
- Data.Kicad.SExpr.SExpr: KeyFpCircle :: Keyword
- Data.Kicad.SExpr.SExpr: KeyFpLine :: Keyword
- Data.Kicad.SExpr.SExpr: KeyFpPoly :: Keyword
- Data.Kicad.SExpr.SExpr: KeyFpText :: Keyword
- Data.Kicad.SExpr.SExpr: KeyJustify :: Keyword
- Data.Kicad.SExpr.SExpr: KeyLayer :: Keyword
- Data.Kicad.SExpr.SExpr: KeyLayers :: Keyword
- Data.Kicad.SExpr.SExpr: KeyModel :: Keyword
- Data.Kicad.SExpr.SExpr: KeyModule :: Keyword
- Data.Kicad.SExpr.SExpr: KeyOffset :: Keyword
- Data.Kicad.SExpr.SExpr: KeyPad :: Keyword
- Data.Kicad.SExpr.SExpr: KeyPath :: Keyword
- Data.Kicad.SExpr.SExpr: KeyPts :: Keyword
- Data.Kicad.SExpr.SExpr: KeyRectDelta :: Keyword
- Data.Kicad.SExpr.SExpr: KeyRotate :: Keyword
- Data.Kicad.SExpr.SExpr: KeyRoundrectRratio :: Keyword
- Data.Kicad.SExpr.SExpr: KeyScale :: Keyword
- Data.Kicad.SExpr.SExpr: KeySize :: Keyword
- Data.Kicad.SExpr.SExpr: KeySolderMaskMargin :: Keyword
- Data.Kicad.SExpr.SExpr: KeySolderPasteMargin :: Keyword
- Data.Kicad.SExpr.SExpr: KeySolderPasteMarginRatio :: Keyword
- Data.Kicad.SExpr.SExpr: KeySolderPasteRatio :: Keyword
- Data.Kicad.SExpr.SExpr: KeyStart :: Keyword
- Data.Kicad.SExpr.SExpr: KeyTags :: Keyword
- Data.Kicad.SExpr.SExpr: KeyTedit :: Keyword
- Data.Kicad.SExpr.SExpr: KeyThermalGap :: Keyword
- Data.Kicad.SExpr.SExpr: KeyThermalWidth :: Keyword
- Data.Kicad.SExpr.SExpr: KeyThickness :: Keyword
- Data.Kicad.SExpr.SExpr: KeyWidth :: Keyword
- Data.Kicad.SExpr.SExpr: KeyXy :: Keyword
- Data.Kicad.SExpr.SExpr: KeyXyz :: Keyword
- Data.Kicad.SExpr.SExpr: KeyZoneConnect :: Keyword
- Data.Kicad.SExpr.SExpr: data Keyword
- Data.Kicad.SExpr.SExpr: instance Bounded Keyword
- Data.Kicad.SExpr.SExpr: instance Enum Keyword
- Data.Kicad.SExpr.SExpr: instance Eq Keyword
- Data.Kicad.SExpr.SExpr: instance Eq SExpr
- Data.Kicad.SExpr.SExpr: instance Show Keyword
- Data.Kicad.SExpr.SExpr: instance Show SExpr
- Data.Kicad.SExpr.Write: writeKeyword :: Keyword -> String
- Data.Kicad.Util: headOr :: a -> [a] -> a
- Data.Kicad.Util: maybeHead :: [a] -> Maybe a
- Data.Kicad.Util: maybeLast :: [a] -> Maybe a
+ Data.Kicad.PcbnewExpr: parseWithFilename :: String -> String -> Either String PcbnewExpr
+ Data.Kicad.PcbnewExpr.Parse: parseWithFilename :: String -> String -> Either String PcbnewExpr
+ Data.Kicad.PcbnewExpr.PcbnewExpr: AllFab :: PcbnewLayerT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: PcbnewDieLength :: Double -> PcbnewAttribute
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [fpArcAngle] :: PcbnewItem -> Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [fpPolyPts] :: PcbnewItem -> [V2Double]
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [fpTextHide] :: PcbnewItem -> Bool
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [fpTextItalic] :: PcbnewItem -> Bool
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [fpTextJustify_] :: PcbnewItem -> [PcbnewJustifyT]
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [fpTextStr] :: PcbnewItem -> String
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [fpTextThickness] :: PcbnewItem -> Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [fpTextType] :: PcbnewItem -> PcbnewFpTextTypeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [itemAt] :: PcbnewItem -> PcbnewAtT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [itemEnd] :: PcbnewItem -> V2Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [itemLayer] :: PcbnewItem -> PcbnewLayerT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [itemSize] :: PcbnewItem -> V2Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [itemStart] :: PcbnewItem -> V2Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [itemWidth] :: PcbnewItem -> Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [padAttributes_] :: PcbnewItem -> [PcbnewAttribute]
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [padLayers] :: PcbnewItem -> [PcbnewLayerT]
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [padNumber] :: PcbnewItem -> String
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [padShape] :: PcbnewItem -> PcbnewPadShapeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [padType] :: PcbnewItem -> PcbnewPadTypeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewAtOrientation] :: PcbnewAtT -> Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewAtPoint] :: PcbnewAtT -> V2Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewDrillOffset] :: PcbnewDrillT -> Maybe V2Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewDrillOval] :: PcbnewDrillT -> Bool
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewDrillSize] :: PcbnewDrillT -> Maybe V2Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewFontItalic] :: PcbnewAttribute -> Bool
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewFontSize] :: PcbnewAttribute -> V2Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewFontThickness] :: PcbnewAttribute -> Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewModelAt] :: PcbnewAttribute -> PcbnewXyzT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewModelPath] :: PcbnewAttribute -> String
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewModelRotate] :: PcbnewAttribute -> PcbnewXyzT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewModelScale] :: PcbnewAttribute -> PcbnewXyzT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewModuleAttrs] :: PcbnewModule -> [PcbnewAttribute]
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewModuleItems] :: PcbnewModule -> [PcbnewItem]
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewModuleLayer] :: PcbnewModule -> PcbnewLayerT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: [pcbnewModuleName] :: PcbnewModule -> String
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance Data.AEq.AEq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewAtT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance Data.AEq.AEq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewAttribute
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance Data.AEq.AEq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewDrillT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance Data.AEq.AEq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewExpr
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance Data.AEq.AEq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewItem
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance Data.AEq.AEq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewModule
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance Data.Kicad.SExpr.SExpr.SExpressable Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewAttribute
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance Data.Kicad.SExpr.SExpr.SExpressable Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewExpr
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance Data.Kicad.SExpr.SExpr.SExpressable Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewItem
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance Data.Kicad.SExpr.SExpr.SExpressable Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewModule
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewAtT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewAttribute
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewDrillT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewExpr
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewFpTextTypeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewItem
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewJustifyT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewLayerT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewModule
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewPadShapeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Classes.Eq Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewPadTypeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Enum.Bounded Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewFpTextTypeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Enum.Bounded Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewJustifyT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Enum.Bounded Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewLayerT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Enum.Bounded Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewPadShapeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Enum.Bounded Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewPadTypeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Enum.Enum Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewFpTextTypeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Enum.Enum Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewJustifyT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Enum.Enum Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewLayerT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Enum.Enum Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewPadShapeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Enum.Enum Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewPadTypeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Num.Num Data.Kicad.PcbnewExpr.PcbnewExpr.V2Double
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewAtT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewAttribute
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewDrillT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewExpr
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewFpTextTypeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewItem
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewJustifyT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewLayerT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewModule
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewPadShapeT
+ Data.Kicad.PcbnewExpr.PcbnewExpr: instance GHC.Show.Show Data.Kicad.PcbnewExpr.PcbnewExpr.PcbnewPadTypeT
+ Data.Kicad.SExpr: Atom :: SourcePos -> String -> SExpr
+ Data.Kicad.SExpr: getPos :: SExpr -> SourcePos
+ Data.Kicad.SExpr: parseWithFilename :: String -> String -> Either String SExpr
+ Data.Kicad.SExpr.Parse: parseWithFilename :: String -> String -> Either String SExpr
+ Data.Kicad.SExpr.SExpr: Atom :: SourcePos -> String -> SExpr
+ Data.Kicad.SExpr.SExpr: getPos :: SExpr -> SourcePos
+ Data.Kicad.SExpr.SExpr: instance GHC.Classes.Eq Data.Kicad.SExpr.SExpr.SExpr
+ Data.Kicad.SExpr.SExpr: instance GHC.Show.Show Data.Kicad.SExpr.SExpr.SExpr
- Data.Kicad.SExpr: List :: [SExpr] -> SExpr
+ Data.Kicad.SExpr: List :: SourcePos -> [SExpr] -> SExpr
- Data.Kicad.SExpr.SExpr: List :: [SExpr] -> SExpr
+ Data.Kicad.SExpr.SExpr: List :: SourcePos -> [SExpr] -> SExpr

Files

Data/Kicad/PcbnewExpr.hs view
@@ -4,6 +4,7 @@   PcbnewExpr(..) -- * Parse , parse+, parseWithFilename , fromSExpr -- * Write , pretty
Data/Kicad/PcbnewExpr/Parse.hs view
@@ -1,105 +1,111 @@ module Data.Kicad.PcbnewExpr.Parse ( parse+, parseWithFilename , fromSExpr ) where import Data.Either import Data.Maybe-import Control.Applicative import Lens.Family2 (over) import Data.List (intersperse)+import Text.Read (readMaybe)+import Text.Parsec.Pos (newPos)+import Control.Applicative ((<$>), (<*>)) -import Data.Kicad.SExpr hiding (parse)-import qualified Data.Kicad.SExpr as SExpr (parse)+import Data.Kicad.SExpr hiding (parse, parseWithFilename)+import qualified Data.Kicad.SExpr as SExpr (parseWithFilename) import Data.Kicad.PcbnewExpr.PcbnewExpr import Data.Kicad.Util (headOr) -{-| Parse a 'PcbnewExpr' from a 'String'. Returns an 'String' with an error or-   a 'PcbnewExpr'. -}+{-| Parse a Pcbnew expression from a string. Returns an 'String' with an error+ - or a 'PcbnewExpr'. -} parse :: String -> Either String PcbnewExpr-parse = either Left fromSExpr . SExpr.parse+parse = parseWithFilename "" +{-| Parse a Pcbnew expression from a string giving a filename argument to be used in error strings. -}+parseWithFilename :: String -> String -> Either String PcbnewExpr+parseWithFilename filename =+    either Left fromSExpr . SExpr.parseWithFilename filename+ {-| Interpret a 'SExpr' as a 'PcbnewExpr'. -} fromSExpr :: SExpr -> Either String PcbnewExpr-fromSExpr (List (AtomKey kw:sxs)) =-    case go of-        Left err   -> Left $ "Could not interpret '" ++ writeKeyword kw ++-                        "' because:\n\t" ++ err-        Right expr -> Right expr-    where go = case kw of-            KeyModule    -> PcbnewExprModule    <$> asPcbnewModule           sxs-            KeyPad       -> PcbnewExprItem      <$> asPcbnewPad              sxs-            KeyFpText    -> PcbnewExprItem      <$> asPcbnewFpText           sxs-            KeyFpArc     -> PcbnewExprItem      <$> asPcbnewFpArc            sxs-            KeyFpPoly    -> PcbnewExprItem      <$> asPcbnewFpPoly           sxs-            KeyLayer     -> PcbnewExprAttribute <$> asPcbnewLayer            sxs-            KeyAt        -> PcbnewExprAttribute <$> asPcbnewAt               sxs-            KeyEffects   -> PcbnewExprAttribute <$> asPcbnewEffects          sxs-            KeyFont      -> PcbnewExprAttribute <$> asPcbnewFont             sxs-            KeyLayers    -> PcbnewExprAttribute <$> asPcbnewLayers           sxs-            KeyPts       -> PcbnewExprAttribute <$> asPcbnewPts              sxs-            KeyXyz       -> PcbnewExprAttribute <$> asPcbnewXyz              sxs-            KeyModel     -> PcbnewExprAttribute <$> asPcbnewModel            sxs-            KeyDrill     -> PcbnewExprAttribute <$> asPcbnewDrill            sxs-            KeySize      -> PcbnewExprAttribute <$> asXy PcbnewSize          sxs-            KeyStart     -> PcbnewExprAttribute <$> asXy PcbnewStart         sxs-            KeyEnd       -> PcbnewExprAttribute <$> asXy PcbnewEnd           sxs-            KeyCenter    -> PcbnewExprAttribute <$> asXy PcbnewCenter        sxs-            KeyRectDelta -> PcbnewExprAttribute <$> asXy PcbnewRectDelta     sxs-            KeyXy        -> PcbnewExprAttribute <$> asXy PcbnewXy            sxs-            KeyOffset    -> PcbnewExprAttribute <$> asXy PcbnewOffset        sxs-            KeyScale     -> PcbnewExprAttribute <$> asXyz PcbnewModelScale   sxs-            KeyRotate    -> PcbnewExprAttribute <$> asXyz PcbnewModelRotate  sxs-            KeyDescr     -> PcbnewExprAttribute <$> asString PcbnewDescr     sxs-            KeyTags      -> PcbnewExprAttribute <$> asString PcbnewTags      sxs-            KeyPath      -> PcbnewExprAttribute <$> asString PcbnewPath      sxs-            KeyAttr      -> PcbnewExprAttribute <$> asString PcbnewAttr      sxs-            KeyTedit     -> PcbnewExprAttribute <$> asString PcbnewTedit     sxs-            KeyAngle     -> PcbnewExprAttribute <$> asDouble PcbnewAngle     sxs-            KeyThickness -> PcbnewExprAttribute <$> asDouble PcbnewThickness sxs-            KeyWidth     -> PcbnewExprAttribute <$> asDouble PcbnewWidth     sxs-            KeyJustify   -> PcbnewExprAttribute <$> asPcbnewJustifyT         sxs-            KeyThermalGap-                -> PcbnewExprAttribute <$> asDouble PcbnewThermalGap sxs-            KeyThermalWidth-                -> PcbnewExprAttribute <$> asDouble PcbnewThermalWidth sxs-            KeySolderPasteMarginRatio-                -> PcbnewExprAttribute <$> asDouble PcbnewPasteMarginRatio  sxs-            KeySolderPasteMargin-                -> PcbnewExprAttribute <$> asDouble PcbnewPasteMargin sxs-            KeySolderMaskMargin-                -> PcbnewExprAttribute <$> asDouble PcbnewMaskMargin  sxs-            KeyClearance-                -> PcbnewExprAttribute <$> asDouble PcbnewClearance   sxs-            KeySolderPasteRatio-                -> PcbnewExprAttribute <$> asDouble PcbnewSolderPasteRatio sxs-            KeyFpLine-                -> PcbnewExprItem <$> asFp defaultPcbnewFpLine        sxs-            KeyFpCircle-                -> PcbnewExprItem <$> asFp defaultPcbnewFpCircle      sxs-            KeyAutoplaceCost180-                -> PcbnewExprAttribute <$> asInt PcbnewAutoplaceCost180 sxs-            KeyAutoplaceCost90-                -> PcbnewExprAttribute <$> asInt PcbnewAutoplaceCost90 sxs-            KeyZoneConnect-                -> PcbnewExprAttribute <$> asInt PcbnewZoneConnect sxs-            KeyRoundrectRratio-                -> PcbnewExprAttribute <$> asDouble PcbnewRoundrectRratio sxs-fromSExpr sx@(AtomStr s) = case s of+fromSExpr (List _ (Atom pos kw:sxs)) = case kw of+    "module"     -> PcbnewExprModule    <$> asPcbnewModule           sxs+    "pad"        -> PcbnewExprItem      <$> asPcbnewPad              sxs+    "fp_text"    -> PcbnewExprItem      <$> asPcbnewFpText           sxs+    "fp_arc"     -> PcbnewExprItem      <$> asPcbnewFpArc            sxs+    "fp_poly"    -> PcbnewExprItem      <$> asPcbnewFpPoly           sxs+    "layer"      -> PcbnewExprAttribute <$> asPcbnewLayer            sxs+    "at"         -> PcbnewExprAttribute <$> asPcbnewAt               sxs+    "effects"    -> PcbnewExprAttribute <$> asPcbnewEffects          sxs+    "font"       -> PcbnewExprAttribute <$> asPcbnewFont             sxs+    "layers"     -> PcbnewExprAttribute <$> asPcbnewLayers           sxs+    "pts"        -> PcbnewExprAttribute <$> asPcbnewPts              sxs+    "xyz"        -> PcbnewExprAttribute <$> asPcbnewXyz              sxs+    "model"      -> PcbnewExprAttribute <$> asPcbnewModel            sxs+    "drill"      -> PcbnewExprAttribute <$> asPcbnewDrill            sxs+    "size"       -> PcbnewExprAttribute <$> asXy PcbnewSize          sxs+    "start"      -> PcbnewExprAttribute <$> asXy PcbnewStart         sxs+    "end"        -> PcbnewExprAttribute <$> asXy PcbnewEnd           sxs+    "center"     -> PcbnewExprAttribute <$> asXy PcbnewCenter        sxs+    "rect_delta" -> PcbnewExprAttribute <$> asXy PcbnewRectDelta     sxs+    "xy"         -> PcbnewExprAttribute <$> asXy PcbnewXy            sxs+    "offset"     -> PcbnewExprAttribute <$> asXy PcbnewOffset        sxs+    "scale"      -> PcbnewExprAttribute <$> asXyz PcbnewModelScale   sxs+    "rotate"     -> PcbnewExprAttribute <$> asXyz PcbnewModelRotate  sxs+    "descr"      -> PcbnewExprAttribute <$> asString PcbnewDescr     sxs+    "tags"       -> PcbnewExprAttribute <$> asString PcbnewTags      sxs+    "path"       -> PcbnewExprAttribute <$> asString PcbnewPath      sxs+    "attr"       -> PcbnewExprAttribute <$> asString PcbnewAttr      sxs+    "tedit"      -> PcbnewExprAttribute <$> asString PcbnewTedit     sxs+    "angle"      -> PcbnewExprAttribute <$> asDouble PcbnewAngle     sxs+    "thickness"  -> PcbnewExprAttribute <$> asDouble PcbnewThickness sxs+    "width"      -> PcbnewExprAttribute <$> asDouble PcbnewWidth     sxs+    "justify"    -> PcbnewExprAttribute <$> asPcbnewJustifyT         sxs+    "thermal_gap"+        -> PcbnewExprAttribute <$> asDouble PcbnewThermalGap sxs+    "thermal_width"+        -> PcbnewExprAttribute <$> asDouble PcbnewThermalWidth sxs+    "solder_paste_margin_ratio"+        -> PcbnewExprAttribute <$> asDouble PcbnewPasteMarginRatio sxs+    "solder_paste_margin"+        -> PcbnewExprAttribute <$> asDouble PcbnewPasteMargin sxs+    "solder_mask_margin"+        -> PcbnewExprAttribute <$> asDouble PcbnewMaskMargin sxs+    "clearance"+        -> PcbnewExprAttribute <$> asDouble PcbnewClearance sxs+    "solder_paste_ratio"+        -> PcbnewExprAttribute <$> asDouble PcbnewSolderPasteRatio sxs+    "fp_line"+        -> PcbnewExprItem <$> asFp defaultPcbnewFpLine sxs+    "fp_circle"+        -> PcbnewExprItem <$> asFp defaultPcbnewFpCircle sxs+    "autoplace_cost180"+        -> PcbnewExprAttribute <$> asInt PcbnewAutoplaceCost180 sxs+    "autoplace_cost90"+        -> PcbnewExprAttribute <$> asInt PcbnewAutoplaceCost90 sxs+    "zone_connect"+        -> PcbnewExprAttribute <$> asInt PcbnewZoneConnect sxs+    "roundrect_rratio"+        -> PcbnewExprAttribute <$> asDouble PcbnewRoundrectRratio sxs+    "die_length"+        -> PcbnewExprAttribute <$> asDouble PcbnewDieLength sxs+    _   -> Left $ "Error in " ++ (show pos) ++ ": unknown expression type '" ++ kw ++ "'"+fromSExpr sx@(Atom _ s) = case s of     "italic" -> Right $ PcbnewExprAttribute PcbnewItalic     "hide"   -> Right $ PcbnewExprAttribute PcbnewHide     "locked" -> Right $ PcbnewExprAttribute PcbnewLocked     "placed" -> Right $ PcbnewExprAttribute PcbnewPlaced     _ -> expecting "'italic' or 'hide' or 'locked' " sx-fromSExpr x = expecting "List with a key or a string atom" x+fromSExpr x = expecting "List _ with a key or a string atom" x  asPcbnewModule :: [SExpr] -> Either String PcbnewModule-asPcbnewModule (AtomStr n:xs) =+asPcbnewModule (Atom _ n:xs) =     interpretRest xs defaultPcbnewModule { pcbnewModuleName = n }     where         interpretRest [] m = Right m         interpretRest (sx:sxs) m = case fromSExpr sx of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewLayer layer)) ->                 interpretRest sxs m {pcbnewModuleLayer = layer}             Right (PcbnewExprItem item) ->@@ -114,18 +120,18 @@ asPcbnewFpText (t:s:a:xs) = interpretType     where         interpretType = case t of-            (AtomStr "reference") ->+            (Atom _ "reference") ->                 interpretString (defaultPcbnewFpText {fpTextType = FpTextReference})-            (AtomStr "value")     ->+            (Atom _ "value")     ->                 interpretString (defaultPcbnewFpText {fpTextType = FpTextValue})-            (AtomStr "user")     ->+            (Atom _ "user")     ->                 interpretString (defaultPcbnewFpText {fpTextType = FpTextUser})             _           -> expecting "'reference', 'value' or 'user'" t         interpretString fp_text = case s of-            (AtomStr string) -> interpretAt fp_text {fpTextStr = string}+            (Atom _ string) -> interpretAt fp_text {fpTextStr = string}             _           -> expecting "string" s         interpretAt fp_text = case fromSExpr a of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewAt at)) ->                 interpretRest xs fp_text {itemAt = at}             _ -> expecting "'at' expression (e.g. '(at 1.0 1.0)')" a@@ -144,7 +150,7 @@             _ -> fp_text         interpretRest [] fp_text = Right fp_text         interpretRest (sx:sxs) fp_text = case fromSExpr sx of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewLayer layer)) ->                 interpretRest sxs (fp_text {itemLayer = layer})             Right (PcbnewExprAttribute (PcbnewFpTextEffects effects)) ->@@ -158,20 +164,20 @@ asFp defaultFp (s:e:xs) = interpretStart defaultFp     where         interpretStart fp_shape = case fromSExpr s of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewStart start)) ->                 interpretEnd fp_shape {itemStart = start}             Right (PcbnewExprAttribute (PcbnewCenter center)) ->                 interpretEnd fp_shape {itemStart = center}             Right _ -> expecting "start (e.g. '(start 1.0 1.0)')" s         interpretEnd fp_shape = case fromSExpr e of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewEnd end)) ->                 interpretRest xs fp_shape {itemEnd = end}             Right _ -> expecting "end (e.g. '(end 1.0 1.0)')" e         interpretRest [] fp_shape = Right fp_shape         interpretRest (sx:sxs) fp_shape = case fromSExpr sx of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewWidth d))                 -> interpretRest sxs fp_shape {itemWidth = d}             Right (PcbnewExprAttribute (PcbnewLayer d))@@ -183,18 +189,18 @@ asPcbnewFpArc (s:e:xs) = interpretStart defaultPcbnewFpArc     where         interpretStart fp_arc = case fromSExpr s of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewStart start)) ->                 interpretEnd fp_arc {itemStart = start}             Right _ -> expecting "start (e.g. '(start 1.0 1.0)')" s         interpretEnd fp_arc = case fromSExpr e of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewEnd end)) ->                 interpretRest xs fp_arc {itemEnd = end}             Right _ -> expecting "end (e.g. '(end 1.0 1.0)')" e         interpretRest [] fp_arc = Right fp_arc         interpretRest (sx:sxs) fp_arc = case fromSExpr sx of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewWidth d))                 -> interpretRest sxs fp_arc {itemWidth = d}             Right (PcbnewExprAttribute (PcbnewLayer d))@@ -209,7 +215,7 @@     where         interpretRest [] fp_poly = Right fp_poly         interpretRest (sx:sxs) fp_poly = case fromSExpr sx of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewPts   d))                 -> interpretRest sxs fp_poly {fpPolyPts = d}             Right (PcbnewExprAttribute (PcbnewWidth d))@@ -222,18 +228,18 @@ asPcbnewPad (n:t:s:xs) = interpretNumber     where         interpretNumber = case n of-            (AtomStr num) -> interpretType defaultPcbnewPad {padNumber = num}+            (Atom _ num) -> interpretType defaultPcbnewPad {padNumber = num}             _ -> expecting "string designating pad number" n         interpretType :: PcbnewItem -> Either String PcbnewItem         interpretType pad = case t of-            (AtomStr str) -> case strToPadType str of+            (Atom _ str) -> case strToPadType str of                     Just d  -> interpretShape pad {padType = d}                     Nothing ->                         expecting "pad type (e.g. 'smd')" t             _ -> expecting "pad type string (e.g. 'smd')" t         interpretShape :: PcbnewItem -> Either String PcbnewItem         interpretShape pad = case s of-            (AtomStr str) -> case strToPadShape str of+            (Atom _ str) -> case strToPadShape str of                     Just d  -> interpretRest xs pad {padShape = d}                     Nothing ->                         expecting "pad shape (e.g. 'circle')" s@@ -241,7 +247,7 @@         interpretRest :: [SExpr] -> PcbnewItem -> Either String PcbnewItem         interpretRest [] pad = Right pad         interpretRest (sx:sxs) pad = case fromSExpr sx of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewAt d))                 -> interpretRest sxs pad {itemAt = d}             Right (PcbnewExprAttribute (PcbnewLayers d))@@ -268,6 +274,8 @@                 -> pushToAttrs sxs a pad             Right (PcbnewExprAttribute a@(PcbnewRoundrectRratio _))                 -> pushToAttrs sxs a pad+            Right (PcbnewExprAttribute a@(PcbnewDieLength _))+                -> pushToAttrs sxs a pad             _ -> expecting "at, size, drill, layers , margins etc. or nothing" sx         pushToAttrs sxs a pad = interpretRest sxs (over padAttributes (++[a]) pad) asPcbnewPad xs = expecting' "number, type and shape" xs@@ -277,31 +285,49 @@ asPcbnewLayer x    = expecting' "only one layer name" x  onePcbnewLayer :: SExpr -> Either String PcbnewAttribute-onePcbnewLayer (AtomStr n) = case strToLayer n of+onePcbnewLayer (Atom _ n) = case strToLayer n of     Just l  -> Right $ PcbnewLayer l     Nothing -> Left ("-> Unknown layer name: " ++ n) onePcbnewLayer x = expecting "layer name" x  asPcbnewAt :: [SExpr] -> Either String PcbnewAttribute-asPcbnewAt (AtomDbl x:[AtomDbl y]) =-    Right $ PcbnewAt $ defaultPcbnewAtT {pcbnewAtPoint = (x,y)}-asPcbnewAt (AtomDbl x:AtomDbl y:[AtomDbl o]) =-    Right $ PcbnewAt $ PcbnewAtT (x,y) o-asPcbnewAt l@[List _] = asXyz PcbnewModelAt l+asPcbnewAt sx@(Atom _ x:[Atom _ y]) = case readXy x y of+    Just xy -> Right $ PcbnewAt $ defaultPcbnewAtT {pcbnewAtPoint = xy}+    Nothing -> expecting' "x y coordinates" sx+asPcbnewAt sx@(Atom _ x:Atom _ y:[Atom _ o]) = case readXyz x y o of+    Just (x', y', o') -> Right $ PcbnewAt $ PcbnewAtT (x',y') o'+    Nothing -> expecting' "x y coordinates and orientation" sx+asPcbnewAt l@[List _ _] = asXyz PcbnewModelAt l asPcbnewAt x =-    expecting' "two or three floats or an 'xyz' expression" x+    expecting' "x y coordinates and orientation" x +readXy :: String -> String -> Maybe (Double, Double)+readXy x y = do+   x' <- readMaybeDouble x+   y' <- readMaybeDouble y+   return (x', y') ++readXyz :: String -> String -> String -> Maybe (Double, Double, Double)+readXyz x y z = do+   x' <- readMaybeDouble x+   y' <- readMaybeDouble y+   z' <- readMaybeDouble z+   return (x', y', z')++ asPcbnewEffects :: [SExpr] -> Either String PcbnewAttribute asPcbnewEffects xs = interpretRest xs []    where       interpretRest [] effects = Right (PcbnewFpTextEffects effects)       interpretRest (sx:sxs) effects = case fromSExpr sx of-         Left err -> Left ('\t':err)+         Left err -> Left err          Right (PcbnewExprAttribute justify@(PcbnewJustify _))             -> interpretRest sxs (justify:effects)          Right (PcbnewExprAttribute font@(PcbnewFont _ _ _))             -> interpretRest sxs (font:effects)+         Right (PcbnewExprAttribute PcbnewHide)+            -> interpretRest sxs (PcbnewHide:effects)          _ -> expecting "font or justify expression" sx  @@ -310,7 +336,7 @@     where         interpretRest [] font = Right font         interpretRest (sx:sxs) font = case fromSExpr sx of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewSize size)) ->                 interpretRest sxs font {pcbnewFontSize = size}             Right (PcbnewExprAttribute (PcbnewThickness t)) ->@@ -320,19 +346,21 @@             Right _ -> expecting "size, thickness or 'italic'" sx  asXy :: ((Double, Double) -> a) -> [SExpr] -> Either String a-asXy constructor [AtomDbl x, AtomDbl y] = Right $ constructor (x,y)+asXy constructor sx@[Atom _ x, Atom _ y] = case readXy x y of+   Just xy -> Right $ constructor xy+   Nothing -> expecting' "two floats (e.g. 1.0 1.0)" sx asXy _ x = expecting' "two floats (e.g. 1.0 1.0)" x  asPcbnewPts :: [SExpr] -> Either String PcbnewAttribute asPcbnewPts = fmap PcbnewPts . foldr interpretXys (Right [])     where interpretXys sx z = case fromSExpr sx of-                        Left err -> Left ('\t':err)+                        Left err -> Left err                         Right (PcbnewExprAttribute (PcbnewXy xy))                             -> Right (xy:) <*> z                         Right _ -> expecting "'xy' (e.g. '(xy 1.0 1.0)')" sx  asString :: (String -> PcbnewAttribute) -> [SExpr] -> Either String PcbnewAttribute-asString pcbnew [AtomStr s] =  Right $ pcbnew s+asString pcbnew [Atom _ s] =  Right $ pcbnew s asString _ x = expecting' "string" x  asPcbnewLayers :: [SExpr] -> Either String PcbnewAttribute@@ -343,11 +371,15 @@                     ++ unlines (map ("\t\t"++) (lefts layers))  asDouble :: (Double -> PcbnewAttribute) -> [SExpr] -> Either String PcbnewAttribute-asDouble constructor [AtomDbl d] = Right $ constructor d+asDouble constructor [sx@(Atom _ d)] = case readMaybeDouble d of+   Just d' -> Right $ constructor d'+   Nothing -> expecting "one float (e.g. '1.0')" sx asDouble _ x = expecting' "one float (e.g. '1.0')" x  asInt :: (Int -> PcbnewAttribute) -> [SExpr] -> Either String PcbnewAttribute-asInt constructor [AtomDbl d] = Right $ constructor $ round d+asInt constructor [sx@(Atom _ i)] = case readMaybe i of+   Just i' -> Right $ constructor i'+   Nothing -> expecting "one int (e.g. '1')" sx asInt _ x = expecting' "one int (e.g. '1')" x  asPcbnewDrill :: [SExpr] -> Either String PcbnewAttribute@@ -355,39 +387,41 @@     where         interpretRest [] drill = Right $ PcbnewDrill drill         interpretRest (sx:sxs) drill = case sx of-            AtomDbl d  -> if isNothing (pcbnewDrillSize drill)-                          then interpretRest sxs drill-                                { pcbnewDrillSize = Just (d,d) }-                          else interpretRest sxs drill-                               { pcbnewDrillSize =-                                    fmap (\(x,_) -> (x,d)) (pcbnewDrillSize drill)-                               }-            AtomStr "oval"  -> interpretRest sxs drill {pcbnewDrillOval = True}-            (List _) -> case fromSExpr sx of-                Left err -> Left ('\t':err)+            Atom _ "oval"  -> interpretRest sxs drill {pcbnewDrillOval = True}+            (List _ _) -> case fromSExpr sx of+                Left err -> Left err                 Right (PcbnewExprAttribute (PcbnewOffset xy))                     -> interpretRest sxs drill {pcbnewDrillOffset = Just xy}                 Right _ -> expecting "offset or nothing" sx-            _ -> expecting "float, 'oval' or offset" sx+            Atom _ d  -> case readMaybeDouble d of+                Just d' -> if isNothing (pcbnewDrillSize drill)+                           then interpretRest sxs drill+                                { pcbnewDrillSize = Just (d',d') }+                           else interpretRest sxs drill+                                { pcbnewDrillSize =+                                     fmap (\(x,_) -> (x,d')) (pcbnewDrillSize drill)+                                }+                Nothing -> expecting "float, 'oval' or offset" sx  asPcbnewXyz :: [SExpr] -> Either String PcbnewAttribute-asPcbnewXyz (AtomDbl x:AtomDbl y:[AtomDbl z]) =-    Right $ PcbnewXyz (x,y,z)+asPcbnewXyz sx@(Atom _ x:Atom _ y:[Atom _ z]) = case readXyz x y z of+    Just xyz -> Right $ PcbnewXyz xyz+    Nothing -> expecting' "three floats" sx asPcbnewXyz x = expecting' "three floats" x  asXyz :: (PcbnewAttribute -> a) -> [SExpr] -> Either String a-asXyz constructor [l@(List _)] = case fromSExpr l of-    Left err -> Left ('\t':err)+asXyz constructor [l@(List _ _)] = case fromSExpr l of+    Left err -> Left err     Right (PcbnewExprAttribute xyz) -> Right $ constructor xyz     Right _ -> expecting "xyz (e.g. '(xyz 1 1 1)')" l asXyz _ x = expecting' "xyz (e.g. '(xyz 1 1 1)')" x  asPcbnewModel :: [SExpr] -> Either String PcbnewAttribute-asPcbnewModel (AtomStr p:xs) = interpretRest xs defaultPcbnewModel {pcbnewModelPath = p}+asPcbnewModel (Atom _ p:xs) = interpretRest xs defaultPcbnewModel {pcbnewModelPath = p}     where         interpretRest [] model = Right model         interpretRest (sx:sxs) model = case fromSExpr sx of-            Left err -> Left ('\t':err)+            Left err -> Left err             Right (PcbnewExprAttribute (PcbnewModelAt (PcbnewXyz xyz))) ->                 interpretRest sxs model {pcbnewModelAt = xyz}             Right (PcbnewExprAttribute (PcbnewModelScale (PcbnewXyz xyz))) ->@@ -411,7 +445,7 @@    where js = fmap oneJustifyT sx  oneJustifyT :: SExpr -> Either String PcbnewJustifyT-oneJustifyT sx@(AtomStr s) = case strToJustify s of+oneJustifyT sx@(Atom _ s) = case strToJustify s of    Just j -> Right j    Nothing -> expecting justifyOneOf sx oneJustifyT x = expecting justifyOneOf x@@ -419,7 +453,7 @@  expecting :: String -> SExpr -> Either String a expecting x y =-    Left $ "-> Expecting " ++ x ++ " but got " +++    Left $ "Error in " ++ pos ++ ": expecting " ++ x ++ " but got " ++         nothing_or (strip_brackets (write y)) ++ " instead"     where         nothing_or y' = case y' of@@ -428,6 +462,19 @@         strip_brackets y' = case head y' of                 '(' -> tail . init $ y'                 _   -> y'+        pos = show (getPos y) + expecting' :: String -> [SExpr] -> Either String a-expecting' x y = expecting x $ List y+expecting' x y = expecting x $ List (newPos "" 0 0) y+++{- Like readMaybe but allows for '.1' and '-.1' style doubles -}+readMaybeDouble :: String -> Maybe Double+readMaybeDouble str@(c1:c2:rest) = case c1 of+   '.' -> readMaybe ('0':str)+   '-' -> case c2 of+      '.' -> readMaybe ('-':'0':rest)+      _   -> readMaybe str+   _  -> readMaybe str+readMaybeDouble str = readMaybe str
Data/Kicad/PcbnewExpr/PcbnewExpr.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} module Data.Kicad.PcbnewExpr.PcbnewExpr ( -- * Types@@ -59,6 +60,7 @@ import Data.Tuple (swap) import Data.Maybe import Data.Foldable (foldMap)+import Text.Parsec.Pos (newPos, SourcePos)  import Data.Kicad.SExpr.SExpr import Data.Kicad.Util@@ -86,10 +88,14 @@                                  }     deriving (Show, Eq) ++pos :: SourcePos+pos = newPos "" 0 0+ instance SExpressable PcbnewModule where     toSExpr (PcbnewModule name l attrs items) =-        List $ [ AtomKey KeyModule-               , AtomStr name+        List pos $ [ Atom pos "module"+               , Atom pos name                , toSExpr (PcbnewLayer l)                ] ++ map toSExpr attrs                ++ map toSExpr items@@ -185,32 +191,32 @@  instance SExpressable PcbnewItem where     toSExpr (PcbnewFpText t s a l h si th i j) =-        List $ [ AtomKey KeyFpText-               , AtomStr $ fpTextTypeToStr t-               , AtomStr s+        List pos $ [ Atom pos "fp_text"+               , Atom pos $ fpTextTypeToStr t+               , Atom pos s                , toSExpr (PcbnewAt a)                , toSExpr (PcbnewLayer l)                ]-               ++ [AtomStr "hide" | h]+               ++ [Atom pos "hide" | h]                ++ [toSExpr $ PcbnewFpTextEffects $                       [PcbnewFont si th i]                       ++ if j == [] then [] else [PcbnewJustify j]]     toSExpr (PcbnewFpLine s e l w) =-        List [ AtomKey KeyFpLine+        List pos [ Atom pos "fp_line"              , toSExpr (PcbnewStart s)              , toSExpr (PcbnewEnd   e)              , toSExpr (PcbnewLayer l)              , toSExpr (PcbnewWidth w)              ]     toSExpr (PcbnewFpCircle s e l w) =-        List [ AtomKey KeyFpCircle+        List pos [ Atom pos "fp_circle"              , toSExpr (PcbnewCenter s)              , toSExpr (PcbnewEnd    e)              , toSExpr (PcbnewLayer  l)              , toSExpr (PcbnewWidth  w)              ]     toSExpr (PcbnewFpArc s e a l w) =-        List [ AtomKey KeyFpArc+        List pos [ Atom pos "fp_arc"              , toSExpr (PcbnewStart s)              , toSExpr (PcbnewEnd   e)              , toSExpr (PcbnewAngle a)@@ -218,16 +224,16 @@              , toSExpr (PcbnewWidth w)              ]     toSExpr (PcbnewFpPoly ps l w) =-        List [ AtomKey KeyFpPoly+        List pos [ Atom pos "fp_poly"              , toSExpr (PcbnewPts ps)              , toSExpr (PcbnewLayer l)              , toSExpr (PcbnewWidth w)              ]     toSExpr (PcbnewPad n t s a si l attrs) =-        List $ [ AtomKey KeyPad-               , AtomStr n-               , AtomStr $ fpPadTypeToStr t-               , AtomStr $ fpPadShapeToStr s+        List pos $ [ Atom pos "pad"+               , Atom pos n+               , Atom pos $ fpPadTypeToStr t+               , Atom pos $ fpPadShapeToStr s                , toSExpr $ PcbnewAt a                , toSExpr $ PcbnewSize si                , toSExpr $ PcbnewLayers l@@ -399,6 +405,7 @@                      | PcbnewThermalWidth      Double                      | PcbnewThermalGap        Double                      | PcbnewJustify           [PcbnewJustifyT]+                     | PcbnewDieLength         Double     deriving (Show, Eq)  @@ -406,84 +413,93 @@ type PcbnewXyzT = (Double, Double, Double)  instance SExpressable PcbnewAttribute where-    toSExpr (PcbnewLayer l) = List [ AtomKey KeyLayer-                                  , AtomStr $ layerToStr l-                                  ]+    toSExpr (PcbnewLayer l) = List pos [ Atom pos "layer"+                                   , Atom pos $ layerToStr l+                                   ]     toSExpr (PcbnewAt (PcbnewAtT (x,y) o)) =-        List $ [ AtomKey KeyAt-               , AtomDbl x-               , AtomDbl y-               ] ++ [AtomDbl o | o /= 0]+        List pos $ [ Atom pos "at"+               , atomDbl x+               , atomDbl y+               ] ++ [atomDbl o | o /= 0]     toSExpr (PcbnewLayers ls) =-        List (AtomKey KeyLayers : map (AtomStr . layerToStr) ls)+        List pos (Atom pos "layers" : map (Atom pos . layerToStr) ls)     toSExpr (PcbnewFont s t i) =-        List $ [ AtomKey KeyFont, toSExpr (PcbnewSize s)+        List pos $ [ Atom pos "font", toSExpr (PcbnewSize s)                , toSExpr (PcbnewThickness t)-               ] ++ [AtomStr "italic" | i]+               ] ++ [Atom pos "italic" | i]     toSExpr (PcbnewPts xys) =-        List $ AtomKey KeyPts : map (toSExpr . PcbnewXy) xys+        List pos $ Atom pos "pts" : map (toSExpr . PcbnewXy) xys     toSExpr (PcbnewModel p a s r) =-        List [AtomKey KeyModel-             , AtomStr p+        List pos [ Atom pos "model"+             , Atom pos p              , toSExpr (PcbnewModelAt     (PcbnewXyz a))              , toSExpr (PcbnewModelScale  (PcbnewXyz s))              , toSExpr (PcbnewModelRotate (PcbnewXyz r))              ]     toSExpr (PcbnewDrill (PcbnewDrillT s o off)) =-        List $ [AtomKey KeyDrill]-             ++ [AtomStr "oval" | o]+        List pos $ [Atom pos "drill"]+             ++ [Atom pos "oval" | o]              ++ (if o && isJust s-                then [AtomDbl (fst (fromJust s)), AtomDbl (snd (fromJust s))]-                else [AtomDbl (fst (fromJust s)) | isJust s])+                then [atomDbl (fst (fromJust s)), atomDbl (snd (fromJust s))]+                else [atomDbl (fst (fromJust s)) | isJust s])              ++ [toSExpr (PcbnewOffset (fromJust off)) | isJust off]     toSExpr (PcbnewXyz (x,y,z)) =-        List [AtomKey KeyXyz, AtomDbl x, AtomDbl y, AtomDbl z]-    toSExpr (PcbnewFpTextEffects l)  = List $ [AtomKey KeyEffects] ++ fmap toSExpr l-    toSExpr (PcbnewFpTextType t)     = AtomStr $ fpTextTypeToStr t-    toSExpr (PcbnewModelAt     xyz)  = List [AtomKey KeyAt    , toSExpr xyz]-    toSExpr (PcbnewModelScale  xyz)  = List [AtomKey KeyScale , toSExpr xyz]-    toSExpr (PcbnewModelRotate xyz)  = List [AtomKey KeyRotate, toSExpr xyz]-    toSExpr (PcbnewClearance   d) = toSxD KeyClearance              d-    toSExpr (PcbnewSolderPasteRatio d) = toSxD KeySolderPasteRatio  d-    toSExpr (PcbnewMaskMargin  d) = toSxD KeySolderMaskMargin       d-    toSExpr (PcbnewPasteMargin d) = toSxD KeySolderPasteMargin      d-    toSExpr (PcbnewPasteMarginRatio d) = toSxD KeySolderPasteMarginRatio d-    toSExpr (PcbnewRoundrectRratio  d) = toSxD KeyRoundrectRratio d-    toSExpr (PcbnewThickness   d) = toSxD KeyThickness      d-    toSExpr (PcbnewWidth       d) = toSxD KeyWidth          d-    toSExpr (PcbnewAngle       d) = toSxD KeyAngle          d-    toSExpr (PcbnewThermalWidth d) = toSxD KeyThermalWidth  d-    toSExpr (PcbnewThermalGap   d) = toSxD KeyThermalGap    d-    toSExpr (PcbnewSize      xy)  = toSxDD KeySize      xy-    toSExpr (PcbnewStart     xy)  = toSxDD KeyStart     xy-    toSExpr (PcbnewCenter    xy)  = toSxDD KeyCenter    xy-    toSExpr (PcbnewRectDelta xy)  = toSxDD KeyRectDelta xy-    toSExpr (PcbnewEnd       xy)  = toSxDD KeyEnd       xy-    toSExpr (PcbnewXy        xy)  = toSxDD KeyXy        xy-    toSExpr (PcbnewOffset    xy)  = toSxDD KeyOffset    xy-    toSExpr (PcbnewTedit s)       = toSxStr KeyTedit s-    toSExpr (PcbnewDescr s)       = toSxStr KeyDescr s-    toSExpr (PcbnewTags  s)       = toSxStr KeyTags  s-    toSExpr (PcbnewPath  s)       = toSxStr KeyPath  s-    toSExpr (PcbnewAttr  s)       = toSxStr KeyAttr  s-    toSExpr PcbnewItalic = AtomStr "italic"-    toSExpr PcbnewHide   = AtomStr "hide"-    toSExpr PcbnewPlaced = AtomStr "placed"-    toSExpr PcbnewLocked = AtomStr "locked"-    toSExpr (PcbnewAutoplaceCost90  i) = toSxD KeyAutoplaceCost90  (fromIntegral i)-    toSExpr (PcbnewAutoplaceCost180 i) = toSxD KeyAutoplaceCost180 (fromIntegral i)-    toSExpr (PcbnewZoneConnect      i) = toSxD KeyZoneConnect      (fromIntegral i)-    toSExpr (PcbnewJustify         js) = List $ AtomKey KeyJustify:map (AtomStr . justifyToString) js+        List pos [Atom pos "xyz", atomDbl x, atomDbl y, atomDbl z]+    toSExpr (PcbnewFpTextEffects l)  = List pos $ [Atom pos "effects"] ++ fmap toSExpr l+    toSExpr (PcbnewFpTextType t)     = Atom pos $ fpTextTypeToStr t+    toSExpr (PcbnewModelAt     xyz)  = List pos [Atom pos "at"    , toSExpr xyz]+    toSExpr (PcbnewModelScale  xyz)  = List pos [Atom pos "scale" , toSExpr xyz]+    toSExpr (PcbnewModelRotate xyz)  = List pos [Atom pos "rotate", toSExpr xyz]+    toSExpr (PcbnewClearance   d)      = toSxD "clearance"                 d+    toSExpr (PcbnewSolderPasteRatio d) = toSxD "solder_paste_ratio"        d+    toSExpr (PcbnewMaskMargin  d)      = toSxD "solder_mask_margin"        d+    toSExpr (PcbnewPasteMargin d)      = toSxD "solder_paste_margin"       d+    toSExpr (PcbnewPasteMarginRatio d) = toSxD "solder_paste_margin_ratio" d+    toSExpr (PcbnewRoundrectRratio  d) = toSxD "roundrect_rratio"          d+    toSExpr (PcbnewThickness   d)      = toSxD "thickness"                 d+    toSExpr (PcbnewWidth       d)      = toSxD "width"                     d+    toSExpr (PcbnewAngle       d)      = toSxD "angle"                     d+    toSExpr (PcbnewThermalWidth d)     = toSxD "thermal_width"             d+    toSExpr (PcbnewThermalGap   d)     = toSxD "thermal_gap"               d+    toSExpr (PcbnewDieLength   d)      = toSxD "die_length"                d+    toSExpr (PcbnewSize      xy)       = toSxDD "size"       xy+    toSExpr (PcbnewStart     xy)       = toSxDD "start"      xy+    toSExpr (PcbnewCenter    xy)       = toSxDD "center"     xy+    toSExpr (PcbnewRectDelta xy)       = toSxDD "rect_delta" xy+    toSExpr (PcbnewEnd       xy)       = toSxDD "end"        xy+    toSExpr (PcbnewXy        xy)       = toSxDD "xy"         xy+    toSExpr (PcbnewOffset    xy)       = toSxDD "offset"     xy+    toSExpr (PcbnewTedit s)            = toSxStr "tedit" s+    toSExpr (PcbnewDescr s)            = toSxStr "descr" s+    toSExpr (PcbnewTags  s)            = toSxStr "tags"  s+    toSExpr (PcbnewPath  s)            = toSxStr "path"  s+    toSExpr (PcbnewAttr  s)            = toSxStr "attr"  s+    toSExpr PcbnewItalic               = Atom pos "italic"+    toSExpr PcbnewHide                 = Atom pos "hide"+    toSExpr PcbnewPlaced               = Atom pos "placed"+    toSExpr PcbnewLocked               = Atom pos "locked"+    toSExpr (PcbnewAutoplaceCost90  i) =+        List pos [Atom pos "autoplace_cost90"  , Atom pos (show i)]+    toSExpr (PcbnewAutoplaceCost180 i) =+        List pos [Atom pos "autoplace_cost180" , Atom pos (show i)]+    toSExpr (PcbnewZoneConnect      i) =+        List pos [Atom pos "zone_connect"      , Atom pos (show i)]+    toSExpr (PcbnewJustify         js) =+        List pos $ (Atom pos "justify"):map (Atom pos . justifyToString) js -toSxD :: Keyword -> Double -> SExpr-toSxD  kw d = List [AtomKey kw, AtomDbl d] -toSxDD :: Keyword -> V2Double -> SExpr-toSxDD kw (x,y) = List [AtomKey kw, AtomDbl x, AtomDbl y]+atomDbl :: Double -> SExpr+atomDbl = Atom pos . show -toSxStr :: Keyword -> String -> SExpr-toSxStr kw s = List [AtomKey kw, AtomStr s]+toSxD :: String -> Double -> SExpr+toSxD kw d = List pos [Atom pos kw, atomDbl d] +toSxDD :: String -> V2Double -> SExpr+toSxDD kw (x,y) = List pos [Atom pos kw, atomDbl x, atomDbl y]++toSxStr :: String -> String -> SExpr+toSxStr kw s = List pos [Atom pos kw, Atom pos s]+ instance AEq PcbnewAttribute where     (PcbnewAt                x) ~== (PcbnewAt                y) = x ~== y     (PcbnewSize              x) ~== (PcbnewSize              y) = x ~== y@@ -531,7 +547,8 @@                   | BCu       | BPaste    | BMask     | DwgsUser  | CmtsUser                   | FAdhes    | AllSilk   | FandBCu   | AllCu     | AllMask                   | AllPaste  | EdgeCuts  | FCrtYd    | BCrtYd    | FFab-                  | BFab      | Margin    | Eco1User  | Eco2User  | BAdhes+                  | BFab      | AllFab    | Margin    | Eco1User  | Eco2User+                  | BAdhes                   | Inner1Cu  | Inner2Cu  | Inner3Cu  | Inner4Cu  | Inner5Cu                   | Inner6Cu  | Inner7Cu  | Inner8Cu  | Inner9Cu  | Inner10Cu                   | Inner11Cu | Inner12Cu | Inner13Cu | Inner14Cu | Inner15Cu@@ -564,6 +581,7 @@     , ("B.CrtYd"   , BCrtYd)     , ("F.Fab"     , FFab)     , ("B.Fab"     , BFab)+    , ("*.Fab"     , AllFab)     , ("Edge.Cuts" , EdgeCuts)     , ("Margin"    , Margin)     , ("Eco1.User" , Eco1User)
Data/Kicad/SExpr.hs view
@@ -4,14 +4,14 @@ ( -- * Types   SExpr(..)-, Keyword(..) , SExpressable(..) -- * Writing , pretty , write-, writeKeyword -- * Parsing , parse+, parseWithFilename+, getPos ) where import Data.Kicad.SExpr.SExpr
Data/Kicad/SExpr/Parse.hs view
@@ -2,24 +2,28 @@ {-# OPTIONS_GHC -fno-warn-unused-do-bind #-} module Data.Kicad.SExpr.Parse ( parse+, parseWithFilename ) where import Text.ParserCombinators.Parsec hiding (spaces, parse) import qualified Text.ParserCombinators.Parsec as Parsec (parse)-import Text.ParserCombinators.Parsec.Number import Text.Parsec.Char (endOfLine)-import Control.Monad+import Text.Parsec (getPosition)  import Data.Kicad.SExpr.SExpr-import Data.Kicad.SExpr.Write (writeKeyword)  {-| Parse a 'String' as a 'SExpr' or return an error. -} parse :: String -> Either String SExpr-parse input = case Parsec.parse parseListOrComment "SExpr" input of-    Left err -> Left $ "Parse Error: " ++ show err-    Right val -> Right val+parse = parseWithFilename "" +{-| Parse a 'String' as a 'SExpr' giving a filename to use in the source code location -}+parseWithFilename :: String -> String -> Either String SExpr+parseWithFilename filename input =+    case Parsec.parse parseListOrComment filename input of+        Left err -> Left $ "Parse Error: " ++ show err+        Right val -> Right val + parseListOrComment :: Parser SExpr parseListOrComment = do     spaces@@ -39,77 +43,34 @@  parseList :: Parser SExpr parseList = do+    pos <- getPosition     char '('     spaces-    first <- parseKeyword-    spaces-    rest <- let parseRest = try parseAtom `sepEndBy` spaces in case first of-        AtomKey KeyFpText -> do t <- parseString-                                  <?> "string designating type e.g. 'user'"-                                spaces1-                                s <- parseString-                                spaces-                                r <- parseRest-                                return (t:s:r)-        AtomKey KeyModule -> do t <- parseString-                                spaces-                                r <- parseRest-                                return (t:r)-        AtomKey KeyTedit  -> do s <- parseString-                                spaces-                                return [s]-        AtomKey KeyDescr  -> do s <- parseString-                                spaces-                                return [s]-        AtomKey KeyTags   -> do s <- parseString-                                spaces-                                return [s]-        AtomKey KeyPad    -> do n <- parseString-                                spaces1-                                t <- parseString-                                  <?> "string designating type e.g. 'smd'"-                                spaces1-                                s <- parseString-                                spaces-                                r <- parseRest-                                return (n:t:s:r)-        _                 -> parseRest-    spaces+    list <- try parseExpr `sepEndBy` spaces     char ')'     spaces-    return $ List (first:rest)+    return $ List pos list -parseAtom :: Parser SExpr-parseAtom =  try parseDouble-         <|> try parseString++parseExpr :: Parser SExpr+parseExpr =  try parseString          <|> try parseListOrComment          <?> "a double, string or s-expression" -parseOneKeyword :: Keyword -> Parser SExpr-parseOneKeyword kw = try $ string (writeKeyword kw) >> return (AtomKey kw) -parseKeyword :: Parser SExpr-parseKeyword = choice (map parseOneKeyword [minBound..maxBound]) <?> "keyword"- parseString :: Parser SExpr-parseString = liftM AtomStr (parseQuotedString <|> parseUnquotedString <?> "string")-        where-            parseQuotedString  = do-                char '"'-                x <- many (noneOf "\\\"" <|> (char '\\' >> anyChar))-                char '"'-                return x-            parseUnquotedString = many1 (noneOf "\" ()\r\n")+parseString =+    do pos <- getPosition+       str <- parseQuotedString <|> parseUnquotedString <?> "string"+       return $ Atom pos str+            where+                parseQuotedString  = do+                    char '"'+                    x <- many (noneOf "\\\"" <|> (char '\\' >> anyChar))+                    char '"'+                    return x+                parseUnquotedString = many1 (noneOf " ()\r\n") -parseDouble :: Parser SExpr-parseDouble = do-    negate_or_id <- sign-    -- the Bool in floating3 is requireDigit which affects whether many (False,-    -- 0 or more) or many1 (True, 1 or more) is used-    x <- floating3 True-    lookAhead (char ')' <|> spaceChar)-    return $ AtomDbl $ negate_or_id x -spaces1 = skipMany1 spaceChar spaces = skipMany spaceChar-spaceChar = endOfLine <|> space+spaceChar = oneOf "\r\n\t "
Data/Kicad/SExpr/SExpr.hs view
@@ -1,66 +1,20 @@ module Data.Kicad.SExpr.SExpr ( SExpr(..)-, Keyword(..) , SExpressable(..)+, getPos ) where+import Text.Parsec (SourcePos) -data SExpr = AtomKey Keyword-           | AtomStr String-           | AtomDbl Double-           | List [SExpr]+data SExpr = Atom SourcePos String+           | List SourcePos [SExpr]     deriving (Show, Eq) -{- The keywords _must_ be "Key" ++ camel-case version of the ones in the- - kicad_mod files as the parser and writer use the derived 'Show' instance.- - The parser will also try them in the order they appear below so KeyAttr has- - to appear before KeyAt for instance. -}-data Keyword = KeyZoneConnect-             | KeyXyz-             | KeyXy-             | KeyWidth-             | KeyThickness-             | KeyThermalWidth-             | KeyThermalGap-             | KeyTedit-             | KeyTags-             | KeyStart-             | KeySolderPasteMarginRatio-             | KeySolderPasteMargin-             | KeySolderMaskMargin-             | KeySize-             | KeyScale-             | KeyRoundrectRratio-             | KeyRotate-             | KeyRectDelta-             | KeyPts-             | KeyPath-             | KeyPad-             | KeyOffset-             | KeyModule-             | KeyModel-             | KeyLayers-             | KeyLayer-             | KeyJustify-             | KeyFpText-             | KeyFpPoly-             | KeyFpLine-             | KeyFpCircle-             | KeyFpArc-             | KeyFont-             | KeyEnd-             | KeyEffects-             | KeyDrill-             | KeyDescr-             | KeyClearance-             | KeySolderPasteRatio-             | KeyCenter-             | KeyAutoplaceCost90-             | KeyAutoplaceCost180-             | KeyAttr-             | KeyAt-             | KeyAngle-    deriving (Show, Eq, Enum, Bounded)- class SExpressable a where     toSExpr :: a -> SExpr++{-| Get s-expression source code position (filename, line-number and+ - column-number) -}+getPos :: SExpr -> SourcePos+getPos (Atom pos _) = pos+getPos (List pos _) = pos
Data/Kicad/SExpr/Write.hs view
@@ -1,45 +1,21 @@ module Data.Kicad.SExpr.Write ( pretty , write-, writeKeyword ) where-import Data.Char (toLower, isLower, isNumber)-import Data.List (intercalate) import Text.PrettyPrint.Compact  import Data.Kicad.SExpr.SExpr -{-| Pretty-print a 'SExpr' as a readable 'Doc'. -}+{-| Pretty-print an s-expression as a readable "document". -} pretty :: SExpr -> Doc-pretty (List xs) = text "(" <> align (sep $ map pretty xs) <> text ")"+pretty (List _ xs) = text "(" <> align (sep $ map pretty xs) <> text ")" pretty atm = text $ write atm  -{-| Serialize an SExpr as a compact s-expression 'String'. -}+{-| Serialize an s-expression into a compact string. -} write :: SExpr -> String-write (AtomKey kw)  = writeKeyword kw-write (AtomStr atm) |  (atm == "")-                    || head atm `elem` '.':'-':['0'..'9']-                    || foldr-                        (\c z -> z || c `elem` ')':'(':'\\':'\"':['\0'..' '])-                            False atm = show atm -- escaped string with quotes-                    | otherwise       = atm--- this should just be printf "%g" but that doesn't work as it should-write (AtomDbl atm) = strip_zeros $ break (== '.') $ show atm-    where strip_zeros (s1,s2) = s1 ++ dot_if_needed (reverse-                                           $ dropWhile (=='0') $ reverse s2)-          dot_if_needed s     = if s == "." then "" else s-write (List    sxs) = "(" ++ unwords (map write sxs) ++ ")"--{-| Write a 'Keyword' as a 'String'. Removes \"Key\" from the 'Show'-   instance and converts the rest to underscore (e.g KeyFpTextType becomes-   "fp_text_type"). -}-writeKeyword :: Keyword -> String-writeKeyword = intercalate "_" . splitCapWords . drop 3 . show-    where-        splitCapWords "" = []-        splitCapWords (x:xs) =-            let (word, rest) = span (\c -> isLower c || isNumber c) xs-            in (toLower x : word) : splitCapWords rest-+write (Atom _ str) | (str == "") || needs_quotes = show str -- escaped string with quotes+                   | otherwise                   = str      -- bare string without quotes+    where needs_quotes = foldr (\c z -> z || c `elem` '#':')':'(':'\\':'\"':['\0'..' ']) False str+write (List _ sxs) = "(" ++ unwords (map write sxs) ++ ")"
+ Data/Kicad/Util.hs view
@@ -0,0 +1,14 @@+module Data.Kicad.Util where++import Data.Maybe++maybeHead :: [a] -> Maybe a+maybeHead [] = Nothing+maybeHead (x:_) = Just x++headOr :: a -> [a] -> a+headOr d xs = fromMaybe d (maybeHead xs)++maybeLast :: [a] -> Maybe a+maybeLast [] = Nothing+maybeLast xs = Just $ last xs
+ README.md view
@@ -0,0 +1,32 @@+# Haskell KiCad Data+[![Build Status](https://travis-ci.org/monostable/haskell-kicad-data.svg?branch=master)](https://travis-ci.org/kasbah/haskell-kicad-data)++Parse and write [KiCad](http://kicad-pcb.org) data (currently .kicad_mod files only).++This library is tested with QuickCheck to ensure it can parse whatever it outputs. +The parser is also fairly regularily checked against over 38,000 kicad_mod files currently part of [monostable/kicad_footprints](https://github.com/monostable/kicad_footprints). The resulting output of these parsed files is then checked with KiCad scripting to make sure they are still valid.++# Usage++    $ cabal repl++```+*Data.Kicad.PcbnewExpr> let pad = parse "(pad 1 smd rect (size 1 1) (at 1 1) (layers F.Cu))"+*Data.Kicad.PcbnewExpr> pad+Right (PcbnewExprItem (PcbnewPad {padNumber = "1", padType = SMD, padShape =+Rect, itemAt = PcbnewAtT {pcbnewAtPoint = (1.0,1.0), pcbnewAtOrientation =+0.0}, itemSize = (1.0,1.0), padLayers = [FCu], padAttributes_ = []}))+*Data.Kicad.PcbnewExpr> fmap write pad+Right "(pad \"1\" smd rect (at 1 1) (size 1 1) (layers F.Cu))"+```++See [docs on Hackage](https://hackage.haskell.org/package/kicad-data).+++# Projects Using This++- [ppelleti/footprint-to-script](https://github.com/ppelleti/footprint-to-script) - Converts a KiCad footprint to a [KicadModTree](https://github.com/pointhi/kicad-footprint-generator) Python script.++# License++This project is MIT licensed but [one dependency](https://hackage.haskell.org/package/pretty-compact) is licensed under GPLv3 thus the GPLv3 applies to the project as a whole.
+ changelog.md view
@@ -0,0 +1,9 @@++---++Version 0.5.0++- Add support for *.Fab layers+- Add support for die_length pad attribute+- Fix issue with comment character output+- Simplify s-expression parser (now supports all KiCad s-expression formats)
kicad-data.cabal view
@@ -1,17 +1,21 @@ name:          kicad-data-version:       0.4.0+version:       0.5.0 synopsis:      Parser and writer for KiCad files. license:       MIT license-file:  LICENSE author:        Kaspar Emanuel-maintainer:    kaspar.emanuel@gmail.com+maintainer:    kaspar@monostable.co.uk homepage:      http://github.com/kasbah/haskell-kicad-data bug-reports:   http://github.com/kasbah/haskell-kicad-data/issues-copyright:     2014+copyright:     2018 category:      Data build-type:    Simple--- extra-source-files:+extra-source-files: README.md cabal-version: >=1.10+description:+            Parse and write <http://kicad-pcb.org/ KiCad> data+            (currently @.kicad_mod@ files only).+Extra-Source-Files: changelog.md  source-repository head   type: git@@ -28,14 +32,14 @@     , Data.Kicad.SExpr.SExpr     , Data.Kicad.SExpr.Parse     , Data.Kicad.SExpr.Write-  -- other-modules:+  other-modules:+      Data.Kicad.Util   -- other-extensions:   build-depends:-      base >=4.4 && <4.9-    , parsec >=3.1 && <3.2-    , parsec-numbers >= 0.1.0  && <0.2.0-    , lens-family >= 1.1 && <1.2-    , ieee754 >= 0.7.4 && <0.8+      base >=4.4 && <4.11+    , parsec >=3.1.6 && <3.2+    , lens-family >= 1.1 && <1.3+    , ieee754 >= 0.7.4 && <0.9     , pretty-compact >= 1.0 && < 2   -- hs-source-dirs:   default-language:    Haskell2010@@ -47,15 +51,23 @@   hs-source-dirs: tests   default-language: Haskell2010   main-is: Test.hs+  other-modules:+      PcbnewExpr+      SExpr+      Utils    build-depends:-      base >=4.4 && <4.9+      base >=4.4 && <4.11     , parsec >=3.1 && <3.2-    , parsec-numbers >= 0.1.0  && <0.2.0-    , lens-family >= 1.1 && <1.2-    , ieee754 >= 0.7.4 && <0.8+    , lens-family >= 1.1 && <1.3+    , ieee754 >= 0.7.4 && <0.9     , QuickCheck >= 2+    , HUnit >= 1.5 && < 1.7     , test-framework >= 0.8 && < 1+    , test-framework-quickcheck2 >= 0.3 && < 0.4+    , test-framework-hunit >= 0.3 && < 0.4     , test-framework-quickcheck2 >= 0.3 && < 1     , pretty-compact >= 1.0 && < 2+    , charsetdetect >= 1.1 && < 1.2+    , encoding >= 0.8.2 && < 0.9     , kicad-data
+ tests/PcbnewExpr.hs view
@@ -0,0 +1,218 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+module PcbnewExpr+( tests+)+where+import Test.Framework (Test)+import Test.Framework.Providers.QuickCheck2+import Test.QuickCheck+import Control.Monad++import Utils+import Data.Kicad.PcbnewExpr+import Data.Kicad.PcbnewExpr.PcbnewExpr++tests :: [Test]+tests = [ testProperty "parse fp_line correctly" parseFpLineCorrectly+        , testProperty "parse fp_arc correctly" parseFpArcCorrectly+        , testProperty "parse fp_poly correctly" parseFpPolyCorrectly+        , testProperty "parse and write any PcbnewExpr" parseAndWriteAnyPcbnewExpr+        , testProperty "parse and pretty any PcbnewExpr" parseAndPrettyAnyPcbnewExpr+        ]++parseFpLineCorrectly :: (Double, Double, Double, Double, Double)+                     -> PcbnewLayerT+                     -> Bool+parseFpLineCorrectly (d1, d2, d3, d4, d5) l =+    tracedPropAEq (parse fp_line) fpLine+    where+        fp_line =+            "(fp_line (start " ++ show d1 ++ " "+             ++ show d2 ++ ") (end " ++ show d3 ++ " "+             ++ show d4 ++ ") (layer "+             ++ layerToStr l+             ++ ") (width " ++ show d5 ++ "))"+        fpLine  = Right $ PcbnewExprItem+                        $ PcbnewFpLine (d1, d2) (d3, d4) l d5++parseFpArcCorrectly :: (Double, Double, Double, Double, Double) -> Double+                     -> PcbnewLayerT+                     -> Bool+parseFpArcCorrectly (d1, d2, d3, d4, d5) d6 l =+    tracedPropAEq (parse fp_arc) fpArc+    where+        fp_arc =+            "(fp_arc (start " ++ show d1 ++ " "+            ++ show d2 ++ ") (end " ++ show d3 ++ " "+            ++ show d4 ++ ") (angle " ++ show d5+            ++ ") (layer " ++ layerToStr l ++ ") (width "+            ++ show d6 ++ "))"+        fpArc = Right $ PcbnewExprItem+                      $ PcbnewFpArc (d1, d2) (d3, d4) d5 l d6++parseFpPolyCorrectly :: [(Double, Double)] -> Double+                     -> PcbnewLayerT+                     -> Bool+parseFpPolyCorrectly ds w l =+    tracedPropAEq (parse fp_poly) fpPoly+    where+        fp_poly =+            "(fp_poly (pts "+            ++ unwords+                (map+                  (\(d1,d2) -> "(xy " ++ show d1 ++ " " ++ show d2 ++ ")")+                    ds)+            ++ ") (layer " ++ layerToStr l ++ ") (width "+            ++ show w ++ "))"+        fpPoly = Right $ PcbnewExprItem $ PcbnewFpPoly ds l w++parseAndWriteAnyPcbnewExpr :: PcbnewExpr -> Bool+parseAndWriteAnyPcbnewExpr a = tracedPropAEq t1 t2+    where t1 = parse $ write a+          t2 = Right a++parseAndPrettyAnyPcbnewExpr :: PcbnewExpr -> Bool+parseAndPrettyAnyPcbnewExpr a = tracedPropAEq t1 t2+    where t1 = parse $ show $ pretty a+          t2 = Right a++instance Arbitrary PcbnewExpr where+    arbitrary = oneof [ do a <- arbitrary+                           return $ PcbnewExprModule a+                      , do a <- arbitrary+                           return $ PcbnewExprItem a+                      , do a <- arbitrary+                           return $ PcbnewExprAttribute a+                      ]++instance Arbitrary PcbnewModule where+    arbitrary = do n <- genSafeString+                   l <- arbitrary+                   attrs <- listOf genModuleAttr+                   items <- arbitrary+                   return $ PcbnewModule n l attrs items+        where+            genModuleAttr :: Gen PcbnewAttribute+            genModuleAttr = suchThat arbitrary not_layer+            not_layer (PcbnewLayer _) = False+            not_layer _ = True++instance Arbitrary PcbnewItem where+    arbitrary = oneof [ do t  <- arbitrary+                           s  <- genSafeString+                           a  <- arbitrary+                           l  <- arbitrary+                           h  <- arbitrary+                           si <- arbitrary+                           th <- arbitrary+                           i  <- arbitrary+                           j  <- arbitrary+                           return $ PcbnewFpText t s a l h si th i j+                      , do s <- arbitrary+                           e <- arbitrary+                           l <- arbitrary+                           w <- arbitrary+                           fp <- elements [PcbnewFpLine, PcbnewFpCircle]+                           return $ fp s e l w+                      , do s <- arbitrary+                           e <- arbitrary+                           a <- arbitrary+                           l <- arbitrary+                           w <- arbitrary+                           return $ PcbnewFpArc s e a l w+                      , do ps <- arbitrary+                           l  <- arbitrary+                           w  <- arbitrary+                           return $ PcbnewFpPoly ps l w+                      , do n  <- genSafeString+                           t  <- arbitrary+                           s  <- arbitrary+                           a  <- arbitrary+                           si <- arbitrary+                           l  <- arbitrary+                           attrs <- listOf genPadAttrs+                           return $ PcbnewPad n t s a si l attrs+                      ]++genPadAttrs :: Gen PcbnewAttribute+genPadAttrs = oneof [ liftM PcbnewRectDelta        arbitrary+                    , liftM PcbnewMaskMargin       arbitrary+                    , liftM PcbnewPasteMarginRatio arbitrary+                    , liftM PcbnewPasteMargin      arbitrary+                    , liftM PcbnewClearance        arbitrary+                    , liftM PcbnewZoneConnect      arbitrary+                    , liftM PcbnewThermalWidth     arbitrary+                    , liftM PcbnewThermalGap       arbitrary+                    , do a <- arbitrary+                         b <- arbitrary+                         return $ PcbnewDrill $ PcbnewDrillT a True b+                    , do a <- suchThatMaybe arbitrary (uncurry (==))+                         b <- arbitrary+                         return $ PcbnewDrill $ PcbnewDrillT a False b+                    ]++instance Arbitrary PcbnewAttribute where+    arbitrary = oneof [ genPadAttrs+                      , oneof [ liftM PcbnewLayer     arbitrary+                              , liftM PcbnewAt        arbitrary+                              , liftM PcbnewSize      arbitrary+                              , liftM PcbnewThickness arbitrary+                              , liftM PcbnewTedit     genSafeString+                              , liftM PcbnewStart     arbitrary+                              , liftM PcbnewEnd       arbitrary+                              , liftM PcbnewCenter    arbitrary+                              , liftM PcbnewWidth     arbitrary+                              , liftM PcbnewDescr     genSafeString+                              , liftM PcbnewTags      genSafeString+                              , liftM PcbnewAttr      genSafeString+                              , liftM PcbnewLayers    arbitrary+                              , liftM PcbnewAngle     arbitrary+                              , liftM PcbnewXy        arbitrary+                              , liftM PcbnewPts       arbitrary+                              , liftM PcbnewXyz       arbitrary+                              , liftM PcbnewZoneConnect  arbitrary+                              , liftM PcbnewThermalGap   arbitrary+                              , liftM PcbnewThermalWidth arbitrary+                              , liftM PcbnewModelScale   arbitrary+                              , liftM PcbnewModelRotate  arbitrary+                              , liftM PcbnewClearance    arbitrary+                              , liftM PcbnewMaskMargin   arbitrary+                              , liftM PcbnewPasteMargin  arbitrary+                              , liftM PcbnewPasteMarginRatio  arbitrary+                              , liftM PcbnewAutoplaceCost90   arbitrary+                              , liftM PcbnewAutoplaceCost180  arbitrary+                              , liftM PcbnewJustify arbitrary+                              , do s <- arbitrary+                                   t <- arbitrary+                                   i <- arbitrary+                                   return $ PcbnewFont s t i+                              , do p <- genSafeString+                                   a <- arbitrary+                                   s <- arbitrary+                                   r <- arbitrary+                                   return $ PcbnewModel p a s r+                             ]+                    ]+++instance Arbitrary PcbnewJustifyT where+    arbitrary = arbitraryBoundedEnum+++instance Arbitrary PcbnewLayerT where+    arbitrary = arbitraryBoundedEnum++instance Arbitrary PcbnewFpTextTypeT where+    arbitrary = arbitraryBoundedEnum++instance Arbitrary PcbnewPadShapeT where+    arbitrary = arbitraryBoundedEnum++instance Arbitrary PcbnewPadTypeT where+    arbitrary = arbitraryBoundedEnum++instance Arbitrary PcbnewAtT where+    arbitrary = do p <- arbitrary+                   o <- arbitrary+                   return $ PcbnewAtT p o+
+ tests/SExpr.hs view
@@ -0,0 +1,70 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+module SExpr+( tests+)+where+import Test.Framework (Test)+import Test.Framework.Providers.QuickCheck2 (testProperty)+import Test.Framework.Providers.HUnit  (testCase)+import Test.HUnit (assertFailure)+import Test.QuickCheck+import Control.Monad (liftM)+import Data.Either (rights)+import Text.Parsec.Pos (newPos)++import Utils++import Data.Kicad.SExpr++tests :: [Test]+tests = [ testProperty "deterministic 1" deterministic1+        , testCase "allows quote marks in unquoted strings" allowQuoteMarks1+        , testCase "allows quote marks in unquoted strings 2" allowQuoteMarks2+        ]+++instance Arbitrary SExpr where+    arbitrary = sized arbitrarySExp+++pos = newPos "" 0 0+-- so we don't create infinitely large s-expressions we keep reducing the size+-- as we go deeper and return atoms when the size is 0+arbitrarySExp :: Int -> Gen SExpr+arbitrarySExp n | n > 0 =+    oneof [ arbitraryAtom+          , liftM (List pos) $ resize (n `div` 2) arbitrary+          ]+arbitrarySExp _ = arbitraryAtom+++arbitraryAtom :: Gen SExpr+arbitraryAtom = liftM (Atom pos) genSafeString+++deterministic1 :: SExpr -> Bool+deterministic1 sx = tracedPropEq t1 t2+        where sx' = List pos [sx]+              t1 = write sx'+              t2 = either id write $ parse t1+++allowQuoteMarks1 :: IO ()+allowQuoteMarks1 =+    let sx = parse "(x\")" in+    if sx /= Right (List (newPos "" 1 1) [Atom (newPos "" 1 2) "x\""])+    then assertFailure ("could not parse quote mark, got: " ++ show sx)+    else return ()+++allowQuoteMarks2 :: IO ()+allowQuoteMarks2 =+    let f = "foo"+        sx = parseWithFilename f "(xxxx\"yyyy yyyy\"xxxx)"+        expected = Right $ List (newPos f 1 1)+            [ Atom (newPos f 1 2)"xxxx\"yyyy"+            , Atom (newPos f 1 12)"yyyy\"xxxx"+            ] :: Either String SExpr+    in if sx /= expected+       then assertFailure ("could not parse quote mark, got: " ++ show sx ++ "\n\texpecting: " ++ (show expected))+       else return ()
+ tests/Utils.hs view
@@ -0,0 +1,26 @@+module Utils where+import Data.AEq+import Debug.Trace+import Test.QuickCheck++genSafeString :: Gen String+genSafeString = listOf genSafeChar+    where genSafeChar :: Gen Char+          genSafeChar = elements [' '..'\126']++tracedPropAEq :: (Show a, AEq a) => a -> a -> Bool+tracedPropAEq = tracedProp (~==) "APPROX. EQUAL"++tracedPropEq :: (Show a, Eq a) => a -> a -> Bool+tracedPropEq = tracedProp (==) "EQUAL"++tracedProp :: Show a => (a -> a -> Bool) -> String -> a -> a -> Bool+tracedProp fn s t1 t2 = fn t1 t2 ||+                            trace (    "====================================="+                                     ++ "=====================================\n"+                                     ++ show t1 ++ "\n"+                                     ++ " - DOES NOT " ++ s ++ " -\n"+                                     ++ show t2 ++ "\n"+                                     ++ "====================================="+                                     ++ "====================================="+                                   ) False