Advertisement
Guest User

Untitled

a guest
Jun 10th, 2021
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {-# LANGUAGE OverloadedStrings #-}
  2.  
  3. module Example
  4.   ( runExample,
  5.   )
  6. where
  7.  
  8. import Control.Applicative hiding (many, some)
  9. import Data.Text (Text)
  10. import Data.Void
  11. import System.IO as SIO
  12. import Text.Megaparsec hiding (State)
  13. import Text.Megaparsec.Char (space1, string')
  14. import qualified Text.Megaparsec.Char.Lexer as L
  15. import Text.Megaparsec.Debug
  16. import Text.Pretty.Simple (pPrint)
  17.  
  18. -- Types
  19.  
  20. type Parser = Parsec Void Text
  21.  
  22. data SyntaxAst = Keyword Text | Recurse | Optional SyntaxAst | Many [SyntaxAst]
  23.  
  24. --  Megaparsec Base Parsers
  25.  
  26. -- Space consumer - used by other parsers to ignore whitespace
  27. sc :: Parser ()
  28. sc =
  29.  L.space
  30.    space1
  31.    (L.skipLineComment "--")
  32.    (L.skipBlockComment "/*" "*/")
  33.  
  34. -- Runs a parser, then consumes any left over space with sc
  35. lexeme :: Parser a -> Parser a
  36. lexeme = L.lexeme sc
  37.  
  38. -- Parses a string, then consumes any left over space with sc
  39. symbol :: Text -> Parser Text
  40. symbol = L.symbol sc
  41.  
  42. -- Parses something between parentheses
  43. inParens :: Parser a -> Parser a
  44. inParens =
  45.  between
  46.    (symbol "(")
  47.    (symbol ")")
  48.  
  49. -- Transforms the AST into a parser
  50. transformSyntaxExprToParser :: Parser [Text] -> SyntaxAst -> Parser [Text]
  51. transformSyntaxExprToParser self = go
  52.  where
  53.    go (Many exprs) = dbg "Many" (foldr1 (liftA2 (<>)) (fmap (transformSyntaxExprToParser self) exprs))
  54.    go (Keyword text) = dbg "Keyword" (pure <$> lexeme (string' text))
  55.     go (Optional inner) = dbg "Optional" (option [] (try (inParens (go inner))))
  56.     go Recurse = dbg "Recurse" self
  57.  
  58. -- Walks over the parser AST and convert it to a parser
  59. createParser :: [SyntaxAst] -> Parser [Text]
  60. createParser expressions = parser
  61.   where
  62.     parser =
  63.       foldr1
  64.         (liftA2 (<>))
  65.         (fmap (transformSyntaxExprToParser parser) expressions)
  66.  
  67. runExample :: IO ()
  68. runExample = do
  69.   -- To make the example simple, lets cut out the language definition parsing and just define
  70.   -- it literally.
  71.   let languageParser = createParser [Keyword "A", Keyword "B", Keyword "C", Optional (Many [Recurse])]
  72.   let run p = runParser p "" "A B C (A B C (A B C))"
  73.   let result = run languageParser
  74.   case result of
  75.     Left bundle -> SIO.putStrLn (errorBundlePretty bundle)
  76.     Right xs -> pPrint xs
  77.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement