packages feed

snail 0.1.2.1 → 0.1.2.2

raw patch · 6 files changed

+149/−17 lines, 6 filesdep ~QuickCheckdep ~containersdep ~hspecnew-component:exe:snailPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: QuickCheck, containers, hspec, hspec-discover, megaparsec, mtl, text, text-display

API changes (from Hackage documentation)

- Snail.Ast: instance GHC.Show.Show Snail.Ast.Bracket
- Snail.Ast: instance GHC.Show.Show Snail.Ast.SnailAst
+ Snail.Ast: instance GHC.Internal.Show.Show Snail.Ast.Bracket
+ Snail.Ast: instance GHC.Internal.Show.Show Snail.Ast.SnailAst

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+### Version 0.1.2.2++* Update dependencies upper bounds+ ### Version 0.1.2.1  * Didn't export unwrap utility
README.md view
@@ -101,7 +101,37 @@ 1. The `arith` language from [Types and Programming Languages][tapl]: https://github.com/chiroptical/snail-arith/blob/main/src/Lib.hs 2. Languages from [essentials-of-compilation][essentials-of-compilation]: https://github.com/chiroptical/essentials-of-compilation (each chapter is a module) +## Differences from S-Cargot++I was recently reminded of [s-cargot][s-cargot]. From their GitHub,++> S-Cargot is a library for parsing and emitting S-expressions, designed to be+> flexible, customizable, and extensible.++This is quite different from Snail. Snail is not flexible, customizable, or+extensible. I have chosen a syntax and either you use it or you don't.+With S-Cargot, you can build a custom S-expression parser. Snail provides one.++I don't think you can re-write Snail using S-Cargot? It doesn't appear to+support `'(x)` or `(let [x 10] x)`. Please correct me if I missed something.++I tried to mimic their example+(https://github.com/aisamanra/s-cargot/blob/master/example/example.hs) in+./example/Main.hs.++## Resources for implementing interpreters and compilers++These are resources I am personally interested in exploring, there are **many** others++- [Types and Programming Languages][tapl]+- [Essentials of Compilation][essentials-of-compilation]+- [Compiler Design][cs4410]+- [Compiler Construction][cse131]+ [tapl]: https://www.cis.upenn.edu/~bcpierce/tapl [haskell-parse-issue]: https://twitter.com/chiroptical/status/1471568781906518018 [pl-wikipedia]: https://en.wikipedia.org/wiki/Programming_language [essentials-of-compilation]: https://mitpress.mit.edu/9780262047760/essentials-of-compilation+[s-cargot]: https://github.com/aisamanra/s-cargot+[cs4410]: https://course.ccs.neu.edu/cs4410sp21/+[cse131]: https://ucsd-cse131-f19.github.io/
+ example/Main.hs view
@@ -0,0 +1,59 @@+module Main where++import Snail+import Control.Monad.Except+import Data.Text (Text)+import Data.Text qualified as Text+import Text.Read (readMaybe)++data Operation = Addition | Multiplication +  deriving (Eq, Show)++data Ast+  = AstInt Integer+  | AstOperation Operation Ast Ast+  deriving (Eq, Show)++data LangError +  = UnknownLexeme Text+  | UnknownOperation Text+  | TextLiteralUnsupported+  | EmptyExpression+  deriving (Eq, Show)++parseLeaf :: (MonadError LangError m) => Text -> m Ast+parseLeaf = \case+  txt ->+    case readMaybe @Integer $ Text.unpack txt of+      Nothing -> throwError $ UnknownLexeme txt+      Just int -> pure $ AstInt int++parseOp :: (MonadError LangError m) => Text -> m Operation+parseOp = \case+  "+" -> pure Addition+  "*" -> pure Multiplication+  txt -> throwError $ UnknownOperation txt++fromSnail :: (MonadError LangError m) => SnailAst -> m Ast+fromSnail = \case+  -- no text literals are supported in this language+  TextLiteral _ -> throwError TextLiteralUnsupported+  -- `X` where `X` is a leaf in 'Ast'+  Lexeme (_, leaf) -> parseLeaf leaf+  SExpression _ _ [Lexeme (_, txt), argumentOne, argumentTwo] -> do+    op <- parseOp txt+    one <- fromSnail argumentOne+    two <- fromSnail argumentTwo+    pure $ AstOperation op one two+  -- empty expressions are invalid+  SExpression _ _ [] -> throwError EmptyExpression+  -- expression of expressions, e.g. `((X))` -> `(X)`+  SExpression leading fence exprs ->+    fromSnail . unwrap . SExpression leading fence $ unwrap <$> exprs++main :: IO ()+main = do+  case parseSnail "(+ 1 2)" of+    Left err -> print $ "Unable to parse snail: " <> show err+    Right [snail] -> runExceptT (fromSnail snail) >>= print+    Right _ -> putStrLn "Excepted single expression"
snail.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.2.+-- This file has been generated from package.yaml by hpack version 0.38.3. -- -- see: https://github.com/sol/hpack  name:           snail-version:        0.1.2.1+version:        0.1.2.2 synopsis:       A programming language with no semantics description:    An s-expression parser and abstract syntax tree for a programming language with no semantics. If you wanted to write an interpreter or compiler you convert the AST into your own. category:       Parsing@@ -51,19 +51,44 @@   hs-source-dirs:       src   default-extensions:+      FlexibleContexts       ImportQualifiedPost       LambdaCase       OverloadedStrings+      TypeApplications   build-depends:-      QuickCheck >=2.14.3 && <2.15+      QuickCheck >=2.14.3 && <2.20     , base >=4.15 && <5-    , containers >=0.6.7 && <0.7-    , megaparsec >=9.3.1 && <9.4-    , mtl >=2.2.2 && <2.3-    , text >=2.0.2 && <2.1-    , text-display >=0.0.5 && <0.1+    , containers >=0.6.7 && <0.8+    , megaparsec >=9.5.0 && <9.9+    , mtl >=2.3.1 && <2.4+    , text >=2.0.2 && <2.2+    , text-display >=0.0.5 && <0.1 || >=1.0 && <1.1   default-language: Haskell2010 +executable snail+  main-is: Main.hs+  other-modules:+      Paths_snail+  hs-source-dirs:+      example+  default-extensions:+      FlexibleContexts+      ImportQualifiedPost+      LambdaCase+      OverloadedStrings+      TypeApplications+  build-depends:+      QuickCheck >=2.14.3 && <2.20+    , base >=4.15 && <5+    , containers >=0.6.7 && <0.8+    , megaparsec >=9.5.0 && <9.9+    , mtl >=2.3.1 && <2.4+    , snail+    , text >=2.0.2 && <2.2+    , text-display >=0.0.5 && <0.1 || >=1.0 && <1.1+  default-language: Haskell2010+ test-suite snail-test   type: exitcode-stdio-1.0   main-is: Spec.hs@@ -76,21 +101,23 @@   hs-source-dirs:       test   default-extensions:+      FlexibleContexts       ImportQualifiedPost       LambdaCase       OverloadedStrings+      TypeApplications   ghc-options: -threaded -rtsopts -with-rtsopts=-N   build-depends:       HUnit >=1.6.2 && <1.7-    , QuickCheck >=2.14.3 && <2.15+    , QuickCheck >=2.14.3 && <2.20     , base >=4.15 && <5-    , containers >=0.6.7 && <0.7-    , hspec >=2.10.10 && <2.11-    , hspec-discover >=2.10.10 && <2.11-    , megaparsec >=9.3.1 && <9.4-    , mtl >=2.2.2 && <2.3+    , containers >=0.6.7 && <0.8+    , hspec >=2.11.8 && <2.12+    , hspec-discover >=2.11.8 && <2.12+    , megaparsec >=9.5.0 && <9.9+    , mtl >=2.3.1 && <2.4     , raw-strings-qq ==1.1.*     , snail-    , text >=2.0.2 && <2.1-    , text-display >=0.0.5 && <0.1+    , text >=2.0.2 && <2.2+    , text-display >=0.0.5 && <0.1 || >=1.0 && <1.1   default-language: Haskell2010
src/Snail/Lexer.hs view
@@ -114,7 +114,7 @@  recursively separated by 'spaces' in 'sExpression'. -} leaves :: Parser SnailAst-leaves = lexeme <|> textLiteral <|> sExpression+leaves = try sExpression <|> lexeme <|> textLiteral  -- | Parse an 'SExpression' sExpression :: Parser SnailAst
test/Snail/LexerSpec.hs view
@@ -160,3 +160,15 @@          it "fails to parse nested mismatched brackets" $ do             parseMaybe snailAst "([)]" `shouldSatisfy` isNothing++        it "associates inner '#' with the s-expression" $ do+            let Just [result] = parseMaybe snailAst "(different-char/2 #(inside))"+            foldLexemes result `shouldBe` ["different-char/2", "inside"]++        it "fails with two leading characters" $ do+            parseMaybe snailAst "@,(foo)" `shouldSatisfy` isNothing++        -- NOTE: this may or may not be the desired behavior+        it "parses two leading characters as valid lexeme" $ do+            let Just [result] = parseMaybe snailAst "(@,(foo ...))"+            foldLexemes result `shouldBe` ["@,", "foo", "..."]