    module Language.GLSL.Syntax where

    -- TODO:
    -- - add support for 'array of strings' ?
    -- - add support for macro preprocessing
    -- - add support for optional macro #include
    -- - applicative style (see http://github.com/markusle/husky)?
    -- - type checking
    -- - check for constant expression where expected
    -- - error reporting
    -- - pretty-printing
    -- - basic queries (inputs and outputs of the shader)
    -- - support GLSL 1.40?
    -- - proper testing (HUnit and QuickCheck)
    -- - use hpc with the tests
    -- - scoping
    -- - clean module import/export
    -- - order of Syntax data types and Pretty instances should be the same
    -- - build with no warning
    -- - use hlint
    -- - push to github
    -- - push to hackage
    -- - use parsec 3
    -- - handle all possible newlines (\n, \r, \r\n, \n\r)
    -- - 80-columns clean

    -- - lot of restriction of Samplers use (section 4.1.7),
    -- well in fact, for plenty of things.

    ----------------------------------------------------------------------
    -- Abstract syntax tree
    ----------------------------------------------------------------------

    data TranslationUnit = TranslationUnit [ExternalDeclaration] -- at least one
      deriving (Int -> TranslationUnit -> ShowS
    [TranslationUnit] -> ShowS
    TranslationUnit -> String
    (Int -> TranslationUnit -> ShowS)
    -> (TranslationUnit -> String)
    -> ([TranslationUnit] -> ShowS)
    -> Show TranslationUnit
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> TranslationUnit -> ShowS
    showsPrec :: Int -> TranslationUnit -> ShowS
    $cshow :: TranslationUnit -> String
    show :: TranslationUnit -> String
    $cshowList :: [TranslationUnit] -> ShowS
    showList :: [TranslationUnit] -> ShowS
    Show, TranslationUnit -> TranslationUnit -> Bool
    (TranslationUnit -> TranslationUnit -> Bool)
    -> (TranslationUnit -> TranslationUnit -> Bool)
    -> Eq TranslationUnit
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: TranslationUnit -> TranslationUnit -> Bool
    == :: TranslationUnit -> TranslationUnit -> Bool
    $c/= :: TranslationUnit -> TranslationUnit -> Bool
    /= :: TranslationUnit -> TranslationUnit -> Bool
    Eq)

    data ExternalDeclaration =
        -- function declarations should be at top level (page 28)
        FunctionDeclaration FunctionPrototype
      | FunctionDefinition FunctionPrototype Compound
      | Declaration Declaration
      deriving (Int -> ExternalDeclaration -> ShowS
    [ExternalDeclaration] -> ShowS
    ExternalDeclaration -> String
    (Int -> ExternalDeclaration -> ShowS)
    -> (ExternalDeclaration -> String)
    -> ([ExternalDeclaration] -> ShowS)
    -> Show ExternalDeclaration
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ExternalDeclaration -> ShowS
    showsPrec :: Int -> ExternalDeclaration -> ShowS
    $cshow :: ExternalDeclaration -> String
    show :: ExternalDeclaration -> String
    $cshowList :: [ExternalDeclaration] -> ShowS
    showList :: [ExternalDeclaration] -> ShowS
    Show, ExternalDeclaration -> ExternalDeclaration -> Bool
    (ExternalDeclaration -> ExternalDeclaration -> Bool)
    -> (ExternalDeclaration -> ExternalDeclaration -> Bool)
    -> Eq ExternalDeclaration
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ExternalDeclaration -> ExternalDeclaration -> Bool
    == :: ExternalDeclaration -> ExternalDeclaration -> Bool
    $c/= :: ExternalDeclaration -> ExternalDeclaration -> Bool
    /= :: ExternalDeclaration -> ExternalDeclaration -> Bool
    Eq)

    -- TODO clean
    data Declaration =
    -- e.g. layout (origin_upper_left) in vec4 gl_FragCoord;
    --      struct name { ... };
    --      struct name { ... } name;
        InitDeclaration InvariantOrType [InitDeclarator]
      | Precision PrecisionQualifier TypeSpecifierNoPrecision
      | Block TypeQualifier String [Field] (Maybe (String, Maybe (Maybe Expr))) -- constant expression
    -- e.g. layout (origin_upper_left) in; TODO check if it is only used for default layout.
      | TQ TypeQualifier
      deriving (Int -> Declaration -> ShowS
    [Declaration] -> ShowS
    Declaration -> String
    (Int -> Declaration -> ShowS)
    -> (Declaration -> String)
    -> ([Declaration] -> ShowS)
    -> Show Declaration
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Declaration -> ShowS
    showsPrec :: Int -> Declaration -> ShowS
    $cshow :: Declaration -> String
    show :: Declaration -> String
    $cshowList :: [Declaration] -> ShowS
    showList :: [Declaration] -> ShowS
    Show, Declaration -> Declaration -> Bool
    (Declaration -> Declaration -> Bool)
    -> (Declaration -> Declaration -> Bool) -> Eq Declaration
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Declaration -> Declaration -> Bool
    == :: Declaration -> Declaration -> Bool
    $c/= :: Declaration -> Declaration -> Bool
    /= :: Declaration -> Declaration -> Bool
    Eq)

    -- TODO regroup String (Maybe (Maybe Expr)) as Declarator and use it for
    -- StructDeclarator.
    data InitDeclarator = InitDecl String (Maybe (Maybe Expr)) (Maybe Expr) -- constant expression; assignment expression
      deriving (Int -> InitDeclarator -> ShowS
    [InitDeclarator] -> ShowS
    InitDeclarator -> String
    (Int -> InitDeclarator -> ShowS)
    -> (InitDeclarator -> String)
    -> ([InitDeclarator] -> ShowS)
    -> Show InitDeclarator
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> InitDeclarator -> ShowS
    showsPrec :: Int -> InitDeclarator -> ShowS
    $cshow :: InitDeclarator -> String
    show :: InitDeclarator -> String
    $cshowList :: [InitDeclarator] -> ShowS
    showList :: [InitDeclarator] -> ShowS
    Show, InitDeclarator -> InitDeclarator -> Bool
    (InitDeclarator -> InitDeclarator -> Bool)
    -> (InitDeclarator -> InitDeclarator -> Bool) -> Eq InitDeclarator
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: InitDeclarator -> InitDeclarator -> Bool
    == :: InitDeclarator -> InitDeclarator -> Bool
    $c/= :: InitDeclarator -> InitDeclarator -> Bool
    /= :: InitDeclarator -> InitDeclarator -> Bool
    Eq)

    data InvariantOrType = InvariantDeclarator | TypeDeclarator FullType
      deriving (Int -> InvariantOrType -> ShowS
    [InvariantOrType] -> ShowS
    InvariantOrType -> String
    (Int -> InvariantOrType -> ShowS)
    -> (InvariantOrType -> String)
    -> ([InvariantOrType] -> ShowS)
    -> Show InvariantOrType
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> InvariantOrType -> ShowS
    showsPrec :: Int -> InvariantOrType -> ShowS
    $cshow :: InvariantOrType -> String
    show :: InvariantOrType -> String
    $cshowList :: [InvariantOrType] -> ShowS
    showList :: [InvariantOrType] -> ShowS
    Show, InvariantOrType -> InvariantOrType -> Bool
    (InvariantOrType -> InvariantOrType -> Bool)
    -> (InvariantOrType -> InvariantOrType -> Bool)
    -> Eq InvariantOrType
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: InvariantOrType -> InvariantOrType -> Bool
    == :: InvariantOrType -> InvariantOrType -> Bool
    $c/= :: InvariantOrType -> InvariantOrType -> Bool
    /= :: InvariantOrType -> InvariantOrType -> Bool
    Eq)

    data FunctionPrototype = FuncProt FullType String [ParameterDeclaration]
      deriving (Int -> FunctionPrototype -> ShowS
    [FunctionPrototype] -> ShowS
    FunctionPrototype -> String
    (Int -> FunctionPrototype -> ShowS)
    -> (FunctionPrototype -> String)
    -> ([FunctionPrototype] -> ShowS)
    -> Show FunctionPrototype
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> FunctionPrototype -> ShowS
    showsPrec :: Int -> FunctionPrototype -> ShowS
    $cshow :: FunctionPrototype -> String
    show :: FunctionPrototype -> String
    $cshowList :: [FunctionPrototype] -> ShowS
    showList :: [FunctionPrototype] -> ShowS
    Show, FunctionPrototype -> FunctionPrototype -> Bool
    (FunctionPrototype -> FunctionPrototype -> Bool)
    -> (FunctionPrototype -> FunctionPrototype -> Bool)
    -> Eq FunctionPrototype
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: FunctionPrototype -> FunctionPrototype -> Bool
    == :: FunctionPrototype -> FunctionPrototype -> Bool
    $c/= :: FunctionPrototype -> FunctionPrototype -> Bool
    /= :: FunctionPrototype -> FunctionPrototype -> Bool
    Eq)

    data ParameterDeclaration =
      ParameterDeclaration (Maybe ParameterTypeQualifier)
                           (Maybe ParameterQualifier)
                           TypeSpecifier
                           (Maybe (String, Maybe Expr)) -- constant expression
      deriving (Int -> ParameterDeclaration -> ShowS
    [ParameterDeclaration] -> ShowS
    ParameterDeclaration -> String
    (Int -> ParameterDeclaration -> ShowS)
    -> (ParameterDeclaration -> String)
    -> ([ParameterDeclaration] -> ShowS)
    -> Show ParameterDeclaration
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ParameterDeclaration -> ShowS
    showsPrec :: Int -> ParameterDeclaration -> ShowS
    $cshow :: ParameterDeclaration -> String
    show :: ParameterDeclaration -> String
    $cshowList :: [ParameterDeclaration] -> ShowS
    showList :: [ParameterDeclaration] -> ShowS
    Show, ParameterDeclaration -> ParameterDeclaration -> Bool
    (ParameterDeclaration -> ParameterDeclaration -> Bool)
    -> (ParameterDeclaration -> ParameterDeclaration -> Bool)
    -> Eq ParameterDeclaration
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ParameterDeclaration -> ParameterDeclaration -> Bool
    == :: ParameterDeclaration -> ParameterDeclaration -> Bool
    $c/= :: ParameterDeclaration -> ParameterDeclaration -> Bool
    /= :: ParameterDeclaration -> ParameterDeclaration -> Bool
    Eq)

    data FullType = FullType (Maybe TypeQualifier) TypeSpecifier
      deriving (Int -> FullType -> ShowS
    [FullType] -> ShowS
    FullType -> String
    (Int -> FullType -> ShowS)
    -> (FullType -> String) -> ([FullType] -> ShowS) -> Show FullType
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> FullType -> ShowS
    showsPrec :: Int -> FullType -> ShowS
    $cshow :: FullType -> String
    show :: FullType -> String
    $cshowList :: [FullType] -> ShowS
    showList :: [FullType] -> ShowS
    Show, FullType -> FullType -> Bool
    (FullType -> FullType -> Bool)
    -> (FullType -> FullType -> Bool) -> Eq FullType
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: FullType -> FullType -> Bool
    == :: FullType -> FullType -> Bool
    $c/= :: FullType -> FullType -> Bool
    /= :: FullType -> FullType -> Bool
    Eq)

    -- sto
    -- lay [sto]
    -- int [sto]
    -- inv [sto]
    -- inv int sto
    data TypeQualifier =
        TypeQualSto StorageQualifier
      | TypeQualLay LayoutQualifier (Maybe StorageQualifier)
      | TypeQualInt InterpolationQualifier (Maybe StorageQualifier)
      | TypeQualInv InvariantQualifier (Maybe StorageQualifier)
      | TypeQualInv3 InvariantQualifier InterpolationQualifier StorageQualifier
      deriving (Int -> TypeQualifier -> ShowS
    [TypeQualifier] -> ShowS
    TypeQualifier -> String
    (Int -> TypeQualifier -> ShowS)
    -> (TypeQualifier -> String)
    -> ([TypeQualifier] -> ShowS)
    -> Show TypeQualifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> TypeQualifier -> ShowS
    showsPrec :: Int -> TypeQualifier -> ShowS
    $cshow :: TypeQualifier -> String
    show :: TypeQualifier -> String
    $cshowList :: [TypeQualifier] -> ShowS
    showList :: [TypeQualifier] -> ShowS
    Show, TypeQualifier -> TypeQualifier -> Bool
    (TypeQualifier -> TypeQualifier -> Bool)
    -> (TypeQualifier -> TypeQualifier -> Bool) -> Eq TypeQualifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: TypeQualifier -> TypeQualifier -> Bool
    == :: TypeQualifier -> TypeQualifier -> Bool
    $c/= :: TypeQualifier -> TypeQualifier -> Bool
    /= :: TypeQualifier -> TypeQualifier -> Bool
    Eq)

    data TypeSpecifier = TypeSpec (Maybe PrecisionQualifier) TypeSpecifierNoPrecision
      deriving (Int -> TypeSpecifier -> ShowS
    [TypeSpecifier] -> ShowS
    TypeSpecifier -> String
    (Int -> TypeSpecifier -> ShowS)
    -> (TypeSpecifier -> String)
    -> ([TypeSpecifier] -> ShowS)
    -> Show TypeSpecifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> TypeSpecifier -> ShowS
    showsPrec :: Int -> TypeSpecifier -> ShowS
    $cshow :: TypeSpecifier -> String
    show :: TypeSpecifier -> String
    $cshowList :: [TypeSpecifier] -> ShowS
    showList :: [TypeSpecifier] -> ShowS
    Show, TypeSpecifier -> TypeSpecifier -> Bool
    (TypeSpecifier -> TypeSpecifier -> Bool)
    -> (TypeSpecifier -> TypeSpecifier -> Bool) -> Eq TypeSpecifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: TypeSpecifier -> TypeSpecifier -> Bool
    == :: TypeSpecifier -> TypeSpecifier -> Bool
    $c/= :: TypeSpecifier -> TypeSpecifier -> Bool
    /= :: TypeSpecifier -> TypeSpecifier -> Bool
    Eq)

    data InvariantQualifier = Invariant
      deriving (Int -> InvariantQualifier -> ShowS
    [InvariantQualifier] -> ShowS
    InvariantQualifier -> String
    (Int -> InvariantQualifier -> ShowS)
    -> (InvariantQualifier -> String)
    -> ([InvariantQualifier] -> ShowS)
    -> Show InvariantQualifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> InvariantQualifier -> ShowS
    showsPrec :: Int -> InvariantQualifier -> ShowS
    $cshow :: InvariantQualifier -> String
    show :: InvariantQualifier -> String
    $cshowList :: [InvariantQualifier] -> ShowS
    showList :: [InvariantQualifier] -> ShowS
    Show, InvariantQualifier -> InvariantQualifier -> Bool
    (InvariantQualifier -> InvariantQualifier -> Bool)
    -> (InvariantQualifier -> InvariantQualifier -> Bool)
    -> Eq InvariantQualifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: InvariantQualifier -> InvariantQualifier -> Bool
    == :: InvariantQualifier -> InvariantQualifier -> Bool
    $c/= :: InvariantQualifier -> InvariantQualifier -> Bool
    /= :: InvariantQualifier -> InvariantQualifier -> Bool
    Eq)

    data InterpolationQualifier =
        Smooth
      | Flat
      | NoPerspective
      deriving (Int -> InterpolationQualifier -> ShowS
    [InterpolationQualifier] -> ShowS
    InterpolationQualifier -> String
    (Int -> InterpolationQualifier -> ShowS)
    -> (InterpolationQualifier -> String)
    -> ([InterpolationQualifier] -> ShowS)
    -> Show InterpolationQualifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> InterpolationQualifier -> ShowS
    showsPrec :: Int -> InterpolationQualifier -> ShowS
    $cshow :: InterpolationQualifier -> String
    show :: InterpolationQualifier -> String
    $cshowList :: [InterpolationQualifier] -> ShowS
    showList :: [InterpolationQualifier] -> ShowS
    Show, InterpolationQualifier -> InterpolationQualifier -> Bool
    (InterpolationQualifier -> InterpolationQualifier -> Bool)
    -> (InterpolationQualifier -> InterpolationQualifier -> Bool)
    -> Eq InterpolationQualifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: InterpolationQualifier -> InterpolationQualifier -> Bool
    == :: InterpolationQualifier -> InterpolationQualifier -> Bool
    $c/= :: InterpolationQualifier -> InterpolationQualifier -> Bool
    /= :: InterpolationQualifier -> InterpolationQualifier -> Bool
    Eq)

    data LayoutQualifier = Layout [LayoutQualifierId]
      deriving (Int -> LayoutQualifier -> ShowS
    [LayoutQualifier] -> ShowS
    LayoutQualifier -> String
    (Int -> LayoutQualifier -> ShowS)
    -> (LayoutQualifier -> String)
    -> ([LayoutQualifier] -> ShowS)
    -> Show LayoutQualifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> LayoutQualifier -> ShowS
    showsPrec :: Int -> LayoutQualifier -> ShowS
    $cshow :: LayoutQualifier -> String
    show :: LayoutQualifier -> String
    $cshowList :: [LayoutQualifier] -> ShowS
    showList :: [LayoutQualifier] -> ShowS
    Show, LayoutQualifier -> LayoutQualifier -> Bool
    (LayoutQualifier -> LayoutQualifier -> Bool)
    -> (LayoutQualifier -> LayoutQualifier -> Bool)
    -> Eq LayoutQualifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LayoutQualifier -> LayoutQualifier -> Bool
    == :: LayoutQualifier -> LayoutQualifier -> Bool
    $c/= :: LayoutQualifier -> LayoutQualifier -> Bool
    /= :: LayoutQualifier -> LayoutQualifier -> Bool
    Eq)

    data LayoutQualifierId = LayoutQualId String (Maybe Expr) -- TODO Expr should be IntConstant
      deriving (Int -> LayoutQualifierId -> ShowS
    [LayoutQualifierId] -> ShowS
    LayoutQualifierId -> String
    (Int -> LayoutQualifierId -> ShowS)
    -> (LayoutQualifierId -> String)
    -> ([LayoutQualifierId] -> ShowS)
    -> Show LayoutQualifierId
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> LayoutQualifierId -> ShowS
    showsPrec :: Int -> LayoutQualifierId -> ShowS
    $cshow :: LayoutQualifierId -> String
    show :: LayoutQualifierId -> String
    $cshowList :: [LayoutQualifierId] -> ShowS
    showList :: [LayoutQualifierId] -> ShowS
    Show, LayoutQualifierId -> LayoutQualifierId -> Bool
    (LayoutQualifierId -> LayoutQualifierId -> Bool)
    -> (LayoutQualifierId -> LayoutQualifierId -> Bool)
    -> Eq LayoutQualifierId
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LayoutQualifierId -> LayoutQualifierId -> Bool
    == :: LayoutQualifierId -> LayoutQualifierId -> Bool
    $c/= :: LayoutQualifierId -> LayoutQualifierId -> Bool
    /= :: LayoutQualifierId -> LayoutQualifierId -> Bool
    Eq)

    data Statement =
      -- declaration statement
        DeclarationStatement Declaration
      -- jump statement
      | Continue
      | Break
      | Return (Maybe Expr)
      | Discard -- fragment shader only
      -- compound statement
      | CompoundStatement Compound
      -- expression statement
      | ExpressionStatement (Maybe Expr)
      -- selection statement
      | SelectionStatement Expr Statement (Maybe Statement)
      -- switch statement
      | SwitchStatement Expr [Statement]
      | CaseLabel CaseLabel
      -- iteration statement
      | While Condition Statement -- no new scope
      | DoWhile Statement Expr
      | For (Either (Maybe Expr) Declaration) (Maybe Condition) (Maybe Expr) Statement
        -- 1st stmt: expression or declaration, 2nd: no new scope
      deriving (Int -> Statement -> ShowS
    [Statement] -> ShowS
    Statement -> String
    (Int -> Statement -> ShowS)
    -> (Statement -> String)
    -> ([Statement] -> ShowS)
    -> Show Statement
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Statement -> ShowS
    showsPrec :: Int -> Statement -> ShowS
    $cshow :: Statement -> String
    show :: Statement -> String
    $cshowList :: [Statement] -> ShowS
    showList :: [Statement] -> ShowS
    Show, Statement -> Statement -> Bool
    (Statement -> Statement -> Bool)
    -> (Statement -> Statement -> Bool) -> Eq Statement
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Statement -> Statement -> Bool
    == :: Statement -> Statement -> Bool
    $c/= :: Statement -> Statement -> Bool
    /= :: Statement -> Statement -> Bool
    Eq)

    data Compound = Compound [Statement]
      deriving (Int -> Compound -> ShowS
    [Compound] -> ShowS
    Compound -> String
    (Int -> Compound -> ShowS)
    -> (Compound -> String) -> ([Compound] -> ShowS) -> Show Compound
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Compound -> ShowS
    showsPrec :: Int -> Compound -> ShowS
    $cshow :: Compound -> String
    show :: Compound -> String
    $cshowList :: [Compound] -> ShowS
    showList :: [Compound] -> ShowS
    Show, Compound -> Compound -> Bool
    (Compound -> Compound -> Bool)
    -> (Compound -> Compound -> Bool) -> Eq Compound
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Compound -> Compound -> Bool
    == :: Compound -> Compound -> Bool
    $c/= :: Compound -> Compound -> Bool
    /= :: Compound -> Compound -> Bool
    Eq)

    data Condition =
        Condition Expr
      | InitializedCondition FullType String Expr -- assignment expression
      deriving (Int -> Condition -> ShowS
    [Condition] -> ShowS
    Condition -> String
    (Int -> Condition -> ShowS)
    -> (Condition -> String)
    -> ([Condition] -> ShowS)
    -> Show Condition
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Condition -> ShowS
    showsPrec :: Int -> Condition -> ShowS
    $cshow :: Condition -> String
    show :: Condition -> String
    $cshowList :: [Condition] -> ShowS
    showList :: [Condition] -> ShowS
    Show, Condition -> Condition -> Bool
    (Condition -> Condition -> Bool)
    -> (Condition -> Condition -> Bool) -> Eq Condition
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Condition -> Condition -> Bool
    == :: Condition -> Condition -> Bool
    $c/= :: Condition -> Condition -> Bool
    /= :: Condition -> Condition -> Bool
    Eq)

    data CaseLabel = Case Expr | Default
      deriving (Int -> CaseLabel -> ShowS
    [CaseLabel] -> ShowS
    CaseLabel -> String
    (Int -> CaseLabel -> ShowS)
    -> (CaseLabel -> String)
    -> ([CaseLabel] -> ShowS)
    -> Show CaseLabel
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> CaseLabel -> ShowS
    showsPrec :: Int -> CaseLabel -> ShowS
    $cshow :: CaseLabel -> String
    show :: CaseLabel -> String
    $cshowList :: [CaseLabel] -> ShowS
    showList :: [CaseLabel] -> ShowS
    Show, CaseLabel -> CaseLabel -> Bool
    (CaseLabel -> CaseLabel -> Bool)
    -> (CaseLabel -> CaseLabel -> Bool) -> Eq CaseLabel
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: CaseLabel -> CaseLabel -> Bool
    == :: CaseLabel -> CaseLabel -> Bool
    $c/= :: CaseLabel -> CaseLabel -> Bool
    /= :: CaseLabel -> CaseLabel -> Bool
    Eq)

    data StorageQualifier =
        Const
      | Attribute -- vertex only
      | Varying
      | CentroidVarying
      | In
      | Out
      | CentroidIn
      | CentroidOut
      | Uniform
      deriving (Int -> StorageQualifier -> ShowS
    [StorageQualifier] -> ShowS
    StorageQualifier -> String
    (Int -> StorageQualifier -> ShowS)
    -> (StorageQualifier -> String)
    -> ([StorageQualifier] -> ShowS)
    -> Show StorageQualifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> StorageQualifier -> ShowS
    showsPrec :: Int -> StorageQualifier -> ShowS
    $cshow :: StorageQualifier -> String
    show :: StorageQualifier -> String
    $cshowList :: [StorageQualifier] -> ShowS
    showList :: [StorageQualifier] -> ShowS
    Show, StorageQualifier -> StorageQualifier -> Bool
    (StorageQualifier -> StorageQualifier -> Bool)
    -> (StorageQualifier -> StorageQualifier -> Bool)
    -> Eq StorageQualifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: StorageQualifier -> StorageQualifier -> Bool
    == :: StorageQualifier -> StorageQualifier -> Bool
    $c/= :: StorageQualifier -> StorageQualifier -> Bool
    /= :: StorageQualifier -> StorageQualifier -> Bool
    Eq)

    data TypeSpecifierNoPrecision = TypeSpecNoPrecision TypeSpecifierNonArray (Maybe (Maybe Expr)) -- constant expression
      deriving (Int -> TypeSpecifierNoPrecision -> ShowS
    [TypeSpecifierNoPrecision] -> ShowS
    TypeSpecifierNoPrecision -> String
    (Int -> TypeSpecifierNoPrecision -> ShowS)
    -> (TypeSpecifierNoPrecision -> String)
    -> ([TypeSpecifierNoPrecision] -> ShowS)
    -> Show TypeSpecifierNoPrecision
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> TypeSpecifierNoPrecision -> ShowS
    showsPrec :: Int -> TypeSpecifierNoPrecision -> ShowS
    $cshow :: TypeSpecifierNoPrecision -> String
    show :: TypeSpecifierNoPrecision -> String
    $cshowList :: [TypeSpecifierNoPrecision] -> ShowS
    showList :: [TypeSpecifierNoPrecision] -> ShowS
    Show, TypeSpecifierNoPrecision -> TypeSpecifierNoPrecision -> Bool
    (TypeSpecifierNoPrecision -> TypeSpecifierNoPrecision -> Bool)
    -> (TypeSpecifierNoPrecision -> TypeSpecifierNoPrecision -> Bool)
    -> Eq TypeSpecifierNoPrecision
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: TypeSpecifierNoPrecision -> TypeSpecifierNoPrecision -> Bool
    == :: TypeSpecifierNoPrecision -> TypeSpecifierNoPrecision -> Bool
    $c/= :: TypeSpecifierNoPrecision -> TypeSpecifierNoPrecision -> Bool
    /= :: TypeSpecifierNoPrecision -> TypeSpecifierNoPrecision -> Bool
    Eq)

    data TypeSpecifierNonArray =
        Void
      | Float
      | Int
      | UInt
      | Bool
      | Vec2
      | Vec3
      | Vec4
      | BVec2
      | BVec3
      | BVec4
      | IVec2
      | IVec3
      | IVec4
      | UVec2
      | UVec3
      | UVec4
      | Mat2
      | Mat3
      | Mat4
      | Mat2x2
      | Mat2x3
      | Mat2x4
      | Mat3x2
      | Mat3x3
      | Mat3x4
      | Mat4x2
      | Mat4x3
      | Mat4x4
      | Sampler1D
      | Sampler2D
      | Sampler3D
      | SamplerCube
      | Sampler1DShadow
      | Sampler2DShadow
      | SamplerCubeShadow
      | Sampler1DArray
      | Sampler2DArray
      | Sampler1DArrayShadow
      | Sampler2DArrayShadow
      | ISampler1D
      | ISampler2D
      | ISampler3D
      | ISamplerCube
      | ISampler1DArray
      | ISampler2DArray
      | USampler1D
      | USampler2D
      | USampler3D
      | USamplerCube
      | USampler1DArray
      | USampler2DArray
      | Sampler2DRect
      | Sampler2DRectShadow
      | ISampler2DRect
      | USampler2DRect
      | SamplerBuffer
      | ISamplerBuffer
      | USamplerBuffer
      | Sampler2DMS
      | ISampler2DMS
      | USampler2DMS
      | Sampler2DMSArray
      | ISampler2DMSArray
      | USampler2DMSArray
      | StructSpecifier (Maybe String) [Field]
      | TypeName String -- TODO user-defined type, should verify if it is declared
      deriving (Int -> TypeSpecifierNonArray -> ShowS
    [TypeSpecifierNonArray] -> ShowS
    TypeSpecifierNonArray -> String
    (Int -> TypeSpecifierNonArray -> ShowS)
    -> (TypeSpecifierNonArray -> String)
    -> ([TypeSpecifierNonArray] -> ShowS)
    -> Show TypeSpecifierNonArray
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> TypeSpecifierNonArray -> ShowS
    showsPrec :: Int -> TypeSpecifierNonArray -> ShowS
    $cshow :: TypeSpecifierNonArray -> String
    show :: TypeSpecifierNonArray -> String
    $cshowList :: [TypeSpecifierNonArray] -> ShowS
    showList :: [TypeSpecifierNonArray] -> ShowS
    Show, TypeSpecifierNonArray -> TypeSpecifierNonArray -> Bool
    (TypeSpecifierNonArray -> TypeSpecifierNonArray -> Bool)
    -> (TypeSpecifierNonArray -> TypeSpecifierNonArray -> Bool)
    -> Eq TypeSpecifierNonArray
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: TypeSpecifierNonArray -> TypeSpecifierNonArray -> Bool
    == :: TypeSpecifierNonArray -> TypeSpecifierNonArray -> Bool
    $c/= :: TypeSpecifierNonArray -> TypeSpecifierNonArray -> Bool
    /= :: TypeSpecifierNonArray -> TypeSpecifierNonArray -> Bool
    Eq)

    data PrecisionQualifier = HighP | MediumP | LowP
      deriving (Int -> PrecisionQualifier -> ShowS
    [PrecisionQualifier] -> ShowS
    PrecisionQualifier -> String
    (Int -> PrecisionQualifier -> ShowS)
    -> (PrecisionQualifier -> String)
    -> ([PrecisionQualifier] -> ShowS)
    -> Show PrecisionQualifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> PrecisionQualifier -> ShowS
    showsPrec :: Int -> PrecisionQualifier -> ShowS
    $cshow :: PrecisionQualifier -> String
    show :: PrecisionQualifier -> String
    $cshowList :: [PrecisionQualifier] -> ShowS
    showList :: [PrecisionQualifier] -> ShowS
    Show, PrecisionQualifier -> PrecisionQualifier -> Bool
    (PrecisionQualifier -> PrecisionQualifier -> Bool)
    -> (PrecisionQualifier -> PrecisionQualifier -> Bool)
    -> Eq PrecisionQualifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: PrecisionQualifier -> PrecisionQualifier -> Bool
    == :: PrecisionQualifier -> PrecisionQualifier -> Bool
    $c/= :: PrecisionQualifier -> PrecisionQualifier -> Bool
    /= :: PrecisionQualifier -> PrecisionQualifier -> Bool
    Eq)

    -- TODO The type qualifier can be present only when there is one or more declarators.
    -- There other restrictions, see 4.1.8.
    data Field = Field (Maybe TypeQualifier) TypeSpecifier [StructDeclarator]
      deriving (Int -> Field -> ShowS
    [Field] -> ShowS
    Field -> String
    (Int -> Field -> ShowS)
    -> (Field -> String) -> ([Field] -> ShowS) -> Show Field
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Field -> ShowS
    showsPrec :: Int -> Field -> ShowS
    $cshow :: Field -> String
    show :: Field -> String
    $cshowList :: [Field] -> ShowS
    showList :: [Field] -> ShowS
    Show, Field -> Field -> Bool
    (Field -> Field -> Bool) -> (Field -> Field -> Bool) -> Eq Field
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Field -> Field -> Bool
    == :: Field -> Field -> Bool
    $c/= :: Field -> Field -> Bool
    /= :: Field -> Field -> Bool
    Eq)

    data StructDeclarator = StructDeclarator String (Maybe (Maybe Expr)) -- constant expression
      deriving (Int -> StructDeclarator -> ShowS
    [StructDeclarator] -> ShowS
    StructDeclarator -> String
    (Int -> StructDeclarator -> ShowS)
    -> (StructDeclarator -> String)
    -> ([StructDeclarator] -> ShowS)
    -> Show StructDeclarator
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> StructDeclarator -> ShowS
    showsPrec :: Int -> StructDeclarator -> ShowS
    $cshow :: StructDeclarator -> String
    show :: StructDeclarator -> String
    $cshowList :: [StructDeclarator] -> ShowS
    showList :: [StructDeclarator] -> ShowS
    Show, StructDeclarator -> StructDeclarator -> Bool
    (StructDeclarator -> StructDeclarator -> Bool)
    -> (StructDeclarator -> StructDeclarator -> Bool)
    -> Eq StructDeclarator
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: StructDeclarator -> StructDeclarator -> Bool
    == :: StructDeclarator -> StructDeclarator -> Bool
    $c/= :: StructDeclarator -> StructDeclarator -> Bool
    /= :: StructDeclarator -> StructDeclarator -> Bool
    Eq)

    data Expr =
      -- primaryExpression
        Variable String
      | IntConstant IntConstantKind Integer
      | FloatConstant Float
      | BoolConstant Bool
      -- postfixExpression
      | Bracket Expr Expr
      | FieldSelection Expr String
      | MethodCall Expr FunctionIdentifier Parameters
      | FunctionCall FunctionIdentifier Parameters
      | PostInc Expr
      | PostDec Expr
      | PreInc Expr
      | PreDec Expr
      -- unary expression
      | UnaryPlus Expr
      | UnaryNegate Expr
      | UnaryNot Expr
      | UnaryOneComplement Expr
      -- binary expression
      | Mul Expr Expr
      | Div Expr Expr
      | Mod Expr Expr
      | Add Expr Expr
      | Sub Expr Expr
      | LeftShift Expr Expr
      | RightShift Expr Expr
      | Lt Expr Expr
      | Gt Expr Expr
      | Lte Expr Expr
      | Gte Expr Expr
      | Equ Expr Expr
      | Neq Expr Expr
      | BitAnd Expr Expr
      | BitXor Expr Expr
      | BitOr Expr Expr
      | And Expr Expr
      | Or Expr Expr
      | Selection Expr Expr Expr -- ternary _ ? _ : _ operator
      -- assignment, the left Expr should be unary expression
      | Equal Expr Expr
      | MulAssign Expr Expr
      | DivAssign Expr Expr
      | ModAssign Expr Expr
      | AddAssign Expr Expr
      | SubAssign Expr Expr
      | LeftAssign Expr Expr
      | RightAssign Expr Expr
      | AndAssign Expr Expr
      | XorAssign Expr Expr
      | OrAssign Expr Expr
      -- sequence
      | Sequence Expr Expr
      deriving (Int -> Expr -> ShowS
    [Expr] -> ShowS
    Expr -> String
    (Int -> Expr -> ShowS)
    -> (Expr -> String) -> ([Expr] -> ShowS) -> Show Expr
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Expr -> ShowS
    showsPrec :: Int -> Expr -> ShowS
    $cshow :: Expr -> String
    show :: Expr -> String
    $cshowList :: [Expr] -> ShowS
    showList :: [Expr] -> ShowS
    Show, Expr -> Expr -> Bool
    (Expr -> Expr -> Bool) -> (Expr -> Expr -> Bool) -> Eq Expr
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Expr -> Expr -> Bool
    == :: Expr -> Expr -> Bool
    $c/= :: Expr -> Expr -> Bool
    /= :: Expr -> Expr -> Bool
    Eq)

    data IntConstantKind = Hexadecimal | Octal | Decimal
      deriving (Int -> IntConstantKind -> ShowS
    [IntConstantKind] -> ShowS
    IntConstantKind -> String
    (Int -> IntConstantKind -> ShowS)
    -> (IntConstantKind -> String)
    -> ([IntConstantKind] -> ShowS)
    -> Show IntConstantKind
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> IntConstantKind -> ShowS
    showsPrec :: Int -> IntConstantKind -> ShowS
    $cshow :: IntConstantKind -> String
    show :: IntConstantKind -> String
    $cshowList :: [IntConstantKind] -> ShowS
    showList :: [IntConstantKind] -> ShowS
    Show, IntConstantKind -> IntConstantKind -> Bool
    (IntConstantKind -> IntConstantKind -> Bool)
    -> (IntConstantKind -> IntConstantKind -> Bool)
    -> Eq IntConstantKind
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: IntConstantKind -> IntConstantKind -> Bool
    == :: IntConstantKind -> IntConstantKind -> Bool
    $c/= :: IntConstantKind -> IntConstantKind -> Bool
    /= :: IntConstantKind -> IntConstantKind -> Bool
    Eq)

    data Parameters = ParamVoid | Params [Expr]
      deriving (Int -> Parameters -> ShowS
    [Parameters] -> ShowS
    Parameters -> String
    (Int -> Parameters -> ShowS)
    -> (Parameters -> String)
    -> ([Parameters] -> ShowS)
    -> Show Parameters
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Parameters -> ShowS
    showsPrec :: Int -> Parameters -> ShowS
    $cshow :: Parameters -> String
    show :: Parameters -> String
    $cshowList :: [Parameters] -> ShowS
    showList :: [Parameters] -> ShowS
    Show, Parameters -> Parameters -> Bool
    (Parameters -> Parameters -> Bool)
    -> (Parameters -> Parameters -> Bool) -> Eq Parameters
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Parameters -> Parameters -> Bool
    == :: Parameters -> Parameters -> Bool
    $c/= :: Parameters -> Parameters -> Bool
    /= :: Parameters -> Parameters -> Bool
    Eq)

    data ParameterQualifier = InParameter | OutParameter | InOutParameter
      deriving (Int -> ParameterQualifier -> ShowS
    [ParameterQualifier] -> ShowS
    ParameterQualifier -> String
    (Int -> ParameterQualifier -> ShowS)
    -> (ParameterQualifier -> String)
    -> ([ParameterQualifier] -> ShowS)
    -> Show ParameterQualifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ParameterQualifier -> ShowS
    showsPrec :: Int -> ParameterQualifier -> ShowS
    $cshow :: ParameterQualifier -> String
    show :: ParameterQualifier -> String
    $cshowList :: [ParameterQualifier] -> ShowS
    showList :: [ParameterQualifier] -> ShowS
    Show, ParameterQualifier -> ParameterQualifier -> Bool
    (ParameterQualifier -> ParameterQualifier -> Bool)
    -> (ParameterQualifier -> ParameterQualifier -> Bool)
    -> Eq ParameterQualifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ParameterQualifier -> ParameterQualifier -> Bool
    == :: ParameterQualifier -> ParameterQualifier -> Bool
    $c/= :: ParameterQualifier -> ParameterQualifier -> Bool
    /= :: ParameterQualifier -> ParameterQualifier -> Bool
    Eq)

    data ParameterTypeQualifier = ConstParameter
      deriving (Int -> ParameterTypeQualifier -> ShowS
    [ParameterTypeQualifier] -> ShowS
    ParameterTypeQualifier -> String
    (Int -> ParameterTypeQualifier -> ShowS)
    -> (ParameterTypeQualifier -> String)
    -> ([ParameterTypeQualifier] -> ShowS)
    -> Show ParameterTypeQualifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ParameterTypeQualifier -> ShowS
    showsPrec :: Int -> ParameterTypeQualifier -> ShowS
    $cshow :: ParameterTypeQualifier -> String
    show :: ParameterTypeQualifier -> String
    $cshowList :: [ParameterTypeQualifier] -> ShowS
    showList :: [ParameterTypeQualifier] -> ShowS
    Show, ParameterTypeQualifier -> ParameterTypeQualifier -> Bool
    (ParameterTypeQualifier -> ParameterTypeQualifier -> Bool)
    -> (ParameterTypeQualifier -> ParameterTypeQualifier -> Bool)
    -> Eq ParameterTypeQualifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ParameterTypeQualifier -> ParameterTypeQualifier -> Bool
    == :: ParameterTypeQualifier -> ParameterTypeQualifier -> Bool
    $c/= :: ParameterTypeQualifier -> ParameterTypeQualifier -> Bool
    /= :: ParameterTypeQualifier -> ParameterTypeQualifier -> Bool
    Eq)

    data FunctionIdentifier =
        -- TODO could be refine (I think a precision qualifier is not permitted,
        -- nor a complete struct definition)
        FuncIdTypeSpec TypeSpecifier
      | FuncId String
      deriving (Int -> FunctionIdentifier -> ShowS
    [FunctionIdentifier] -> ShowS
    FunctionIdentifier -> String
    (Int -> FunctionIdentifier -> ShowS)
    -> (FunctionIdentifier -> String)
    -> ([FunctionIdentifier] -> ShowS)
    -> Show FunctionIdentifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> FunctionIdentifier -> ShowS
    showsPrec :: Int -> FunctionIdentifier -> ShowS
    $cshow :: FunctionIdentifier -> String
    show :: FunctionIdentifier -> String
    $cshowList :: [FunctionIdentifier] -> ShowS
    showList :: [FunctionIdentifier] -> ShowS
    Show, FunctionIdentifier -> FunctionIdentifier -> Bool
    (FunctionIdentifier -> FunctionIdentifier -> Bool)
    -> (FunctionIdentifier -> FunctionIdentifier -> Bool)
    -> Eq FunctionIdentifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: FunctionIdentifier -> FunctionIdentifier -> Bool
    == :: FunctionIdentifier -> FunctionIdentifier -> Bool
    $c/= :: FunctionIdentifier -> FunctionIdentifier -> Bool
    /= :: FunctionIdentifier -> FunctionIdentifier -> Bool
    Eq)