{- This module was generated from data in the Kate syntax
   highlighting file sql-postgresql.xml, version 1.13, by Shane Wright (me@shanewright.co.uk) -}

module Text.Highlighting.Kate.Syntax.SqlPostgresql
          (highlight, parseExpression, syntaxName, syntaxExtensions)
where
import Text.Highlighting.Kate.Types
import Text.Highlighting.Kate.Common
import Text.ParserCombinators.Parsec hiding (State)
import Control.Monad.State
import Data.Char (isSpace)
import qualified Data.Set as Set

-- | Full name of language.
syntaxName :: String
syntaxName = "SQL (PostgreSQL)"

-- | Filename extensions for this language.
syntaxExtensions :: String
syntaxExtensions = "*.sql;*.SQL;*.ddl;*.DDL"

-- | Highlight source code using this syntax definition.
highlight :: String -> [SourceLine]
highlight input = evalState (mapM parseSourceLine $ lines input) startingState

parseSourceLine :: String -> State SyntaxState SourceLine
parseSourceLine = mkParseSourceLine (parseExpression Nothing)

-- | Parse an expression using appropriate local context.
parseExpression :: Maybe (String,String)
                -> KateParser Token
parseExpression mbcontext = do
  (lang,cont) <- maybe currentContext return mbcontext
  result <- parseRules (lang,cont)
  optional $ do eof
                updateState $ \st -> st{ synStPrevChar = '\n' }
                pEndLine
  return result

startingState = SyntaxState {synStContexts = [("SQL (PostgreSQL)","Normal")], synStLineNumber = 0, synStPrevChar = '\n', synStPrevNonspace = False, synStContinuation = False, synStCaseSensitive = True, synStKeywordCaseSensitive = False, synStCaptures = []}

pEndLine = do
  updateState $ \st -> st{ synStPrevNonspace = False }
  context <- currentContext
  contexts <- synStContexts `fmap` getState
  st <- getState
  if length contexts >= 2
    then case context of
      _ | synStContinuation st -> updateState $ \st -> st{ synStContinuation = False }
      ("SQL (PostgreSQL)","Normal") -> return ()
      ("SQL (PostgreSQL)","CreateFunction") -> return ()
      ("SQL (PostgreSQL)","FunctionBody") -> return ()
      ("SQL (PostgreSQL)","MultiLineString") -> return ()
      ("SQL (PostgreSQL)","String") -> return ()
      ("SQL (PostgreSQL)","SingleLineComment") -> (popContext) >> pEndLine
      ("SQL (PostgreSQL)","MultiLineComment") -> return ()
      ("SQL (PostgreSQL)","Identifier") -> (popContext) >> pEndLine
      ("SQL (PostgreSQL)","Preprocessor") -> (popContext) >> pEndLine
      _ -> return ()
    else return ()

withAttribute attr txt = do
  when (null txt) $ fail "Parser matched no text"
  updateState $ \st -> st { synStPrevChar = last txt
                          , synStPrevNonspace = synStPrevNonspace st || not (all isSpace txt) }
  return (attr, txt)

list_keywords = Set.fromList $ words $ "abort access action add admin after aggregate alias all allocate alter analyse analyze any are as asc asensitive assertion assignment asymmetric at atomic authorization backward before begin between binary both breadth by c cache call called cardinality cascade cascaded case cast catalog catalog_name chain characteristics character_length character_set_catalog character_set_name character_set_schema char_length check checked checkpoint class class_origin clob close cluster coalesce cobol collate collation collation_catalog collation_name collation_schema column column_name command_function command_function_code comment commit committed completion condition_number connect connection connection_name constraints constraint constraint_catalog constraint_name constraint_schema constructor contains continue convert copy corresponding count create createdb createuser cross cube current current_date current_path current_role current_time current_timestamp current_user cursor cursor_name cycle data database date datetime_interval_code datetime_interval_precision day deallocate dec decimal declare default deferrable deferred defined definer delete delimiters depth deref desc describe descriptor destroy destructor deterministic diagnostics dictionary disconnect dispatch distinct do domain double drop dynamic dynamic_function dynamic_function_code each else encoding encrypted end end-exec equals escape every except exception exclusive exec execute existing exists explain external false fetch final first for force foreign fortran forward found free freeze from full function g general generated get global go goto grant granted group grouping handler having hierarchy hold host hour identity ignore ilike immediate immutable implementation in increment index indicator infix inherits initialize initially inner inout input insensitive insert instance instantiable instead intersect interval into invoker is isnull isolation iterate join k key key_member key_type lancompiler language large last lateral leading left length less level like limit listen load local localtime localtimestamp location locator lock lower m map match max maxvalue message_length message_octet_length message_text method min minute minvalue mod mode modifies modify module month more move mumps name names national natural new next no nocreatedb nocreateuser none not nothing notify notnull null nullable nullif number numeric object octet_length of off offset oids old on only open operation operator option options order ordinality out outer output overlaps overlay overriding owner pad parameter parameters parameter_mode parameter_name parameter_ordinal_position parameter_specific_catalog parameter_specific_name parameter_specific_schema partial pascal password path pendant pli position postfix precision prefix preorder prepare preserve primary prior privileges procedural procedure public read reads real recursive ref references referencing reindex relative rename repeatable replace reset restrict result return returned_length returned_octet_length returned_sqlstate returns revoke right role rollback rollup routine routine_catalog routine_name routine_schema row rows row_count rule savepoint scale schema schema_name scope scroll search second section security select self sensitive sequence serializable server_name session session_user set setof sets share show similar simple size some source space specific specifictype specific_name sql sqlcode sqlerror sqlexception sqlstate sqlwarning stable start state statement static statistics stdin stdout structure style subclass_origin sublist substring sum symmetric sysid system system_user table table_name temp template temporary terminate than then timezone_hour timezone_minute to toast trailing transaction transactions_committed transactions_rolled_back transaction_active transform transforms translate translation treat trigger trigger_catalog trigger_name trigger_schema trim true truncate trusted type uncommitted under unencrypted union unique unknown unlisten unnamed unnest until update upper usage user user_defined_type_catalog user_defined_type_name user_defined_type_schema using vacuum valid value values variable varying verbose version view volatile when whenever where while with without work write year zone"
list_operators = Set.fromList $ words $ "+ - * / || |/ ||/ ! !! @ & | # << >> % ^ = != <> < <= > >= ~ ~* !~ !~* ^= := => ** .. and or not ## && &< &> <-> <^ >^ ?# ?- ?-| @-@ ?| ?|| @@ ~= <<= >>="
list_functions = Set.fromList $ words $ "abs cbrt ceil degrees exp floor ln log mod pi pow radians random round sign sqrt trunc acos asin atan atan2 cos cot sin tan bit_length char_length character_length lower octet_length position substring trim upper ascii btrim chr convert initcap length lpad ltrim pg_client_encoding repeat rpad rtrim strpos substr to_ascii translate encode decode to_char to_date to_timestamp to_number age date_part date_trunc extract isfinite now timeofday timestamp extract area box center diameter height isclosed isopen pclose npoint popen radius width box circle lseg path point polygon broadcast host masklen set_masklen netmask network abbrev nextval currval setval coalesce nullif has_table_privilege pg_get_viewdef pg_get_ruledef pg_get_indexdef pg_get_userbyid obj_description col_description avg count max min stddev sum variance"
list_types = Set.fromList $ words $ "bigint bigserial bit bit varying bool boolean box bytea char character character varying cidr circle date decimal double precision float8 inet int int2 int4 int8 integer interval line lseg lztext macaddr money numeric oid path point polygon real serial serial8 smallint text time timestamp timestamp with timezone timestamptz timetz varbit varchar"

regex_'25bulk'5fexceptions'5cb = compileRegex False "%bulk_exceptions\\b"
regex_'25bulk'5frowcount'5cb = compileRegex False "%bulk_rowcount\\b"
regex_'25found'5cb = compileRegex False "%found\\b"
regex_'25isopen'5cb = compileRegex False "%isopen\\b"
regex_'25notfound'5cb = compileRegex False "%notfound\\b"
regex_'25rowcount'5cb = compileRegex False "%rowcount\\b"
regex_'25rowtype'5cb = compileRegex False "%rowtype\\b"
regex_'25type'5cb = compileRegex False "%type\\b"
regex_rem'5cb = compileRegex False "rem\\b"
regex_'2f'24 = compileRegex False "/$"
regex_'40'40'3f'5b'5e'40_'5ct'5cr'5cn'5d = compileRegex False "@@?[^@ \\t\\r\\n]"

parseRules ("SQL (PostgreSQL)","Normal") =
  (((pString False "CREATE FUNCTION" >>= withAttribute KeywordTok) >>~ pushContext ("SQL (PostgreSQL)","CreateFunction"))
   <|>
   ((pKeyword " \n\t(),;[]{}\\" list_keywords >>= withAttribute KeywordTok))
   <|>
   ((pKeyword " \n\t(),;[]{}\\" list_operators >>= withAttribute NormalTok))
   <|>
   ((pKeyword " \n\t(),;[]{}\\" list_functions >>= withAttribute FunctionTok))
   <|>
   ((pKeyword " \n\t(),;[]{}\\" list_types >>= withAttribute DataTypeTok))
   <|>
   ((pRegExpr regex_'25bulk'5fexceptions'5cb >>= withAttribute DataTypeTok))
   <|>
   ((pRegExpr regex_'25bulk'5frowcount'5cb >>= withAttribute DataTypeTok))
   <|>
   ((pRegExpr regex_'25found'5cb >>= withAttribute DataTypeTok))
   <|>
   ((pRegExpr regex_'25isopen'5cb >>= withAttribute DataTypeTok))
   <|>
   ((pRegExpr regex_'25notfound'5cb >>= withAttribute DataTypeTok))
   <|>
   ((pRegExpr regex_'25rowcount'5cb >>= withAttribute DataTypeTok))
   <|>
   ((pRegExpr regex_'25rowtype'5cb >>= withAttribute DataTypeTok))
   <|>
   ((pRegExpr regex_'25type'5cb >>= withAttribute DataTypeTok))
   <|>
   ((pFloat >>= withAttribute FloatTok))
   <|>
   ((pInt >>= withAttribute DecValTok))
   <|>
   ((pDetectChar False '\'' >>= withAttribute StringTok) >>~ pushContext ("SQL (PostgreSQL)","String"))
   <|>
   ((pDetectChar False '#' >>= withAttribute CommentTok) >>~ pushContext ("SQL (PostgreSQL)","SingleLineComment"))
   <|>
   ((pDetect2Chars False '-' '-' >>= withAttribute CommentTok) >>~ pushContext ("SQL (PostgreSQL)","SingleLineComment"))
   <|>
   ((pDetect2Chars False '/' '*' >>= withAttribute CommentTok) >>~ pushContext ("SQL (PostgreSQL)","MultiLineComment"))
   <|>
   ((pColumn 0 >> pRegExpr regex_rem'5cb >>= withAttribute CommentTok) >>~ pushContext ("SQL (PostgreSQL)","SingleLineComment"))
   <|>
   ((pDetectChar False '"' >>= withAttribute CommentTok) >>~ pushContext ("SQL (PostgreSQL)","Identifier"))
   <|>
   ((pAnyChar ":&" >>= withAttribute CharTok))
   <|>
   ((pColumn 0 >> pRegExpr regex_'2f'24 >>= withAttribute CharTok))
   <|>
   ((pColumn 0 >> pRegExpr regex_'40'40'3f'5b'5e'40_'5ct'5cr'5cn'5d >>= withAttribute OtherTok) >>~ pushContext ("SQL (PostgreSQL)","Preprocessor"))
   <|>
   ((pRegExprDynamic "\\$([^\\$\\n\\r]*)\\$" >>= withAttribute NormalTok) >>~ pushContext ("SQL (PostgreSQL)","MultiLineString"))
   <|>
   (currentContext >>= \x -> guard (x == ("SQL (PostgreSQL)","Normal")) >> pDefault >>= withAttribute NormalTok))

parseRules ("SQL (PostgreSQL)","CreateFunction") =
  (((pRegExprDynamic "\\$([^\\$\\n\\r]*)\\$" >>= withAttribute FunctionTok) >>~ pushContext ("SQL (PostgreSQL)","FunctionBody"))
   <|>
   ((parseRules ("SQL (PostgreSQL)","Normal")))
   <|>
   (currentContext >>= \x -> guard (x == ("SQL (PostgreSQL)","CreateFunction")) >> pDefault >>= withAttribute NormalTok))

parseRules ("SQL (PostgreSQL)","FunctionBody") =
  (((pRegExprDynamic "\\$%1\\$" >>= withAttribute FunctionTok) >>~ (popContext >> popContext))
   <|>
   ((parseRules ("SQL (PostgreSQL)","Normal")))
   <|>
   (currentContext >>= \x -> guard (x == ("SQL (PostgreSQL)","FunctionBody")) >> pDefault >>= withAttribute NormalTok))

parseRules ("SQL (PostgreSQL)","MultiLineString") =
  (((pRegExprDynamic "\\$%1\\$" >>= withAttribute NormalTok) >>~ (popContext))
   <|>
   (currentContext >>= \x -> guard (x == ("SQL (PostgreSQL)","MultiLineString")) >> pDefault >>= withAttribute StringTok))

parseRules ("SQL (PostgreSQL)","String") =
  (((pLineContinue >>= withAttribute StringTok) >>~ (popContext))
   <|>
   ((pHlCStringChar >>= withAttribute CharTok))
   <|>
   ((pDetectChar False '&' >>= withAttribute CharTok))
   <|>
   ((pDetectChar False '\'' >>= withAttribute StringTok) >>~ (popContext))
   <|>
   (currentContext >>= \x -> guard (x == ("SQL (PostgreSQL)","String")) >> pDefault >>= withAttribute StringTok))

parseRules ("SQL (PostgreSQL)","SingleLineComment") =
  (currentContext >>= \x -> guard (x == ("SQL (PostgreSQL)","SingleLineComment")) >> pDefault >>= withAttribute CommentTok)

parseRules ("SQL (PostgreSQL)","MultiLineComment") =
  (((pLineContinue >>= withAttribute CommentTok) >>~ (popContext))
   <|>
   ((pDetect2Chars False '*' '/' >>= withAttribute CommentTok) >>~ (popContext))
   <|>
   (currentContext >>= \x -> guard (x == ("SQL (PostgreSQL)","MultiLineComment")) >> pDefault >>= withAttribute CommentTok))

parseRules ("SQL (PostgreSQL)","Identifier") =
  (((pDetectChar False '"' >>= withAttribute OtherTok) >>~ (popContext))
   <|>
   (currentContext >>= \x -> guard (x == ("SQL (PostgreSQL)","Identifier")) >> pDefault >>= withAttribute OtherTok))

parseRules ("SQL (PostgreSQL)","Preprocessor") =
  (currentContext >>= \x -> guard (x == ("SQL (PostgreSQL)","Preprocessor")) >> pDefault >>= withAttribute OtherTok)


parseRules x = parseRules ("SQL (PostgreSQL)","Normal") <|> fail ("Unknown context" ++ show x)
