parsley-2.0.0.0: benchmarks/NandlangBench/Parsley/Parser.hs
{-# OPTIONS_GHC -fplugin=Parsley.OverloadedQuotesPlugin #-}
{-# LANGUAGE TemplateHaskellQuotes #-}
{-# LANGUAGE DeriveLift #-}
{-# LANGUAGE StandaloneDeriving #-}
module NandlangBench.Parsley.Parser where
import Prelude hiding (fmap, pure, (<*), (*>), (<*>), (<$>), (<$), pred)
import Parsley
import Parsley.Combinator (eof)
import Parsley.Char (token, oneOf)
import Parsley.Fold (skipMany, skipSome)
--import Parsley.Garnish
import NandlangBench.Parsley.Functions
import Data.Char (isSpace)
nandlang :: Parser ()
nandlang = whitespace *> skipMany funcdef <* eof
where
index :: Parser ()
index = brackets nat
identifier :: Parser ()
identifier = try (identStart *> skipMany identLetter) *> whitespace
variable :: Parser ()
variable = identifier *> optional index
literal :: Parser ()
literal = bit <|> charLit
keyword :: String -> Parser ()
keyword s = try (string s *> notIdentLetter) *> whitespace
identStart = satisfy [|nandIdentStart|]
identLetter = satisfy [|nandIdentLetter|]
notIdentLetter = notFollowedBy identLetter
bit :: Parser ()
bit = (char '0' <|> char '1') *> whitespace
nat :: Parser ()
nat = decimal
charLit :: Parser ()
charLit = between (char '\'') (symbol '\'') charChar
charChar :: Parser ()
charChar = void (satisfy [|nandStringLetter|]) <|> esc
esc :: Parser ()
esc = char '\\' *> void (oneOf "0tnvfr")
expr :: Parser ()
expr = nandexpr *> skipMany (symbol '!' *> nandexpr)
nandexpr :: Parser ()
nandexpr = literal <|> funccallOrVar
funccallOrVar :: Parser ()
funccallOrVar = identifier *> optional (parens exprlist <|> index)
exprlist = commaSep expr
exprlist1 = commaSep1 expr
varlist = commaSep variable
varlist1 = commaSep1 variable
funcparam = varlist *> optional (symbol ':' *> varlist)
varstmt = optional (keyword "var") *> varlist1 *> symbol '=' *> exprlist1 <* semi
ifstmt = keyword "if" *> expr *> block *> optional (keyword "else" *> block)
whilestmt = keyword "while" *> expr *> block
statement = ifstmt <|> whilestmt <|> try varstmt <|> expr <* semi
block = braces (skipMany statement)
funcdef = keyword "function" *> identifier *> parens funcparam *> block
decimal :: Parser ()
decimal = number (oneOf ['0'..'9'])
hexadecimal = oneOf "xX" *> number (oneOf (['a'..'f'] ++ ['A'..'F'] ++ ['0'..'9']))
octal = oneOf "oO" *> number (oneOf ['0'..'7'])
number :: Parser a -> Parser ()
number digit = skipSome digit
symbol :: Char -> Parser Char
symbol c = char c <* whitespace
parens :: Parser a -> Parser a
parens = between (symbol '(') (symbol ')')
brackets :: Parser a -> Parser a
brackets = between (symbol '[') (symbol ']')
braces :: Parser a -> Parser a
braces = between (symbol '{') (symbol '}')
semi :: Parser Char
semi = symbol ';'
comma :: Parser Char
comma = symbol ','
commaSep :: Parser a -> Parser ()
commaSep p = optional (commaSep1 p)
commaSep1 :: Parser a -> Parser ()
commaSep1 p = p *> skipMany (comma *> p)
space :: Parser ()
space = void (satisfy [|isSpace|])
whitespace :: Parser ()
whitespace = skipMany (spaces <|> oneLineComment)
spaces :: Parser ()
spaces = skipSome space
oneLineComment :: Parser ()
oneLineComment = void (token "//" *> skipMany (satisfy [|(/= '\n')|]))