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

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

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

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

-- | 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
<**> -- Dash block comment and dash comment both start with "--"
                    (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)) 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
<**> -- Escaped character in string always starts with backslash
                         ((\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) 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
<<|> -- the end of the string
                      (:) 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 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 String
parseLabel :: LParser String
parseLabel = 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
*> (forall (p :: * -> *) a. IsParser p => p a -> p (Maybe a)
pMaybe LParser String
parseWhitespace forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> LParser String
parseIdentifier forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall (p :: * -> *) a. IsParser p => p a -> p (Maybe a)
pMaybe LParser String
parseWhitespace) 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
<<|>
                String -> Token
Label forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LParser String
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
<<|> -- Add micro cost to prevent conflict with parseHashBang
                Token
CAnd 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)