{-# LANGUAGE BangPatterns, LambdaCase, OverloadedStrings #-}
{-|
Module      : Htcc.Parser.Parsing.Global
Description : The C languge parser and AST constructor
Copyright   : (c) roki, 2019
License     : MIT
Maintainer  : falgon53@yahoo.co.jp
Stability   : experimental
Portability : POSIX

The module of the globals
-}
module Htcc.Parser.Parsing.Global (
    globalDef
) where

import           Data.Bits

import           Htcc.Parser.AST
import           Htcc.Parser.ConstructionData
import           Htcc.Parser.Parsing.Global.Function
import           Htcc.Parser.Parsing.Global.Var
import           Htcc.Parser.Parsing.Type            (takeType)
import           Htcc.Parser.Parsing.Typedef
import qualified Htcc.Tokenizer                      as HT
import           Htcc.Utils                          (uncurry4)

-- | `globalDef` parses global definitions (include functions and global variables)
-- \[
-- \text{global-def}=\left(\text{global-var}\ \mid\ \text{function}\right)\text{*}
-- \]
globalDef :: (Show i, Read i, Integral i, Bits i) => [HT.TokenLC i] -> ATree i -> ConstructionData i -> ASTConstruction i
globalDef :: [TokenLC i] -> ATree i -> ConstructionData i -> ASTConstruction i
globalDef (cur :: TokenLC i
cur@(_, HT.TKReserved "register"):_) _ _ = (Text, TokenLC i) -> ASTConstruction i
forall a b. a -> Either a b
Left ("illegal storage class on file-scoped identifier", TokenLC i
cur)
globalDef (cur :: TokenLC i
cur@(_, HT.TKReserved "auto"):_) _ _ = (Text, TokenLC i) -> ASTConstruction i
forall a b. a -> Either a b
Left ("illegal storage class on file-scoped identifier", TokenLC i
cur)
globalDef xs :: [TokenLC i]
xs@((_, HT.TKTypedef):_) _ sc :: ConstructionData i
sc = [TokenLC i] -> ConstructionData i -> ASTConstruction i
forall i a.
(Integral i, Show i, Read i, Bits i) =>
[(TokenLCNums i, Token i)]
-> ConstructionData i
-> Either
     (ASTError i)
     ([(TokenLCNums i, Token i)], ATree a, ConstructionData i)
typedef [TokenLC i]
xs ConstructionData i
sc -- for global @typedef@
globalDef tks :: [TokenLC i]
tks at :: ATree i
at !ConstructionData i
va = Either
  (Text, TokenLC i)
  (StorageClass i, Maybe (TokenLC i), [TokenLC i],
   ConstructionData i)
-> ((StorageClass i, Maybe (TokenLC i), [TokenLC i],
     ConstructionData i)
    -> ASTConstruction i)
-> ASTConstruction i
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
(>>=) ([TokenLC i]
-> ConstructionData i
-> Either
     (Text, TokenLC i)
     (StorageClass i, Maybe (TokenLC i), [TokenLC i],
      ConstructionData i)
forall i.
(Integral i, Show i, Read i, Bits i) =>
[TokenLC i]
-> ConstructionData i
-> Either
     (ASTError i)
     (StorageClass i, Maybe (TokenLC i), [TokenLC i],
      ConstructionData i)
takeType [TokenLC i]
tks ConstructionData i
va) (((StorageClass i, Maybe (TokenLC i), [TokenLC i],
   ConstructionData i)
  -> ASTConstruction i)
 -> ASTConstruction i)
-> ((StorageClass i, Maybe (TokenLC i), [TokenLC i],
     ConstructionData i)
    -> ASTConstruction i)
-> ASTConstruction i
forall a b. (a -> b) -> a -> b
$ \case
    (_, Nothing, (_, HT.TKReserved ";"):ds' :: [TokenLC i]
ds', scp :: ConstructionData i
scp) -> ([TokenLC i], ATree i, ConstructionData i) -> ASTConstruction i
forall a b. b -> Either a b
Right ([TokenLC i]
ds', ATree i
forall a. ATree a
ATEmpty, ConstructionData i
scp) -- e.g., @int;@ is legal in C11 (See N1570/section 6.7 Declarations)
    (funcType :: StorageClass i
funcType, ident :: Maybe (TokenLC i)
ident@(Just (_, HT.TKIdent _)), tk :: [TokenLC i]
tk@((_, HT.TKReserved "("):_), !ConstructionData i
sc) -> StorageClass i
-> Maybe (TokenLC i)
-> [TokenLC i]
-> ATree i
-> ConstructionData i
-> ASTConstruction i
forall i.
(Show i, Read i, Integral i, Bits i) =>
StorageClass i
-> Maybe (TokenLC i)
-> [TokenLC i]
-> ATree i
-> ConstructionData i
-> ASTConstruction i
function StorageClass i
funcType Maybe (TokenLC i)
ident [TokenLC i]
tk ATree i
at ConstructionData i
sc
    p :: (StorageClass i, Maybe (TokenLC i), [TokenLC i],
 ConstructionData i)
p@(_, Just (_, HT.TKIdent _), _, _) -> (StorageClass i
 -> Maybe (TokenLC i)
 -> [TokenLC i]
 -> ConstructionData i
 -> ASTConstruction i)
-> (StorageClass i, Maybe (TokenLC i), [TokenLC i],
    ConstructionData i)
-> ASTConstruction i
forall a b c d e. (a -> b -> c -> d -> e) -> (a, b, c, d) -> e
uncurry4 StorageClass i
-> Maybe (TokenLC i)
-> [TokenLC i]
-> ConstructionData i
-> ASTConstruction i
forall i.
(Show i, Read i, Integral i, Bits i) =>
StorageClass i
-> Maybe (TokenLC i)
-> [TokenLC i]
-> ConstructionData i
-> ASTConstruction i
var (StorageClass i, Maybe (TokenLC i), [TokenLC i],
 ConstructionData i)
p
    _ -> (Text, TokenLC i) -> ASTConstruction i
forall a b. a -> Either a b
Left ("invalid definition of global identifier", [TokenLC i] -> TokenLC i
forall i. Num i => [TokenLC i] -> TokenLC i
HT.altEmptyToken [TokenLC i]
tks)