This commit is contained in:
Dmitry Zuikov 2023-02-07 11:55:56 +03:00
parent b1f2c94eb8
commit 1e95e53d3b
3 changed files with 131 additions and 67 deletions

View File

@ -1,4 +1,10 @@
{-# Language ConstraintKinds #-}
module Data.Config.Suckless.Parse.Megaparsec module Data.Config.Suckless.Parse.Megaparsec
( parseSyntax
, parseTop
, MegaParsec
, MegaContext
)
where where
import Data.Config.Suckless.Syntax import Data.Config.Suckless.Syntax
@ -8,13 +14,27 @@ import Control.Applicative()
import Data.Char (showLitChar) import Data.Char (showLitChar)
import Data.Text qualified as Text import Data.Text qualified as Text
import Control.Monad
import Text.Megaparsec import Text.Megaparsec
import Text.Megaparsec.Char (space1,char,letterChar,digitChar) import Text.Megaparsec.Char (hspace1,space1,char,letterChar,digitChar,eol)
import Text.Megaparsec.Char.Lexer qualified as L import Text.Megaparsec.Char.Lexer qualified as L
import Text.Megaparsec.Char.Lexer ( signed ) import Text.Megaparsec.Char.Lexer ( signed )
import Data.String(IsString(..)) import Data.String(IsString(..))
import GHC.Generics
import Data.Data
import Debug.Trace data MegaParsec =
MegaParsec
deriving (Data,Typeable,Generic)
newtype instance Context MegaParsec = MegaContext (Maybe Int)
instance IsContext MegaParsec where
noContext = MegaContext Nothing
type MegaContext = Context MegaParsec
type MegaConstraints c = ( c ~ MegaParsec, IsContext c )
type Parser r = Parsec () [Char] r type Parser r = Parsec () [Char] r
@ -26,24 +46,34 @@ sc = do
where where
lineComment = L.skipLineComment ";" lineComment = L.skipLineComment ";"
scTop :: Parser ()
scTop = do
L.space hspace1 lineComment empty
where
lineComment = L.skipLineComment ";"
dquot :: Parser Char dquot :: Parser Char
dquot = char '"' dquot = char '"'
-- FIXME: position! -- FIXME: position!
stringLit :: Monoid (Context c) => Parser (Syntax c) stringLit :: forall c . MegaConstraints c
stringLit = L.lexeme sc $ => Parser () -> Parser (Syntax c)
Literal mempty . LitStr <$> str
stringLit sp = L.lexeme sp $ do
co <- MegaContext . Just <$> getOffset
Literal co . LitStr <$> str
where where
str = do str = do
s <- dquot >> manyTill L.charLiteral dquot s <- dquot >> manyTill L.charLiteral dquot
pure $ Text.pack (mconcat [ showLitChar c "" | c <- s ]) pure $ Text.pack (mconcat [ showLitChar c "" | c <- s ])
{-
-- FIXME: position! -- FIXME: position!
intLit :: Parser Syntax intLit :: forall c . MegaConstraints c
intLit = L.lexeme sc $ => Parser () -> Parser (Syntax c)
Literal . LitInt <$> choice [hex, oct, bin, dec, dec']
intLit sp = L.lexeme sp $ do
co <- MegaContext . Just <$> getOffset
Literal co . LitInt <$> choice [hex, oct, bin, dec, dec']
where where
hex = L.symbol sc "0x" >> L.hexadecimal hex = L.symbol sc "0x" >> L.hexadecimal
oct = L.symbol sc "0o" >> L.octal oct = L.symbol sc "0o" >> L.octal
@ -58,18 +88,20 @@ symbolChar :: Parser Char
symbolChar = oneOf symbolChars symbolChar = oneOf symbolChars
-- FIXME: position! -- FIXME: position!
symbol :: Parser Syntax symbol :: forall c . MegaConstraints c
symbol = L.lexeme sc $ do => Parser () -> Parser (Syntax c)
co <- Context . Just <$> getOffset symbol sp = L.lexeme sp $ do
co <- MegaContext . Just <$> getOffset
h <- letterChar <|> symbolChar h <- letterChar <|> symbolChar
t <- many (letterChar <|> digitChar <|> symbolChar) t <- many (letterChar <|> digitChar <|> symbolChar)
case Symbol (fromString (h:t)) of case h:t of
SymbolVal "#t" -> pure $ Literal (mkLit True) "#t" -> pure $ Literal co (mkLit True)
SymbolVal "#f" -> pure $ Literal (mkLit False) "#f" -> pure $ Literal co (mkLit False)
SymbolVal other -> pure (Symbol_ co other) other -> pure $ Symbol co (fromString other)
skipChar :: Char -> Parser () skipChar :: Char -> Parser ()
skipChar c = void $ char c skipChar c = void (char c)
oParen :: Parser () oParen :: Parser ()
oParen = skipChar '(' oParen = skipChar '('
@ -97,51 +129,54 @@ someEnclosedBy :: Parser ()
someEnclosedBy o i c = do someEnclosedBy o i c = do
between o c (many (sc >> i)) -- <|> parseError (error (show ("WTF!", ctx))) -- (ParseError (ListParseError ctx)) between o c (many (sc >> i)) -- <|> parseError (error (show ("WTF!", ctx))) -- (ParseError (ListParseError ctx))
list :: Parser Syntax list :: forall c . MegaConstraints c
list = L.lexeme sc $ do => Parser() -> Parser (Syntax c)
co <- Context . Just <$> getOffset
-- traceShowM ("List", co)
List_ co <$> choice [ someEnclosedBy oParen syntax cParen
, someEnclosedBy oBrace syntax cBrace
, someEnclosedBy oBracket syntax cBracket
]
syntax :: Parser Syntax list sp = L.lexeme sp $ do
syntax = choice [ symbol co <- MegaContext . Just <$> getOffset
, stringLit List co <$> choice [ someEnclosedBy oParen (syntax sp) cParen
, intLit , someEnclosedBy oBrace (syntax sp) cBrace
, list , someEnclosedBy oBracket (syntax sp) cBracket
] ]
-- top :: Parser (AST (Core S)) syntax :: forall c . MegaConstraints c
-- top = sc >> many syntaxWithPos >>= toAST => Parser () -> Parser (Syntax c)
-- where syntax sp = choice [ symbol sp
-- -- FIXME: push real position here , stringLit sp
-- syntaxWithPos = do , intLit sp
-- pos <- getOffset , list sp
-- node <- (pos,) <$> syntax ]
-- pure node
-- toAST xs = go xs merely :: Parser a -> Parser a
merely f = do
sc
r <- f
sc
eof
pure r
-- go :: [(Int, Syntax)] -> Parser (AST (Core S)) parseSyntax :: forall c . MegaConstraints c
-- go ( (p, syn) : rest ) = do => String -> Either ParseFail (Syntax c)
-- let c = Context (Just p)
-- mkExpr c . Seq syn <$> go rest
-- go [] = pure $ mkLeaf0 () parseSyntax = parse (merely (syntax sc)) "input"
-- merely :: Parser a -> Parser a top :: forall c . MegaConstraints c => Parser [Syntax c]
-- merely f = do top = sc >> many (topStmt <|> syntax scTop)
-- sc
-- r <- f
-- sc
-- eof
-- pure r
-- parseSyntax :: String -> Either ParseFail Syntax topStmt :: forall c . MegaConstraints c => Parser (Syntax c)
-- parseSyntax = parse (merely syntax) "input" topStmt = do
scTop
co <- MegaContext . Just <$> getOffset
s0 <- symbol scTop
ss <- many (syntax scTop)
void eol <|> eof
pure $ List co (s0:ss)
parseTop :: forall c . MegaConstraints c
=> String -> Either ParseFail [Syntax c]
parseTop = parse top "input"
-- parseTop :: String -> Either ParseFail (AST (Core S))
-- parseTop = parse top "input"
-}

View File

@ -1,33 +1,51 @@
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PatternSynonyms #-}
module Data.Config.Suckless.Syntax module Data.Config.Suckless.Syntax
( Syntax(..) ( Syntax(..)
, Context(..)
, Id(..) , Id(..)
, Literal(..) , Literal(..)
, Context
, HasContext(..) , HasContext(..)
, IsContext(..)
, IsLiteral(..)
, pattern SymbolVal , pattern SymbolVal
, pattern ListVal
, pattern LitVal
) )
where where
import GHC.Generics
import Data.Text (Text)
import Data.Data import Data.Data
import Data.String
import Data.Kind import Data.Kind
import Data.String
import Data.Text (Text)
import GHC.Generics
import Prettyprinter import Prettyprinter
pattern SymbolVal :: Id -> Syntax c pattern SymbolVal :: Id -> Syntax c
pattern SymbolVal v <- Symbol _ v pattern SymbolVal v <- Symbol _ v
data family Context c :: Type pattern LitVal :: forall {c}. Id -> Syntax c
pattern LitVal v <- Symbol _ v
pattern ListVal :: forall {c}. [Syntax c] -> Syntax c
pattern ListVal v <- List _ v
data family Context c :: Type
class IsContext c where
noContext :: Context c
class HasContext c a where class HasContext c a where
setContext :: Context c -> a -> a setContext :: Context c -> a -> a
getContext :: a -> Context c getContext :: a -> Context c
class IsLiteral a where
mkLit :: a -> Literal
newtype Id = newtype Id =
Id Text Id Text
deriving newtype (IsString,Pretty) deriving newtype (IsString,Pretty)
@ -39,6 +57,15 @@ data Literal =
| LitBool Bool | LitBool Bool
deriving stock (Eq,Ord,Data,Generic,Show) deriving stock (Eq,Ord,Data,Generic,Show)
instance IsLiteral Text where
mkLit = LitStr
instance IsLiteral Bool where
mkLit = LitBool
instance IsLiteral Integer where
mkLit = LitInt
data Syntax c data Syntax c
= List (Context c) [Syntax c] = List (Context c) [Syntax c]
| Symbol (Context c) Id | Symbol (Context c) Id
@ -71,3 +98,9 @@ instance Pretty Literal where
| otherwise -> "#f" | otherwise -> "#f"
deriving instance ( Data c
, Data (Context c)
, Typeable c
) => Data (Syntax c)

View File

@ -1,4 +0,0 @@
module MyLib (someFunc) where
someFunc :: IO ()
someFunc = putStrLn "someFunc"