gdritter repos s-cargot / a785d89
Fix README so it compiles + More Complete Example aaron levin 8 years ago
1 changed file(s) with 28 addition(s) and 12 deletion(s). Collapse all Expand all
454454 literals:
455455
456456 ~~~~.haskell
457 {-# LANGUAGE OverloadedStrings #-}
458
459 module SCargotExample where
460
461 import Control.Applicative ((<|>))
462 import Data.Char (isDigit)
463 import Data.SCargot
464 import Data.SCargot.Repr.Basic
465 import Data.Text (Text, pack)
466 import Numeric (readHex)
467 import Text.Parsec (anyChar, char, digit, many1, manyTill, newline, satisfy, string)
468 import Text.Parsec.Text (Parser)
469
457470 -- Our operators are going to represent addition, subtraction, or
458471 -- multiplication
459472 data Op = Add | Sub | Mul deriving (Eq, Show)
468481
469482 -- Conversions to and from our Expr type
470483 toExpr :: SExpr Atom -> Either String Expr
471 toExpr (A (AOp op) ::: l ::: r ::: Nil) = EOp op <$> l <*> r
484 toExpr (A (AOp op) ::: l ::: r ::: Nil) = EOp op <$> toExpr l <*> toExpr r
472485 toExpr (A (ANum n)) = pure (ENum n)
473486 toExpr sexpr = Left ("Unable to parse expression: " ++ show sexpr)
474487
475488 fromExpr :: Expr -> SExpr Atom
476489 fromExpr (EOp op l r) = A (AOp op) ::: fromExpr l ::: fromExpr r ::: Nil
477 fromExpr (ENum n) = ANum n
490 fromExpr (ENum n) = A (ANum n) ::: Nil
478491
479492 -- Parser and serializer for our Atom type
480493 pAtom :: Parser Atom
481 pAtom = ((ANum . read . T.unpack) <$> many1 isDigit)
482 <|> (char "+" *> pure (AOp Add))
483 <|> (char "-" *> pure (AOp Sub))
484 <|> (char "*" *> pure (AOp Mul))
494 pAtom = ((ANum . read) <$> many1 digit)
495 <|> (char '+' *> pure (AOp Add))
496 <|> (char '-' *> pure (AOp Sub))
497 <|> (char '*' *> pure (AOp Mul))
485498
486499 sAtom :: Atom -> Text
487500 sAtom (AOp Add) = "+"
488501 sAtom (AOp Sub) = "-"
489502 sAtom (AOp Mul) = "*"
490 sAtom (ANum n) = T.pack (show n)
503 sAtom (ANum n) = pack (show n)
491504
492505 -- Our comment syntax is going to be Haskell-like:
493506 hsComment :: Parser ()
494 hsComment = string "--" >> manyTill newline >> return ()
507 hsComment = string "--" >> manyTill anyChar newline >> return ()
495508
496509 -- Our custom reader macro: grab the parse stream and read a
497510 -- hexadecimal number from it:
498511 hexReader :: Reader Atom
499 hexReader _ = (Num . readHex . T.unpack) <$> takeWhile1 isHexDigit
500 where isHexDigit c = isDigit c || c `elem` "AaBbCcDdEeFf"
501 rd = readHex . head . fst
512 hexReader _ = (A . ANum . rd) <$> many1 (satisfy isHexDigit)
513 where isHexDigit c = isDigit c || c `elem` hexChars
514 rd = fst . head . readHex
515 hexChars :: String
516 hexChars = "AaBbCcDdEeFf"
502517
503518 -- Our final s-expression parser and printer:
504519 myLangParser :: SExprParser Atom Expr
508523 $ setCarrier toExpr -- convert final repr to Expr
509524 $ mkParser pAtom -- create spec with Atom type
510525
511 mkLangPrinter :: SexprPrinter Atom Expr
526 mkLangPrinter :: SExprPrinter Atom Expr
512527 mkLangPrinter
513528 = setFromCarrier fromExpr
514529 $ setIndentStrategy (const Align)
515530 $ basicPrint sAtom
531
516532 ~~~~
517533
518534 Keep in mind that you often won't need to write all this by hand,