{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE NoMonomorphismRestriction #-}

-- | Lex GLua into MTokens
module GLua.Lexer where

import GLua.AG.Token (MToken (..), Region (..), Token (..))

import Data.Char (ord)
import Text.ParserCombinators.UU (
  ExtAlternative (opt, (<<|>)),
  P,
  micro,
  pEnd,
  pErrors,
  pMany,
  pPos,
  pReturn,
  pSome,
  parse,
  (<$$>),
  (<**>),
 )
import Text.ParserCombinators.UU.BasicInstances (
  Error,
  Insertion (Insertion),
  LineColPos (..),
  Str,
  createStr,
  pMunch,
  pSatisfy,
  pSym,
  pToken,
 )
import Text.ParserCombinators.UU.Utils (pDigit)

-- | String parser that maintains positions.
type LParser a = P (Str Char String LineColPos) a

-- | Whitespace parser that requires at least one whitespace character
parseWhitespace :: LParser String
parseWhitespace :: LParser String
parseWhitespace = forall (f :: * -> *) a. IsParser f => f a -> f [a]
pSome forall a b. (a -> b) -> a -> b
$ forall loc state a.
(Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
(a -> Bool) -> Insertion a -> P (Str a state loc) a
pSatisfy (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
" \r\n\t") (forall a. String -> a -> Int -> Insertion a
Insertion String
"Whitespace" Char
' ' Int
5)

-- | Whitespace parser that requires 0 or more whitespace characters
parseOptionalWhitespace :: LParser String
parseOptionalWhitespace :: LParser String
parseOptionalWhitespace = forall (f :: * -> *) a. IsParser f => f a -> f [a]
pMany forall a b. (a -> b) -> a -> b
$ forall loc state a.
(Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
(a -> Bool) -> Insertion a -> P (Str a state loc) a
pSatisfy (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
" \r\n\t") (forall a. String -> a -> Int -> Insertion a
Insertion String
"Whitespace" Char
' ' Int
5)

-- | Blanco parser. Parses anything. Used in parsing comments.
parseAnyChar :: LParser Char
parseAnyChar :: LParser Char
parseAnyChar = forall loc state a.
(Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
(a -> Bool) -> Insertion a -> P (Str a state loc) a
pSatisfy (forall a b. a -> b -> a
const Bool
True) (forall a. String -> a -> Int -> Insertion a
Insertion String
"Any character" Char
'y' Int
5)

-- See luajit's src/lj_char.c and src/lj_char.h
pIdentifierCharacter :: LParser Char
pIdentifierCharacter :: LParser Char
pIdentifierCharacter = forall loc state a.
(Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
(a -> Bool) -> Insertion a -> P (Str a state loc) a
pSatisfy Char -> Bool
validChar (forall a. String -> a -> Int -> Insertion a
Insertion String
"Identifying character (letter, number, emoji)" Char
'a' Int
5)
  where
    validChar :: Char -> Bool
    validChar :: Char -> Bool
validChar Char
c =
      Char -> Char -> Char -> Bool
between Char
c Char
'0' Char
'9'
        Bool -> Bool -> Bool
|| Char -> Char -> Char -> Bool
between Char
c Char
'A' Char
'Z'
        Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'_'
        Bool -> Bool -> Bool
|| Char -> Char -> Char -> Bool
between Char
c Char
'a' Char
'z'
        Bool -> Bool -> Bool
|| Char -> Int
ord Char
c forall a. Ord a => a -> a -> Bool
>= Int
128

pNonDigitIdentifierCharacter :: LParser Char
pNonDigitIdentifierCharacter :: LParser Char
pNonDigitIdentifierCharacter = forall loc state a.
(Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
(a -> Bool) -> Insertion a -> P (Str a state loc) a
pSatisfy Char -> Bool
validChar (forall a. String -> a -> Int -> Insertion a
Insertion String
"Identifying character (letter, emoji)" Char
'a' Int
5)
  where
    validChar :: Char -> Bool
    validChar :: Char -> Bool
validChar Char
c =
      Char -> Char -> Char -> Bool
between Char
c Char
'A' Char
'Z'
        Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'_'
        Bool -> Bool -> Bool
|| Char -> Char -> Char -> Bool
between Char
c Char
'a' Char
'z'
        Bool -> Bool -> Bool
|| Char -> Int
ord Char
c forall a. Ord a => a -> a -> Bool
>= Int
128

between :: Char -> Char -> Char -> Bool
between :: Char -> Char -> Char -> Bool
between Char
c Char
left Char
right = Char
c forall a. Ord a => a -> a -> Bool
>= Char
left Bool -> Bool -> Bool
&& Char
c forall a. Ord a => a -> a -> Bool
<= Char
right

-- | Parses a C-style block comment.
parseCBlockComment :: LParser String
parseCBlockComment :: LParser String
parseCBlockComment =
  forall a b. a -> b -> a
const String
""
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"*/"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> (:)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser Char
parseAnyChar
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser String
parseCBlockComment

-- | Try to parse a block comment.
-- Might actually return a single line Dash comment, because for example
-- the following line is a line comment, rather than a block comment
-- [===== <- missing the last '[' bracket.
parseBlockComment :: LParser Token
parseBlockComment :: LParser Token
parseBlockComment = forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"[" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> LParser Token
nested Int
0
  where
    -- The amount of =-signs in the string delimiter is n
    nested :: Int -> LParser Token
    nested :: Int -> LParser Token
nested Int
n =
      forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"="
        forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> LParser Token
nested (Int
n forall a. Num a => a -> a -> a
+ Int
1)
          forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Int -> String -> Token
DashBlockComment Int
n
        forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"["
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> LParser String
restString Int
n
          forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Int -> String -> Token
lineComment Int
n
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser String
pUntilEnd

    -- Turns out we were describing a line comment all along, cheeky bastard!
    -- (the last [ of the block comment start token is missing)
    lineComment :: Int -> String -> Token
    lineComment :: Int -> String -> Token
lineComment Int
n String
str = String -> Token
DashComment forall a b. (a -> b) -> a -> b
$ Char
'[' forall a. a -> [a] -> [a]
: forall a. Int -> a -> [a]
replicate Int
n Char
'=' forall a. [a] -> [a] -> [a]
++ String
str

    -- Right-recursive grammar. This part searches for the rest of the string until it finds the ]=^n] token
    restString :: Int -> LParser String
    restString :: Int -> LParser String
restString Int
n =
      forall a b. a -> b -> a
const String
""
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken (String
"]" forall a. [a] -> [a] -> [a]
++ forall a. Int -> a -> [a]
replicate Int
n Char
'=' forall a. [a] -> [a] -> [a]
++ String
"]")
          forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> (:)
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser Char
parseAnyChar
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> LParser String
restString Int
n

-- | Parse the string until the end. Used in parseLineComment among others.
pUntilEnd :: LParser String
pUntilEnd :: LParser String
pUntilEnd = forall loc state a.
(Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
(a -> Bool) -> P (Str a state loc) [a]
pMunch (\Char
c -> Char
c forall a. Eq a => a -> a -> Bool
/= Char
'\n' Bool -> Bool -> Bool
&& Char
c forall a. Eq a => a -> a -> Bool
/= Char
'\r')

-- | A comment that spans until the end of the line.
parseLineComment :: String -> LParser String
parseLineComment :: String -> LParser String
parseLineComment String
prefix = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. a -> b -> a
const forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
prefix forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser String
pUntilEnd

-- | Parses a multiline string except for its first character (e.g. =[ string ]=])
-- This is because the first [ could also just be parsed as a square bracket.
nestedString :: LParser String
nestedString :: LParser String
nestedString = Int -> LParser String
nested Int
0
  where
    -- The amount of =-signs in the string delimiter is n
    nested :: Int -> LParser String
    nested :: Int -> LParser String
nested Int
n =
      (\String
str -> String
"=" forall a. [a] -> [a] -> [a]
++ String
str)
        forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"="
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> LParser String
nested (Int
n forall a. Num a => a -> a -> a
+ Int
1)
          forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> (Char
'[' forall a. a -> [a] -> [a]
:)
        forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"["
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> LParser String
restString Int
n

    -- Right-recursive grammar. This part searches for the rest of the string until it finds the ]=^n] token
    restString :: Int -> LParser String
    restString :: Int -> LParser String
restString Int
n =
      forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken (String
"]" forall a. [a] -> [a] -> [a]
++ forall a. Int -> a -> [a]
replicate Int
n Char
'=' forall a. [a] -> [a] -> [a]
++ String
"]")
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> (:)
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser Char
parseAnyChar
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> LParser String
restString Int
n

-- | Parse any kind of comment.
parseComment :: LParser Token
parseComment :: LParser Token
parseComment =
  forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"--"
    forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> (forall a b. a -> b -> a
const forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (LParser Token
parseBlockComment forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> String -> Token
DashComment forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser String
pUntilEnd)) -- Dash block comment and dash comment both start with "--"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"/"
    forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> ( forall a b. a -> b -> a
const
            forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ( String -> Token
SlashBlockComment
                    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"*"
                    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser String
parseCBlockComment
                      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> String -> Token
SlashComment
                    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> LParser String
parseLineComment String
"/"
                      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall (p :: * -> *) a. Applicative p => a -> p a
pReturn Token
Divide -- The /-sign is here because it also starts with '/'
                )
         )

-- | Parse single line strings e.g. "sdf", 'werf'.
parseLineString :: Char -> LParser String
parseLineString :: Char -> LParser String
parseLineString Char
c = forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
c forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> LParser String
innerString
  where
    innerString :: LParser String
    innerString :: LParser String
innerString =
      forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'\\'
        forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> ((\String
c' String
str Char
esc -> Char
esc forall a. a -> [a] -> [a]
: String
c' forall a. [a] -> [a] -> [a]
++ String
str) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser String
escapeSequence forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser String
innerString) -- Escaped character in string always starts with backslash
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a b. a -> b -> a
const String
""
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
c
          forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> (:)
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser Char
pNoNewline
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser String
innerString -- the end of the string
        -- the next character in the string
    escapeSequence :: LParser String
    escapeSequence :: LParser String
escapeSequence = (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'z' forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser String
parseOptionalWhitespace forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> (forall a. a -> [a] -> [a]
: []) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser Char
parseAnyChar

    pNoNewline :: LParser Char
    pNoNewline :: LParser Char
pNoNewline = forall loc state a.
(Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
(a -> Bool) -> Insertion a -> P (Str a state loc) a
pSatisfy (forall a. Eq a => a -> a -> Bool
/= Char
'\n') (forall a. String -> a -> Int -> Insertion a
Insertion String
"Anything but a newline" Char
c Int
5)

-- | Single and multiline strings.
parseString :: LParser Token
parseString :: LParser Token
parseString =
  String -> Token
DQString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> LParser String
parseLineString Char
'"'
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> String -> Token
SQString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> LParser String
parseLineString Char
'\''
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|>
      -- Parse either a multiline string or just a bracket.
      -- Placed here because they have the first token '[' in common
      forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'['
      forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> ( (\Char
_ -> String -> Token
MLString forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:) Char
'[')
              forall (p :: * -> *) a b c.
IsParser p =>
(a -> b -> c) -> p b -> p (a -> c)
<$$> LParser String
nestedString
              forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a b. a -> b -> a
const
              forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (p :: * -> *) a. Applicative p => a -> p a
pReturn Token
LSquare
           )

-- | Parse any kind of number.
parseNumber :: LParser Token
parseNumber :: LParser Token
parseNumber = String -> Token
TNumber forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall a. [a] -> [a] -> [a]
(++) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (LParser String
pZeroPrefixedNumber forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> LParser String
pNumber) forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (LParser String
pLLULL forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall (p :: * -> *) a. ExtAlternative p => p a -> a -> p a
opt LParser String
parseNumberSuffix String
""))
  where
    -- Numbers starting with 0 can be regular numbers, hexadecimals or binary
    pZeroPrefixedNumber :: LParser String
    pZeroPrefixedNumber :: LParser String
pZeroPrefixedNumber =
      forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'0'
        forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> ( (\String
hex Char
_0 -> Char
_0 forall a. a -> [a] -> [a]
: String
hex)
                forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser String
pHexadecimal
                  forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> (\String
bin Char
_0 -> Char
_0 forall a. a -> [a] -> [a]
: String
bin)
                forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser String
pBinary
                  forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> (\String
digits Char
_0 -> Char
_0 forall a. a -> [a] -> [a]
: String
digits)
                forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (LParser String
pDecimal forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> LParser String
pNumber)
                  forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. a -> [a] -> [a]
: [])
             )

    pNumber :: LParser String
    pNumber :: LParser String
pNumber = forall a. [a] -> [a] -> [a]
(++) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a. IsParser f => f a -> f [a]
pSome Parser Char
pDigit forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (p :: * -> *) a. ExtAlternative p => p a -> a -> p a
opt LParser String
pDecimal String
""

    pDecimal :: LParser String
    pDecimal :: LParser String
pDecimal = (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'.' forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. IsParser f => f a -> f [a]
pMany Parser Char
pDigit

    pHexDecimal :: LParser String
    pHexDecimal :: LParser String
pHexDecimal = (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'.' forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. IsParser f => f a -> f [a]
pMany LParser Char
pHex

    pHexadecimal :: LParser String
    pHexadecimal :: LParser String
pHexadecimal = (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'x' forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'X') forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (forall a. [a] -> [a] -> [a]
(++) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a. IsParser f => f a -> f [a]
pSome LParser Char
pHex forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (p :: * -> *) a. ExtAlternative p => p a -> a -> p a
opt LParser String
pHexDecimal String
"")

    pBinary :: LParser String
    pBinary :: LParser String
pBinary = (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'b' forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'B') forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (forall a. [a] -> [a] -> [a]
(++) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a. IsParser f => f a -> f [a]
pSome LParser Char
pBin forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (p :: * -> *) a. ExtAlternative p => p a -> a -> p a
opt LParser String
pDecimal String
"")

    pHex :: LParser Char
    pHex :: LParser Char
pHex =
      Parser Char
pDigit
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'a'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'b'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'c'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'd'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'e'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'f'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'A'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'B'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'C'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'D'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'E'
        forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'F'

    pBin :: LParser Char
    pBin :: LParser Char
pBin = forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'0' forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'1'

    -- LL/ULL suffix of a number, making it signed/unsigned int64 respectively
    -- http://luajit.org/ext_ffi_api.html#literals
    pLLULL :: LParser String
    pLLULL :: LParser String
pLLULL = LParser String
pULL forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> LParser String
pLL

    pLL :: LParser String
    pLL :: LParser String
pLL = String
"LL" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ (forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'L' forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'l') forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* (forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'L' forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'l')

    pULL :: LParser String
    pULL :: LParser String
pULL = String
"ULL" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ (forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'U' forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'u') forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* LParser String
pLL

-- Parse the suffix of a number
parseNumberSuffix :: LParser String
parseNumberSuffix :: LParser String
parseNumberSuffix = forall {loc} {state}.
(IsLocationUpdatedBy loc Char, ListLike state Char) =>
P (Str Char state loc) String
imaginary forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall {loc} {state}.
(IsLocationUpdatedBy loc Char, ListLike state Char) =>
P (Str Char state loc) String
extension
  where
    imaginary :: P (Str Char state loc) String
imaginary = (forall a. a -> [a] -> [a]
: []) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'i' forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'I')

    extension :: P (Str Char state loc) String
extension =
      (\Char
e String
s String
d -> Char
e forall a. a -> [a] -> [a]
: String
s forall a. [a] -> [a] -> [a]
++ String
d)
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'e' forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'E' forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'p' forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a loc state.
(Eq a, Show a, IsLocationUpdatedBy loc a, ListLike state a) =>
a -> P (Str a state loc) a
pSym Char
'P')
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (p :: * -> *) a. ExtAlternative p => p a -> a -> p a
opt (forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"+" forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"-") String
""
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. IsParser f => f a -> f [a]
pSome Parser Char
pDigit

-- | Parse a keyword. Note: It must really a key/word/! This parser makes sure to return an identifier when
-- it's actually an identifier that starts with that keyword.
parseKeyword :: Token -> String -> LParser Token
parseKeyword :: Token -> String -> LParser Token
parseKeyword Token
tok String
word =
  forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
word
    forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> ((\String
k -> String -> Token
Identifier forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a] -> [a]
(++) String
k) forall (p :: * -> *) a b c.
IsParser p =>
(a -> b -> c) -> p b -> p (a -> c)
<$$> forall (f :: * -> *) a. IsParser f => f a -> f [a]
pSome LParser Char
pIdentifierCharacter forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a b. a -> b -> a
const forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (p :: * -> *) a. Applicative p => a -> p a
pReturn Token
tok)

-- | Parse just an identifier.
parseIdentifier :: LParser String
parseIdentifier :: LParser String
parseIdentifier = (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser Char
pNonDigitIdentifierCharacter forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. IsParser f => f a -> f [a]
pMany LParser Char
pIdentifierCharacter

-- | Parse a label.
parseLabel :: LParser Token
parseLabel :: LParser Token
parseLabel =
  String -> String -> String -> Token
Label
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"::"
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser String
parseOptionalWhitespace
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser String
parseIdentifier
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser String
parseOptionalWhitespace
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"::"

-- | Parse anything to do with dots. Indexaction (.), concatenation (..) or varargs (...)
parseDots :: LParser Token
parseDots :: LParser Token
parseDots =
  forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"."
    forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> ( -- A dot means it's either a VarArg (...), concatenation (..) or just a dot (.)
           forall a b. a -> b -> a
const
            forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ( forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"."
                    forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> ( forall a b. a -> b -> a
const Token
VarArg
                            forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"."
                              forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a b. a -> b -> a
const
                            forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (p :: * -> *) a. Applicative p => a -> p a
pReturn Token
Concatenate
                         )
                )
              forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> (\String
ds String
sfx String
dot -> String -> Token
TNumber forall a b. (a -> b) -> a -> b
$ String
dot forall a. [a] -> [a] -> [a]
++ String
ds forall a. [a] -> [a] -> [a]
++ String
sfx)
            forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a. IsParser f => f a -> f [a]
pSome Parser Char
pDigit
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (p :: * -> *) a. ExtAlternative p => p a -> a -> p a
opt LParser String
parseNumberSuffix String
""
              forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> forall a b. a -> b -> a
const
            forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (p :: * -> *) a. Applicative p => a -> p a
pReturn Token
Dot
         )

-- | Parse any kind of token.
parseToken :: LParser Token
parseToken :: LParser Token
parseToken =
  LParser Token
parseComment
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|>
    -- Constants
    LParser Token
parseString
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> LParser Token
parseNumber
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
TTrue String
"true"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
TFalse String
"false"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Nil String
"nil"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Not String
"not"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
And String
"and"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Or String
"or"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Function String
"function"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Local String
"local"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
If String
"if"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Then String
"then"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Elseif String
"elseif"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Else String
"else"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
For String
"for"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
In String
"in"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Do String
"do"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
While String
"while"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Until String
"until"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Repeat String
"repeat"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Continue String
"continue"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Break String
"break"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
Return String
"return"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token -> String -> LParser Token
parseKeyword Token
End String
"end"
    forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> String -> Token
Identifier
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser String
parseIdentifier
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
Semicolon
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
";"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> LParser Token
parseDots
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|>
      -- Operators
      Token
Plus
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"+"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
Minus
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"-"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
Multiply
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"*"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
Modulus
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"%"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
Power
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"^"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
TEq
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"=="
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
Equals
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"="
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
TNEq
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"~="
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
TCNEq
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"!="
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
CNot
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"!"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
TLEQ
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"<="
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
TLT
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"<"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
TGEQ
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
">="
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
TGT
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
">"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> LParser Token
parseLabel
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
Colon
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
":"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
Comma
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
","
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
Hash
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"#"
      forall state a. P state a -> Int -> P state a
`micro` Int
10
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
CAnd -- Add micro cost to prevent conflict with parseHashBang
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"&&"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
COr
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"||"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
LRound
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"("
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
RRound
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
")"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
LCurly
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"{"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> Token
RCurly
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"}"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|>
      -- Other square bracket is parsed in parseString
      Token
RSquare
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"]"
      forall (p :: * -> *) a. ExtAlternative p => p a -> p a -> p a
<<|> String -> Token
Whitespace
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser String
parseWhitespace

-- | A thing of which the region is to be parsed
annotated :: (Region -> a -> b) -> LParser a -> LParser b
annotated :: forall a b. (Region -> a -> b) -> LParser a -> LParser b
annotated Region -> a -> b
f LParser a
p = (\LineColPos
s a
t LineColPos
e -> Region -> a -> b
f (LineColPos -> LineColPos -> Region
Region LineColPos
s LineColPos
e) a
t) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall st pos. HasPosition st pos => P st pos
pPos forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser a
p forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall st pos. HasPosition st pos => P st pos
pPos

-- | parse located MToken
parseMToken :: LParser MToken
parseMToken :: LParser MToken
parseMToken = forall a b. (Region -> a -> b) -> LParser a -> LParser b
annotated Region -> Token -> MToken
MToken LParser Token
parseToken

-- | Parse a list of tokens and turn them into MTokens.
parseTokens :: LParser [MToken]
parseTokens :: LParser [MToken]
parseTokens = forall (f :: * -> *) a. IsParser f => f a -> f [a]
pMany LParser MToken
parseMToken

-- | Parse the potential #!comment on the first line
-- Lua ignores the first line if it starts with #
parseHashBang :: LParser String
parseHashBang :: LParser String
parseHashBang = forall (p :: * -> *) a. ExtAlternative p => p a -> a -> p a
opt (forall loc state a.
(Show a, Eq a, IsLocationUpdatedBy loc a, ListLike state a) =>
[a] -> P (Str a state loc) [a]
pToken String
"#" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* LParser String
pUntilEnd) String
""

-- | Lex a string with a given lexer
lexFromString :: LParser a -> String -> (a, [Error LineColPos])
lexFromString :: forall a. LParser a -> String -> (a, [Error LineColPos])
lexFromString LParser a
p = forall t a. Eof t => P t a -> t -> a
parse ((,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser a
p forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall st error. StoresErrors st error => P st [error]
pErrors forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall st error. (StoresErrors st error, Eof st) => P st [error]
pEnd) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a loc. ListLike s a => loc -> s -> Str a s loc
createStr (Int -> Int -> Int -> LineColPos
LineColPos Int
0 Int
0 Int
0)

-- | Parse a string into MTokens. Also returns parse errors.
execParseTokens :: String -> ([MToken], [Error LineColPos])
execParseTokens :: String -> ([MToken], [Error LineColPos])
execParseTokens = forall t a. Eof t => P t a -> t -> a
parse ((,) forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ LParser String
parseHashBang forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LParser [MToken]
parseTokens forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall st error. StoresErrors st error => P st [error]
pErrors forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall st error. (StoresErrors st error, Eof st) => P st [error]
pEnd) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a loc. ListLike s a => loc -> s -> Str a s loc
createStr (Int -> Int -> Int -> LineColPos
LineColPos Int
0 Int
0 Int
0)