Last active
July 11, 2024 09:35
-
-
Save sondr3/3fafb67952562368cbd61666284b916b to your computer and use it in GitHub Desktop.
Megaparsec Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
:set -XOverloadedStrings | |
import Data.Text qualified as T | |
import Data.Text.IO qualified as TIO |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# 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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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