{- This module was generated from data in the Kate syntax
   highlighting file sql.xml, version 1.17, by Yury Lebedev (yurylebedev@mail.ru) -}

module Text.Highlighting.Kate.Syntax.Sql
          (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"

-- | 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","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","Normal") -> return ()
      ("SQL","String literal") -> return ()
      ("SQL","Singleline PL/SQL-style comment") -> (popContext) >> pEndLine
      ("SQL","Multiline C-style comment") -> return ()
      ("SQL","SQL*Plus remark directive") -> (popContext) >> pEndLine
      ("SQL","User-defined identifier") -> (popContext) >> pEndLine
      ("SQL","SQL*Plus directive to include file") -> (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 $ "access account add admin administer advise after agent all allocate all_rows alter analyze ancillary and any archive archivelog as asc assertion associate at attribute attributes audit authenticated authid authorization autoallocate autoextend automatic backup become before begin behalf between binding bitmap block block_range body both bound break broadcast btitle buffer_pool build bulk by cache cache_instances call cancel cascade case category chained change check checkpoint child choose chunk class clear clone close close_cached_open_cursors cluster coalesce column columns column_value comment commit committed compatibility compile complete composite_limit compress compute connect connect_time consider consistent constant constraint constraints container contents context continue controlfile copy cost cpu_per_call cpu_per_session create create_stored_outlines cross cube current cursor cycle dangling data database datafile datafiles dba ddl deallocate debug declare default deferrable deferred definer degree delete demand desc determines dictionary dimension directory disable disassociate disconnect diskgroup dismount distinct distributed domain drop dynamic each else elsif empty enable end enforce entry escape estimate events except exception exceptions exchange excluding exclusive exec execute exists expire explain explosion extends extent extents externally failed_login_attempts false fast file filter first_rows flagger flashback flush following for force foreign freelist freelists fresh from full function functions generated global globally global_name grant group groups hash hashkeys having header heap hierarchy hour id identified identifier idgenerators idle_time if immediate in including increment incremental index indexed indexes indextype indextypes indicator initial initialized initially initrans inner insert instance instances instead intermediate intersect into invalidate is isolation isolation_level java join keep key kill label layer leading left less level library like limit link list local locator lock locked logfile logging logical_reads_per_call logical_reads_per_session logoff logon loop manage managed management master materialized maxarchlogs maxdatafiles maxextents maxinstances maxlogfiles maxloghistory maxlogmembers maxsize maxtrans maxvalue member merge method minextents minimize minimum minus minute minvalue mode modify monitoring mount move movement mts_dispatchers multiset named natural needed nested nested_table_id network never new next nls_calendar nls_characterset nls_comp nls_currency nls_date_format nls_date_language nls_iso_currency nls_lang nls_language nls_numeric_characters nls_sort nls_special_chars nls_territory no noarchivelog noaudit nocache nocompress nocycle noforce nologging nomaxvalue nominimize nominvalue nomonitoring none noorder nooverride noparallel norely noresetlogs noreverse normal nosegment nosort not nothing novalidate nowait null nulls objno objno_reuse of off offline oid oidindex old on online only opcode open operator optimal optimizer_goal option or order organization out outer outline over overflow overlaps own package packages parallel parameters parent partition partitions partition_hash partition_range password password_grace_time password_life_time password_lock_time password_reuse_max password_reuse_time password_verify_function pctfree pctincrease pctthreshold pctused pctversion percent permanent plan plsql_debug post_transaction prebuilt preceding prepare present preserve previous primary prior private private_sga privilege privileges procedure profile public purge query queue quota random range rba read reads rebuild records_per_block recover recoverable recovery recycle reduced references referencing refresh rely rename replace reset resetlogs resize resolve resolver resource restrict restricted resume return returning reuse reverse revoke rewrite right role roles rollback rollup row rownum rows rule sample savepoint scan scan_instances schema scn scope sd_all sd_inhibit sd_show segment seg_block seg_file select selectivity sequence serializable servererror session sessions_per_user session_cached_cursors set share shared shared_pool shrink shutdown singletask size skip skip_unusable_indexes snapshot some sort source specification split sql_trace standby start startup statement_id static statistics stop storage store structure submultiset subpartition subpartitions successful summary supplemental suspend switch synonym sysdba sysoper system sys_op_bitvec sys_op_enforce_not_null$ sys_op_noexpand sys_op_ntcimg$ table tables tablespace tablespace_no tabno tempfile temporary than the then thread through timeout timezone_hour timezone_minute time_zone to toplevel trace tracing trailing transaction transitional trigger triggers true truncate type types unarchived unbound unbounded undo uniform union unique unlimited unlock unrecoverable until unusable unused updatable update upd_indexes uppper usage use user_defined use_stored_outlines using validate validation values view when whenever where while with without work write"
list_operators = Set.fromList $ words $ "+ - * / || = != <> < <= > >= ~= ^= := => ** .."
list_functions = Set.fromList $ words $ "abs acos add_months ascii asciistr asin atan atan2 avg bfilename bin_to_num bitand cardinality cast ceil chartorowid chr coalesce collect compose concat convert corr corr_k corr_s cos cosh count covar_pop covar_samp cume_dist current_date current_timestamp cv dbtimezone decode decompose dense_rank depth deref dump empty_blob empty_clob existsnode exp extract extractvalue first first_value floor from_tz greatest group_id grouping grouping_id hextoraw initcap instr instrb lag last last_day last_value lead least length lengthb ln lnnvl localtimestamp log lower lpad ltrim make_ref max median min mod months_between nanvl nchr new_time next_day nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_upper nlssort ntile nullif numtodsinterval numtoyminterval nvl nvl2 ora_hash ora_rowscn percent_rank percentile_cont percentile_disc power powermultiset powermultiset_by_cardinality presentnnv presentv rank ratio_to_report rawtohex rawtonhex ref reftohex regexp_instr regexp_like regexp_replace regexp_substr regr_slope regr_intercept regr_count regr_r2 regr_avgx regr_avgy regr_sxx regr_syy regr_sxy remainder round row_number rowidtochar rowidtonchar rpad rtrim scn_to_timestamp sessiontimezone sign sin sinh soundex sqrt stats_binomial_test stats_crosstab stats_f_test stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_one stats_t_test_paired stats_t_test_indep stats_t_test_indepu stats_wsr_test stddev stddev_pop stddev_samp substr substrb sum sys_connect_by_path sys_context sys_dburigen sys_extract_utc sys_guid sys_typeid sys_xmlagg sys_xmlgen sysdate systimestamp tan tanh timestamp_to_scn to_binary_double to_binary_float to_char to_clob to_date to_dsinterval to_lob to_multi_byte to_nchar to_nclob to_number to_single_byte to_timestamp to_timestamp_tz to_yminterval translate treat trim trunc tz_offset uid unistr updatexml upper user userenv value var_pop var_samp variance vsize width_bucket xmlagg xmlcolattval xmlconcat xmlelement xmlforest xmlsequence xmltransform"
list_types = Set.fromList $ words $ "anydata anydataset anytype array bfile binary_double binary_float binary_integer blob boolean cfile char character clob date day dburitype dec decimal double float flob httpuritype int integer interval lob long mlslabel month national nchar nclob number numeric nvarchar object pls_integer precision raw real record rowid second single smallint time timestamp urifactorytype uritype urowid varchar varchar2 varray varying xmltype year zone"

regex_'25'28'3f'3abulk'5f'28'3f'3aexceptions'7crowcount'29'7cfound'7cisopen'7cnotfound'7crowcount'7crowtype'7ctype'29'5cb = compileRegex False "%(?:bulk_(?:exceptions|rowcount)|found|isopen|notfound|rowcount|rowtype|type)\\b"
regex_rem'5cb = compileRegex False "rem\\b"
regex_'28'3a'7c'26'26'3f'29'5cw'2b = compileRegex False "(:|&&?)\\w+"
regex_'2f'24 = compileRegex False "/$"
regex_'40'40'3f'5b'5e'40_'5ct'5cr'5cn'5d = compileRegex False "@@?[^@ \\t\\r\\n]"
regex_'26'26'3f'5cw'2b = compileRegex False "&&?\\w+"

parseRules ("SQL","Normal") =
  (((pDetectSpaces >>= withAttribute NormalTok))
   <|>
   ((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))
   <|>
   ((pDetectIdentifier >>= withAttribute NormalTok))
   <|>
   ((pRegExpr regex_'25'28'3f'3abulk'5f'28'3f'3aexceptions'7crowcount'29'7cfound'7cisopen'7cnotfound'7crowcount'7crowtype'7ctype'29'5cb >>= withAttribute DataTypeTok))
   <|>
   ((pHlCHex >>= withAttribute BaseNTok))
   <|>
   ((pFloat >>= withAttribute FloatTok))
   <|>
   ((pInt >>= withAttribute DecValTok))
   <|>
   ((pDetectChar False '\'' >>= withAttribute StringTok) >>~ pushContext ("SQL","String literal"))
   <|>
   ((pDetect2Chars False '-' '-' >>= withAttribute CommentTok) >>~ pushContext ("SQL","Singleline PL/SQL-style comment"))
   <|>
   ((pDetect2Chars False '/' '*' >>= withAttribute CommentTok) >>~ pushContext ("SQL","Multiline C-style comment"))
   <|>
   ((pColumn 0 >> pRegExpr regex_rem'5cb >>= withAttribute CommentTok) >>~ pushContext ("SQL","SQL*Plus remark directive"))
   <|>
   ((pDetectChar False '"' >>= withAttribute OtherTok) >>~ pushContext ("SQL","User-defined identifier"))
   <|>
   ((pRegExpr regex_'28'3a'7c'26'26'3f'29'5cw'2b >>= 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","SQL*Plus directive to include file"))
   <|>
   (currentContext >>= \x -> guard (x == ("SQL","Normal")) >> pDefault >>= withAttribute NormalTok))

parseRules ("SQL","String literal") =
  (((pDetect2Chars False '\\' '\'' >>= withAttribute StringTok) >>~ (popContext))
   <|>
   ((pHlCStringChar >>= withAttribute CharTok))
   <|>
   ((pRegExpr regex_'26'26'3f'5cw'2b >>= withAttribute CharTok))
   <|>
   ((pDetect2Chars False '\'' '\'' >>= withAttribute CharTok))
   <|>
   ((pDetectChar False '\'' >>= withAttribute StringTok) >>~ (popContext))
   <|>
   (currentContext >>= \x -> guard (x == ("SQL","String literal")) >> pDefault >>= withAttribute StringTok))

parseRules ("SQL","Singleline PL/SQL-style comment") =
  (currentContext >>= \x -> guard (x == ("SQL","Singleline PL/SQL-style comment")) >> pDefault >>= withAttribute CommentTok)

parseRules ("SQL","Multiline C-style comment") =
  (((pDetect2Chars False '*' '/' >>= withAttribute CommentTok) >>~ (popContext))
   <|>
   (currentContext >>= \x -> guard (x == ("SQL","Multiline C-style comment")) >> pDefault >>= withAttribute CommentTok))

parseRules ("SQL","SQL*Plus remark directive") =
  (currentContext >>= \x -> guard (x == ("SQL","SQL*Plus remark directive")) >> pDefault >>= withAttribute CommentTok)

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

parseRules ("SQL","SQL*Plus directive to include file") =
  (currentContext >>= \x -> guard (x == ("SQL","SQL*Plus directive to include file")) >> pDefault >>= withAttribute OtherTok)


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