gdritter repos s-cargot / 68e8eb1
Merge branch 'master' of github.com:aisamanra/s-cargot Getty Ritter 6 years ago
3 changed file(s) with 88 addition(s) and 1 deletion(s). Collapse all Expand all
2525 -- ** Numeric Literals for Arbitrary Bases
2626 , commonLispNumberAnyBase
2727 , gnuM4NumberAnyBase
28 -- ** Source locations
29 , Location(..), Located(..), located, dLocation
2830 ) where
2931
3032 #if !MIN_VERSION_base(4,8,0)
3537 import Data.Text (Text)
3638 import qualified Data.Text as T
3739 import Text.Parsec
40 import Text.Parsec.Pos (newPos)
3841 import Text.Parsec.Text (Parser)
3942
4043 -- | Parse an identifier according to the R5RS Scheme standard. This
332335 signedHexNumber :: Parser Integer
333336 signedHexNumber = ($) <$> sign <*> hexNumber
334337
338
339 -- |
340 data Location = Span !SourcePos !SourcePos
341 deriving (Eq, Ord, Show)
342
343 -- | Add support for source locations while parsing S-expressions, as described in this
344 -- <https://www.reddit.com/r/haskell/comments/4x22f9/labelling_ast_nodes_with_locations/d6cmdy9/ Reddit>
345 -- thread.
346 data Located a = At !Location a
347 deriving (Eq, Ord, Show)
348
349 -- | Adds a source span to a parser.
350 located :: Parser a -> Parser (Located a)
351 located parser = do
352 begin <- getPosition
353 result <- parser
354 end <- getPosition
355 return $ At (Span begin end) result
356
357 -- | A default location value
358 dLocation :: Location
359 dLocation = Span dPos dPos
360 where dPos = newPos "" 0 0
361
335362 {- $intro
336363
337364 This module contains a selection of parsers for different kinds of
55 -- $descr
66 basicParser
77 , basicPrinter
8 , locatedBasicParser
9 , locatedBasicPrinter
810 ) where
911
1012 import Control.Applicative ((<$>))
1113 import Data.Char (isAlphaNum)
1214 import Text.Parsec (many1, satisfy)
1315 import Data.Text (Text, pack)
16 import Data.Functor.Identity (Identity)
17 import Text.Parsec.Prim (ParsecT)
1418
19 import Data.SCargot.Common (Located(..), located)
1520 import Data.SCargot.Repr.Basic (SExpr)
1621 import Data.SCargot ( SExprParser
1722 , SExprPrinter
2429 || c == '-' || c == '*' || c == '/'
2530 || c == '+' || c == '<' || c == '>'
2631 || c == '=' || c == '!' || c == '?'
32
33 pToken :: ParsecT Text a Identity Text
34 pToken = pack <$> many1 (satisfy isAtomChar)
2735
2836 -- $descr
2937 -- The 'basicSpec' describes S-expressions whose atoms are simply
4351 -- Right [SCons (SAtom "1") (SCons (SAtom "elephant") SNil)]
4452 basicParser :: SExprParser Text (SExpr Text)
4553 basicParser = mkParser pToken
46 where pToken = pack <$> many1 (satisfy isAtomChar)
54
55 -- | A 'basicParser' which produces 'Located' values
56 --
57 -- >>> decode locatedBasicParser $ pack "(1 elephant)"
58 -- Right [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 3)) "1")) (SCons (SAtom (At (Span (line 1, column 4) (line 1, column 12)) "elephant")) SNil)]
59 --
60 -- >>> decode locatedBasicParser $ pack "(let ((x 1))\n x)"
61 -- Right [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 5)) "let")) (SCons (SCons (SCons (SAtom (At (Span (line 1, column 8) (line 1, column 9)) "x")) (SCons (SAtom (At (Span (line 1, column 10) (line 1, column 11)) "1")) SNil)) SNil) (SCons (SAtom (At (Span (line 2, column 3) (line 2, column 4)) "x")) SNil))]
62 locatedBasicParser :: SExprParser (Located Text) (SExpr (Located Text))
63 locatedBasicParser = mkParser $ located pToken
4764
4865 -- | A 'SExprPrinter' that prints textual atoms directly (without quoting
4966 -- or any other processing) onto a single line.
5269 -- "(1 elephant)"
5370 basicPrinter :: SExprPrinter Text (SExpr Text)
5471 basicPrinter = flatPrint id
72
73 -- | A 'SExprPrinter' for 'Located' values. Works exactly like 'basicPrinter'
74 -- It ignores the location tags when printing the result.
75 --
76 -- >>> let (Right dec) = decode locatedBasicParser $ pack "(1 elephant)"
77 -- [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 3)) "1")) (SCons (SAtom (At (Span (line 1, column 4) (line 1, column 12)) "elephant")) SNil)]
78 --
79 -- >>> encode locatedBasicPrinter dec
80 -- "(1 elephant)"
81 locatedBasicPrinter :: SExprPrinter (Located Text) (SExpr (Located Text))
82 locatedBasicPrinter = flatPrint unLoc
83 where unLoc (At _loc e) = e
1 {-# LANGUAGE FlexibleInstances #-}
12 {-# LANGUAGE OverloadedStrings #-}
23
34 module Data.SCargot.Language.HaskLike
56 HaskLikeAtom(..)
67 , haskLikeParser
78 , haskLikePrinter
9 , locatedHaskLikeParser
10 , locatedHaskLikePrinter
811 -- * Individual Parsers
912 , parseHaskellString
1013 , parseHaskellFloat
5558
5659 instance IsString HaskLikeAtom where
5760 fromString = HSIdent . fromString
61
62 instance IsString (Located HaskLikeAtom) where
63 fromString = (At dLocation) . HSIdent . fromString
5864
5965 -- | Parse a Haskell string literal as defined by the Haskell 2010
6066 -- language specification.
157163 haskLikeParser :: SExprParser HaskLikeAtom (SExpr HaskLikeAtom)
158164 haskLikeParser = mkParser pHaskLikeAtom
159165
166 -- | A 'haskLikeParser' which produces 'Located' values
167 --
168 -- >>> decode locatedHaskLikeParser $ pack "(0x01 \"\\x65lephant\")"
169 -- Right [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 6)) (HSInt 1))) (SCons (SAtom (At (Span (line 1, column 7) (line 1, column 20)) (HSString "elephant"))) SNil)]
170 --
171 -- >>> decode locatedHaskLikeParser $ pack "(1 elephant)"
172 -- Right [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 3)) (HSInt 1))) (SCons (SAtom (At (Span (line 1, column 4) (line 1, column 12)) (HSIdent "elephant"))) SNil)]
173 locatedHaskLikeParser :: SExprParser (Located HaskLikeAtom) (SExpr (Located HaskLikeAtom))
174 locatedHaskLikeParser = mkParser $ located pHaskLikeAtom
175
160176 -- | This 'SExprPrinter' emits s-expressions that contain Scheme-like
161177 -- tokens as well as string literals, integer literals, and floating-point
162178 -- literals, which will be emitted as the literals produced by Haskell's
167183 -- "(1 \"elephant\")"
168184 haskLikePrinter :: SExprPrinter HaskLikeAtom (SExpr HaskLikeAtom)
169185 haskLikePrinter = flatPrint sHaskLikeAtom
186
187 -- | Ignore location tags when packing values into text
188 sLocatedHasklikeAtom :: Located HaskLikeAtom -> Text
189 sLocatedHasklikeAtom (At _loc e) = sHaskLikeAtom e
190
191 -- | A 'SExprPrinter' for 'Located' values. Works exactly like 'haskLikePrinter'
192 -- It ignores the location tags when printing the result.
193 --
194 -- >>> let (Right dec) = decode locatedHaskLikeParser $ pack "(1 elephant)"
195 -- [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 3)) (HSInt 1))) (SCons (SAtom (At (Span (line 1, column 4) (line 1, column 12)) (HSIdent "elephant"))) SNil)]
196 --
197 -- >>> encode locatedHaskLikePrinter dec
198 -- "(1 elephant)"
199 locatedHaskLikePrinter :: SExprPrinter (Located HaskLikeAtom) (SExpr (Located HaskLikeAtom))
200 locatedHaskLikePrinter = flatPrint sLocatedHasklikeAtom