# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
# 
# The contents of this file are subject to the Mozilla Public License
# Version 1.1 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
# 
# The Original Code is Komodo code.
# 
# The Initial Developer of the Original Code is ActiveState Software Inc.
# Portions created by ActiveState Software Inc are Copyright (C) 2000-2007
# ActiveState Software Inc. All Rights Reserved.
# 
# Contributor(s):
#   ActiveState Software Inc
# 
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
# 
# ***** END LICENSE BLOCK *****

# Lexer description for PHP

# First we need to tell the lexer a bit about this language

family ssl # server-side language
sublanguage PHP

# We have to specify the min and max styles we'll be referring to

start_style SSL_DEFAULT
end_style SSL_VARIABLE

# If the language has keywords, specify which style needs to be transformed

keyword_style SSL_IDENTIFIER => SSL_WORD

# From Komodo's koPHPLanguage.py
# From http://www.php.net/manual/en/language.types.boolean.php
# recognition of 'true' and 'false' is case-insensitive!

keywords [
                # http://www.php.net/manual/en/reserved.keywords.php
                # new to php 5.3
                "__dir__", "__namespace__",
                "e_deprecated", "e_user_deprecated", "php_maxpathlen",
                "goto", "namespace",
                # new to php5
                "public", "private", "protected", "final",
                "abstract", "interface", "implements",
                "try", "catch", "throw", "instanceof",
                # existed in php4
                "define", "true", "false", 
                "int", "integer", "real", "double",
                "float", "string",  "object", "bool", "boolean",
                "this", "virtual", "parent", "null",
                # general keywords
                "and", "or", "xor", "__file__", "__line__",
                "array", "as", "break", "case", "cfunction",
                "class", "const", "continue", "declare"
                "default", "die", "do", "echo", "else",
                "elseif", "empty", "enddeclare", "endfor", "endforeach",
                "endif", "endswitch", "endwhile", "eval", "exit",
                "extends", "for", "foreach", "function", "global",
                "if", "include", "include_once", "isset", "list",
                "new", "old_function", "print", "require", "require_once",
                "return", "static", "switch", "unset", "use",
                "var", "while", "_function_", "_class_",
                # http://www.php.net/manual/en/reserved.constants.php
                "php_version",
                "php_os",
                "default_include_path",
                "pear_install_dir",
                "pear_extension_dir",
                "php_extension_dir",
                "php_bindir",
                "php_libdir",
                "php_datadir",
                "php_sysconfdir",
                "php_localstatedir",
                "php_config_file_path",
                "php_output_handler_start",
                "php_output_handler_cont",
                "php_output_handler_end",
                "e_error",
                "e_warning",
                "e_parse",
                "e_notice",
                "e_core_error",
                "e_core_warning",
                "e_compile_error",
                "e_compile_warning",
                "e_user_error",
                "e_user_warning",
                "e_user_notice",
                "e_all",
                "extr_overwrite",
                "extr_skip",
                "extr_prefix_same",
                "extr_prefix_all",
                "extr_prefix_invalid",
                "extr_prefix_if_exists",
                "extr_if_exists",
                "sort_asc",
                "sort_desc",
                "sort_regular",
                "sort_numeric",
                "sort_string",
                "case_lower",
                "case_upper",
                "count_normal",
                "count_recursive",
                "assert_active",
                "assert_callback",
                "assert_bail",
                "assert_warning",
                "assert_quiet_eval",
                "connection_aborted",
                "connection_normal",
                "connection_timeout",
                "ini_user",
                "ini_perdir",
                "ini_system",
                "ini_all",
                "m_e",
                "m_log2e",
                "m_log10e",
                "m_ln2",
                "m_ln10",
                "m_pi",
                "m_pi_2",
                "m_pi_4",
                "m_1_pi",
                "m_2_pi",
                "m_2_sqrtpi",
                "m_sqrt2",
                "m_sqrt1_2",
                "crypt_salt_length",
                "crypt_std_des",
                "crypt_ext_des",
                "crypt_md5",
                "crypt_blowfish",
                "directory_separator",
                "seek_set",
                "seek_cur",
                "seek_end",
                "lock_sh",
                "lock_ex",
                "lock_un",
                "lock_nb",
                "html_specialchars",
                "html_entities",
                "ent_compat",
                "ent_quotes",
                "ent_noquotes",
                "info_general",
                "info_credits",
                "info_configuration",
                "info_modules",
                "info_environment",
                "info_variables",
                "info_license",
                "info_all",
                "credits_group",
                "credits_general",
                "credits_sapi",
                "credits_modules",
                "credits_docs",
                "credits_fullpage",
                "credits_qa",
                "credits_all",
                "str_pad_left",
                "str_pad_right",
                "str_pad_both",
                "pathinfo_dirname",
                "pathinfo_basename",
                "pathinfo_extension",
                "char_max",
                "lc_ctype",
                "lc_numeric",
                "lc_time",
                "lc_collate",
                "lc_monetary",
                "lc_all",
                "lc_messages",
                "abday_1",
                "abday_2",
                "abday_3",
                "abday_4",
                "abday_5",
                "abday_6",
                "abday_7",
                "day_1",
                "day_2",
                "day_3",
                "day_4",
                "day_5",
                "day_6",
                "day_7",
                "abmon_1",
                "abmon_2",
                "abmon_3",
                "abmon_4",
                "abmon_5",
                "abmon_6",
                "abmon_7",
                "abmon_8",
                "abmon_9",
                "abmon_10",
                "abmon_11",
                "abmon_12",
                "mon_1",
                "mon_2",
                "mon_3",
                "mon_4",
                "mon_5",
                "mon_6",
                "mon_7",
                "mon_8",
                "mon_9",
                "mon_10",
                "mon_11",
                "mon_12",
                "am_str",
                "pm_str",
                "d_t_fmt",
                "d_fmt",
                "t_fmt",
                "t_fmt_ampm",
                "era",
                "era_year",
                "era_d_t_fmt",
                "era_d_fmt",
                "era_t_fmt",
                "alt_digits",
                "int_curr_symbol",
                "currency_symbol",
                "crncystr",
                "mon_decimal_point",
                "mon_thousands_sep",
                "mon_grouping",
                "positive_sign",
                "negative_sign",
                "int_frac_digits",
                "frac_digits",
                "p_cs_precedes",
                "p_sep_by_space",
                "n_cs_precedes",
                "n_sep_by_space",
                "p_sign_posn",
                "n_sign_posn",
                "decimal_point",
                "radixchar",
                "thousands_sep",
                "thousep",
                "grouping",
                "yesexpr",
                "noexpr",
                "yesstr",
                "nostr",
                "codeset",
                "log_emerg",
                "log_alert",
                "log_crit",
                "log_err",
                "log_warning",
                "log_notice",
                "log_info",
                "log_debug",
                "log_kern",
                "log_user",
                "log_mail",
                "log_daemon",
                "log_auth",
                "log_syslog",
                "log_lpr",
                "log_news",
                "log_uucp",
                "log_cron",
                "log_authpriv",
                "log_local0",
                "log_local1",
                "log_local2",
                "log_local3",
                "log_local4",
                "log_local5",
                "log_local6",
                "log_local7",
                "log_pid",
                "log_cons",
                "log_odelay",
                "log_ndelay",
                "log_nowait",
                "log_perror"
                ]


# Some info on the styles we're using here

pattern NMSTART = '_a-zA-Z\x80-\xff'   # inside cset
pattern NMCHAR = '$NMSTART\d'   # inside cset
pattern CS = '\w\d_\x80-\xff'   # inside cset
pattern WS = '\s\t\r\n'           # inside cset
pattern OP = '!\#%&\(\)\*\+,-\.\/:;<=>\?@\[\]\^\{\}~|\\'

initial IN_SSL_DEFAULT

state IN_SSL_DEFAULT:

# One-line comments end at either end-of-line or '?>'
# This is a hard-wired transition

/<\?php\b/ : #stay, we should have processed this during a transition point

'#' : paint(upto, SSL_DEFAULT),  => IN_SSL_COMMENT_1
'//' : paint(upto, SSL_DEFAULT),  => IN_SSL_COMMENT_1

'/*' : paint(upto, SSL_DEFAULT), => IN_SSL_COMMENT_2
/\$[$NMSTART][$CS]*/ : paint(upto, SSL_DEFAULT), paint(include, SSL_VARIABLE)

/[$WS]+/  : #stay

'"' : paint(upto, SSL_DEFAULT), => IN_SSL_DSTRING
'\'' : paint(upto, SSL_DEFAULT), => IN_SSL_SSTRING
'`' : paint(upto, SSL_DEFAULT), => IN_SSL_XSTRING

# Go process a number, try to do it in regexes
# octal and hex first
/0[Xx][0-9a-fA-F]+/ : paint(upto, SSL_DEFAULT), paint(include, SSL_NUMBER)
/[-+]?0[0-7]*/ : paint(upto, SSL_DEFAULT), paint(include, SSL_NUMBER)
/[1-9]/ : paint(upto, SSL_DEFAULT), => IN_SSL_NUMBER_1
/\.(?=[$NMSTART])/ : paint(upto, SSL_DEFAULT), paint(include, SSL_OPERATOR), \
=> IN_SSL_NON_KEYWORD_IDENTIFIER_1
/\.(?=\d)/ : paint(upto, SSL_DEFAULT), => IN_SSL_NUMBER_2

/[$NMSTART][$CS]*/ : paint(upto, SSL_DEFAULT), paint(include, SSL_IDENTIFIER)

# Now a bunch of operators
# Multi-char operators first

#XXX Support high-bit characters in delimiter strings.

/<<<(?=\s*[$NMSTART][$NMCHAR]*;?\r?$)/: paint(upto, SSL_DEFAULT), \
paint(include, SSL_OPERATOR), => IN_SSL_PRE_HEREDOC_1
/<<<(?=\s*"[$NMSTART][$NMCHAR]*";?\r?$)/: paint(upto, SSL_DEFAULT), \
paint(include, SSL_OPERATOR), => IN_SSL_PRE_HEREDOC_1
/<<<(?=\s*'[$NMSTART][$NMCHAR]*';?\r?$)/: paint(upto, SSL_DEFAULT), \
paint(include, SSL_OPERATOR), => IN_SSL_PRE_NOWDOC_1

/[$OP]/ : paint(upto, SSL_DEFAULT), redo, => IN_SSL_OP1


################ Here-doc handling ################

state IN_SSL_PRE_HEREDOC_1:
/"?([$NMCHAR]+)"?/ : paint(include, SSL_IDENTIFIER), set_delimiter(1)
';' : paint(include, SSL_OPERATOR)
/[\r\n]+/ : paint(include, SSL_DEFAULT), => IN_SSL_IN_HEREDOC_1
/\s+/ : paint(include, SSL_DEFAULT)

# When we're in a here-doc, if we find a line that starts with the
# current delimiter, check for end-of-line.  Otherwise look for interpolation
# on the current line, in state IN_SSL_IN_HEREDOC_2

# So we need to keep the delimiter alive, and then kill it if it's
# the only item on a line.

state IN_SSL_IN_HEREDOC_1:
delimiter : keep_delimiter, paint(upto, SSL_STRING), => IN_SSL_IN_FOUND_HEREDOC_1
/./ : redo, => IN_SSL_IN_HEREDOC_2
/\z/ : paint(upto, SSL_STRING)

state IN_SSL_IN_HEREDOC_2:
/\$[$NMSTART][$NMCHAR]*/: paint(upto, SSL_STRING), paint(include, SSL_VARIABLE) #stay
/$/ : => IN_SSL_IN_HEREDOC_1
/\z/ : paint(upto, SSL_STRING)

state IN_SSL_IN_FOUND_HEREDOC_1:
/;(?=[\r\n]*$)/ : no_keyword, paint(upto, SSL_IDENTIFIER), paint(include, SSL_OPERATOR) => IN_SSL_DEFAULT
/$/ : no_keyword, paint(upto, SSL_IDENTIFIER), => IN_SSL_DEFAULT
/[\r\n]/ : no_keyword, paint(upto, SSL_IDENTIFIER), => IN_SSL_DEFAULT
/./ : redo, => IN_SSL_IN_HEREDOC_2

################ Now-doc handling ################
# Now-docs are like here-docs, but don't interpolate variables
# Only difference: single-quotes surround the delimiter

state IN_SSL_PRE_NOWDOC_1:
/'([$NMCHAR]+)'/ : paint(include, SSL_IDENTIFIER), set_delimiter(1)
';' : paint(include, SSL_OPERATOR)
/[\r\n]+/ : paint(include, SSL_DEFAULT), => IN_SSL_IN_NOWDOC_1
/\s+/ : paint(include, SSL_DEFAULT)

# When we're in a here-doc, if we find a line that starts with the
# current delimiter, check for end-of-line.  Otherwise look for interpolation
# on the current line, in state IN_SSL_IN_NOWDOC_2

# So we need to keep the delimiter alive, and then kill it if it's
# the only item on a line.

state IN_SSL_IN_NOWDOC_1:
delimiter : keep_delimiter, paint(upto, SSL_STRING), => IN_SSL_IN_FOUND_NOWDOC_1
/.+/ : #stay
/\z/ : paint(upto, SSL_STRING)

state IN_SSL_IN_FOUND_NOWDOC_1:
/;(?=[\r\n]*$)/ : no_keyword, paint(upto, SSL_IDENTIFIER), paint(include, SSL_OPERATOR) => IN_SSL_DEFAULT
/$/ : no_keyword, paint(upto, SSL_IDENTIFIER), => IN_SSL_DEFAULT
/[\r\n]/ : no_keyword, paint(upto, SSL_IDENTIFIER), => IN_SSL_DEFAULT
/./ : redo, => IN_SSL_IN_NOWDOC_1

################ Non-keyword identifiers ################

state IN_SSL_NON_KEYWORD_IDENTIFIER_1:
/./ : no_keyword, paint(include, SSL_IDENTIFIER), => IN_SSL_NON_KEYWORD_IDENTIFIER_2

state IN_SSL_NON_KEYWORD_IDENTIFIER_2:
/[$CS]/ : #stay
/[^$CS]/ : paint(upto, SSL_IDENTIFIER), redo, no_keyword, => IN_SSL_DEFAULT

################ Comments ################

state IN_SSL_COMMENT_1 : 
'?>' : paint(upto, SSL_COMMENT), redo => IN_SSL_DEFAULT
/[\r\n]/ : paint(upto, SSL_COMMENT), => IN_SSL_DEFAULT

state IN_SSL_COMMENT_2 : 
'*/' : paint(include, SSL_COMMENTBLOCK), => IN_SSL_DEFAULT

################ Strings ################

# We need counting to handle ${...} expressions, like in Ruby

state IN_SSL_DSTRING:
/\$[$NMSTART][$NMCHAR]*/: paint(upto, SSL_STRING), paint(include, SSL_VARIABLE) #stay
/\$\{[$NMSTART][$NMCHAR]*\}/: paint(upto, SSL_STRING), paint(include, SSL_VARIABLE) #stay
'"' : paint(include, SSL_STRING), => IN_SSL_DEFAULT
/\\./ : #stay, Don't miscount backslash at end
/[\r\n]/ : #stay, php strings are multi-line
/\z/: paint(include, SSL_STRING)

state IN_SSL_SSTRING:
'\'' : paint(include, SSL_STRING), => IN_SSL_DEFAULT
/\\./ : #
/[\r\n]/ : #stay, php strings are multi-line
# Verify we create a \z

state IN_SSL_XSTRING:
'`' : paint(include, SSL_STRING), => IN_SSL_DEFAULT
/\\./ : #backslash-escape


################ Numbers ################

state IN_SSL_NUMBER_1 :
/$/ : paint(upto, SSL_NUMBER), => IN_SSL_DEFAULT
'.' : => IN_SSL_NUMBER_2
/[\d]/ : #stay
/[Ee][-+]?/ : => IN_SSL_NUMBER_3
/./ : paint(upto, SSL_NUMBER), redo, => IN_SSL_DEFAULT

state IN_SSL_NUMBER_2:
/$/ : paint(upto, SSL_NUMBER), => IN_SSL_DEFAULT
/[\d]/ : #stay
/[Ee][-+]?/ : => IN_SSL_NUMBER_3
'.' : paint(upto, SSL_NUMBER), paint(include, SSL_OPERATOR),  => IN_SSL_DEFAULT
/./ : paint(upto, SSL_NUMBER), redo, => IN_SSL_DEFAULT

state IN_SSL_NUMBER_3:
/$/ : paint(upto, SSL_NUMBER), => IN_SSL_DEFAULT
/[^\d]/ : paint(upto, SSL_NUMBER), redo, => IN_SSL_DEFAULT

################ Operators ################

# If we're here, we've painted the previous part, and 
# just need to figure out which operator we have, doing
# greedy left-to-right matching ('+++' parses as /++/, /+/)

state IN_SSL_OP1:
# Single-char operator -- all ops work as standalone chars

# Single-char operator -- all ops work as standalone chars
/[$OP](?:(?![$OP])|$)/ : paint(include, SSL_OPERATOR), => IN_SSL_DEFAULT
/==?=?/ : paint(include, SSL_OPERATOR), => IN_SSL_DEFAULT
/!=?=?/ : paint(include, SSL_OPERATOR), => IN_SSL_DEFAULT
/<<=?/	 : paint(include, SSL_OPERATOR), => IN_SSL_DEFAULT
/>>=?/	 : paint(include, SSL_OPERATOR), => IN_SSL_DEFAULT
/[-<>+\*\/\.%&|\^]=?/ : paint(include, SSL_OPERATOR), => IN_SSL_DEFAULT
/([-\+\&|])\1?/ : paint(include, SSL_OPERATOR), => IN_SSL_DEFAULT
# The fallback
/[$OP]/ : paint(include, SSL_OPERATOR), => IN_SSL_DEFAULT

################ End States ################

# PHP/CSS fold info


fold "<?" SSL_OPERATOR +
fold "?>" SSL_OPERATOR -

fold "{" SSL_OPERATOR +
fold "}" SSL_OPERATOR -

fold "{{{" SSL_COMMENT +
fold "}}}" SSL_COMMENT -

fold "{{{" SSL_COMMENTBLOCK +
fold "}}}" SSL_COMMENTBLOCK -
