Skip to content

Instantly share code, notes, and snippets.

@sondr3
Last active July 11, 2024 09:35
Show Gist options
  • Save sondr3/3fafb67952562368cbd61666284b916b to your computer and use it in GitHub Desktop.
Save sondr3/3fafb67952562368cbd61666284b916b to your computer and use it in GitHub Desktop.
Megaparsec Example
:set -XOverloadedStrings
import Data.Text qualified as T
import Data.Text.IO qualified as TIO
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Monad (void)
import Data.Text (Text)
import Data.Void (Void)
import Text.Megaparsec
import Text.Megaparsec.Char
import Text.Megaparsec.Char.Lexer qualified as L
type Parser = Parsec Void Text
sc :: Parser ()
sc = L.space space1 (L.skipLineComment "#") (L.skipBlockComment "/*" "*/")
lexeme :: Parser a -> Parser a
lexeme = L.lexeme sc
symbol :: Text -> Parser Text
symbol = L.symbol sc
keyword :: Text -> Parser Text
keyword word = lexeme (string word)
data MSGDefinition = MSGDefinition
{ subject :: Text,
sid :: Text,
replyTo :: Maybe Text,
bytes :: Int,
payload :: Maybe Text
}
deriving (Show)
data NATS
= MSG MSGDefinition
| HMSG
deriving (Show)
item :: Parser Text
item = takeWhile1P (Just "any char") (/= ' ') <* space
pPayload :: Parser Text
pPayload = takeWhile1P Nothing (/= '\r') <* space
integer :: Parser Int
integer = lexeme L.decimal
parseWithReply :: Parser (Maybe Text, Int)
parseWithReply = (,) <$> optional item <*> integer
parseWithoutReply :: Parser (Maybe Text, Int)
parseWithoutReply = (Nothing,) <$> integer
parseMessage :: Parser MSGDefinition
parseMessage = do
void (keyword "MSG") <?> "MSG"
subject <- item <?> "subject"
sid <- item <?> "sid"
(replyTo, len) <- try parseWithReply <|> parseWithoutReply
payload <- optional pPayload <?> "payload"
pure $ MSGDefinition subject sid replyTo len payload
parseProtocol :: Parser NATS
parseProtocol = choice [MSG <$> parseMessage] <* optional eof
main :: IO ()
main = do
parseTest parseProtocol "MSG target.subject 1 reply.subject 500\r\n"
parseTest parseProtocol "MSG target.subject 1 500\r\n"
parseTest parseProtocol "MSG FOO.BAR 9 11\r\nHello World\r\n"
parseTest parseProtocol "MSG FOO.BAR 9 GREETING.34 11\r\nHello World\r\n"
cabal-version: 3.4
name: parse-test
version: 0.1.0.0
license: NONE
author: Sondre Aasemoen
maintainer: sondre@eons.io
build-type: Simple
extra-doc-files: CHANGELOG.md
common warnings
ghc-options: -Wall
executable parse-test
import: warnings
main-is: Main.hs
build-depends: base ^>=4.19.1.0, megaparsec, text
hs-source-dirs: app
default-language: GHC2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment