# ***** 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 Perl

family ssl
sublanguage Perl

start_style SSL_DEFAULT
end_style SSL_VARIABLE

keyword_style SSL_IDENTIFIER => SSL_WORD
keywords ["abs",
#{{
"accept", "alarm", "and", "atan2", "BEGIN", "bind", "binmode", "bless",
"caller", "chdir", "chmod", "chomp", "chop", "chown", "chr", "chroot", "close",
"closedir", "cmp", "connect", "continue", "cos", "crypt", "DATA", "dbmclose",
"dbmopen", "define", "defined", "delete", "die", "do", "dump", "each", "else",
"elsif", "END", "endgrent", "endhostent", "endnetent", "endprotoent",
"endpwent", "endservent", "eof", "eq", "eval", "exec", "exists", "exit", "exp",
"fcntl", "fileno", "flock", "for", "foreach", "fork", "format", "formline",
"ge", "getc", "getgrent", "getgrgid", "getgrnam", "gethostbyaddr",
"gethostbyname", "gethostent", "getlogin", "getnetbyaddr", "getnetbyname",
"getnetent", "getpeername", "getpgrp", "getppid", "getpriority",
"getprotobyname", "getprotobynumber", "getprotoent", "getpwent", "getpwnam",
"getpwuid", "getservbyname", "getservbyport", "getservent", "getsockname",
"getsockopt", "glob", "gmtime", "goto", "grep", "gt", "hex", "if", "import",
"include", "index", "int", "ioctl", "join", "keys", "kill", "last", "lc",
"lcfirst", "le", "length", "link", "listen", "local", "localtime", "lock",
"log", "lstat", "lt", "m", "map", "mkdir", "msgctl", "msgget", "msgrcv",
"msgsnd", "my", "ne", "new", "next", "no", "not", "oct", "open", "opendir",
"or", "ord", "our", "pack", "package", "pipe", "pop", "pos", "print", "printf",
"prototype", "push", "q", "qq", "qr", "qx", "qw", "quotemeta", "rand", "read",
"readdir", "readline", "readlink", "readpipe", "recv", "redo", "ref", "rename",
"require", "reset", "return", "reverse", "rewinddir", "rindex", "rmdir", "s",
"scalar", "seek", "seekdir", "select", "semctl", "semget", "semop", "send",
"setgrent", "sethostent", "setnetent", "setpgrp", "setpriority", "setprotoent",
"setpwent", "setservent", "setsockopt", "shift", "shmctl", "shmget", "shmread",
"shmwrite", "shutdown", "sin", "sleep", "socket", "socketpair", "sort",
"splice", "split", "sprintf", "sqrt", "srand", "stat", "study", "sub", "substr",
"symlink", "syscall", "sysopen", "sysread", "sysseek", "system", "syswrite",
"tell" "telldir", "tie", "tied", "time", "times", "tr", "truncate", "uc",
"ucfirst", "umask", "undef", "unless", "unlink", "unpack", "unshift", "untie",
"until", "use", "utime", "values", "vec", "wait", "waitpid", "wantarray",
"warn", "while", "write", "xor", "y" ]
#}}

# Some info on the styles we're using here

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

initial IN_SSL_DEFAULT
state IN_SSL_DEFAULT:

/#.*/ : paint(upto, SSL_DEFAULT),  => IN_SSL_COMMENT_1
/^=[$NMSTART]/ : paint(upto, SSL_DEFAULT), => IN_SSL_COMMENT_2
/[$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
/0x[0-9a-fA-F_]*/ : paint(upto, SSL_DEFAULT), paint(include, SSL_NUMBER)
/0b[01_]*/ : 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
/\.(?=\d)/ : paint(upto, SSL_DEFAULT), => IN_SSL_NUMBER_2

# In Perl two things can precede names and turn off their keywordness
/::(?=[$NMSTART])/ : paint(upto, SSL_DEFAULT), paint(include, SSL_OPERATOR), \
=> IN_SSL_NON_KEYWORD_IDENTIFIER_1
/->(?=\s*[$NMSTART])/ : paint(upto, SSL_DEFAULT), paint(include, SSL_OPERATOR), \
=> IN_SSL_NON_KEYWORD_IDENTIFIER_1

'$' : paint(upto, SSL_DEFAULT), => IN_SSL_FINISH_DOLLAR
'@' : paint(upto, SSL_DEFAULT), => IN_SSL_FINISH_AT_SIGN
'%' : paint(upto, SSL_DEFAULT), paint(include, SSL_OPERATOR) => IN_SSL_FINISH_PERCENT

/(?:m|qr)([\{\[\(\<])/ : paint(upto, SSL_DEFAULT), set_opposite_delimiter(1), => IN_SSL_REGEX1_TARGET
/(?:m|qr)([^\w\d])/ : paint(upto, SSL_DEFAULT), set_delimiter(1), => IN_SSL_REGEX1_TARGET
'/' token_check : paint(upto, SSL_DEFAULT) => IN_SSL_REGEX_1

/s([\{\[\(\<])/ : paint(upto, SSL_DEFAULT), set_opposite_delimiter(1), => IN_SSL_REGEX2_TARGET1_OPPOSITE_1
/s([^\w\d])/ : paint(upto, SSL_DEFAULT), set_delimiter(1), => IN_SSL_REGEX2_TARGET1_SAME

/q[qwx]?([\{\[\(\<])/ : paint(upto, SSL_DEFAULT), set_opposite_delimiter(1), => IN_SSL_QSTRING
/q[qwx]?([^\w\d])/ : paint(upto, SSL_DEFAULT), set_delimiter(1), => IN_SSL_QSTRING

'=~' : paint(upto, SSL_DEFAULT), paint(include, SSL_OPERATOR) => IN_SSL_PRE_REGEX_1

# We set up a microstate for recognizing barewords in function calls
# and hash assignments
/[\(,\{]/ : paint(upto, SSL_DEFAULT), paint(include, SSL_OPERATOR) => IN_SSL_DEFAULT_HANDLE_ARROW_BAREWORDS_1

/$VARNAME/: paint(upto, SSL_DEFAULT), paint(include, SSL_IDENTIFIER)

'->' : paint(upto, SSL_DEFAULT), paint(include, SSL_OPERATOR), => IN_SSL_BRACE_IS_INDEXER
/[$OP]/ : paint(upto, SSL_DEFAULT), paint(include, SSL_OPERATOR)

################ Allowing for barewords ################

state IN_SSL_DEFAULT_HANDLE_ARROW_BAREWORDS_1:
/[$WS]/ #stay
/[-+]?$VARNAME(?=\s*=>)/ : paint(upto, SSL_DEFAULT), paint(include, SSL_STRING) => IN_SSL_DEFAULT
/./ : paint(upto, SSL_DEFAULT), redo, => IN_SSL_DEFAULT

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

state IN_SSL_COMMENT_1 : 
/\r/ : paint(include, SSL_COMMENT) => IN_SSL_DEFAULT
/$/ : paint(include, SSL_COMMENT), => IN_SSL_DEFAULT

state IN_SSL_COMMENT_2:
/^=cut\r?$/ : paint(include, SSL_COMMENT), => IN_SSL_DEFAULT

#{{
################ Strings ################

#XXX Add quoted delimiters, including a rules block, for ruby and perl

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

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

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

# qr/.../ goes to regex
state IN_SSL_QSTRING:
delimiter: paint(include, SSL_STRING), => IN_SSL_DEFAULT
/\\./ #stay

################ 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

################ Names ################
#}}

state IN_SSL_FINISH_DOLLAR:
/\d+/ : paint(upto, SSL_VARIABLE), => IN_SSL_DEFAULT
'::' : => IN_SSL_VARIABLE_1
/\$+(?=#?[$NMSTART]|::)/ : #stay
/[-&`'+*.\/|,\\";%=~\^:?!@$<>()\[\]]/ : paint(upto, SSL_VARIABLE), => IN_SSL_DEFAULT
/\^[A-Z]/ : paint(upto, SSL_VARIABLE), => IN_SSL_DEFAULT
/\{\^[A-Z_]+/ : => IN_SSL_FINISH_DOLLAR_EXTENDED
/#?[$NMSTART]/ : => IN_SSL_VARIABLE_1
/./ : redo, paint(upto, SSL_DEFAULT), => IN_SSL_DEFAULT

state IN_SSL_FINISH_DOLLAR_EXTENDED:
'}' : paint(upto, SSL_VARIABLE), => IN_SSL_DEFAULT
/./ : redo, paint(upto, SSL_VARIABLE), => IN_SSL_DEFAULT

state IN_SSL_FINISH_AT_SIGN:
/[-+]/ : paint(upto, SSL_VARIABLE), => IN_SSL_DEFAULT
'::' : => IN_SSL_VARIABLE_1
/[$NMSTART]/ : => IN_SSL_VARIABLE_1
/\$+(?=[$NMSTART]|::)/ : #stay
/./ : redo, paint(upto, SSL_DEFAULT), => IN_SSL_DEFAULT

state IN_SSL_FINISH_PERCENT:
'::' : => IN_SSL_VARIABLE_1
/[_!]/ : paint(upto, SSL_VARIABLE), => IN_SSL_DEFAULT
/^[H]/ : paint(upto, SSL_VARIABLE), => IN_SSL_DEFAULT
/[$NMSTART]/ : => IN_SSL_VARIABLE_1
/\$+(?=[$NMSTART]|::)/ : #stay
/./ : redo, paint(upto, SSL_OPERATOR), => IN_SSL_DEFAULT

state IN_SSL_VARIABLE_1:
/[$CS]+/ : #stay, check for one of those ruby prefix things
/::/ : paint(upto, SSL_VARIABLE), paint(include, SSL_OPERATOR) #stay
'{' : paint(upto, SSL_VARIABLE), paint(include, SSL_OPERATOR), => IN_SSL_INDEXER_1
/[$WS]/: paint(upto, SSL_VARIABLE) => IN_SSL_BRACE_IS_INDEXER
/./ : redo, paint(upto, SSL_VARIABLE), => IN_SSL_DEFAULT

state IN_SSL_IDENTIFIER_1:
/[$CS]+/ #stay, check for one of those ruby prefix things
/::(?=[$NMSTART])/ : paint(upto, SSL_IDENTIFIER), paint(include, SSL_OPERATOR), \
=> IN_SSL_NON_KEYWORD_IDENTIFIER_1
'::' : paint(upto, SSL_IDENTIFIER), paint(include, SSL_OPERATOR), => IN_SSL_DEFAULT
'{' : paint(upto, SSL_IDENTIFIER), paint(include, SSL_OPERATOR), no_keyword, => IN_SSL_INDEXER_1
/[$WS]/ : paint(upto, SSL_VARIABLE), => IN_SSL_NON_KEYWORD_IDENTIFIER_2
/./ : redo, paint(upto, SSL_VARIABLE), => IN_SSL_DEFAULT

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

state IN_SSL_NON_KEYWORD_IDENTIFIER_1:
# Match anything since we know how we got here.  Don't color single-char keywords
/./ : no_keyword, paint(include, SSL_IDENTIFIER), => IN_SSL_NON_KEYWORD_IDENTIFIER_2

state IN_SSL_NON_KEYWORD_IDENTIFIER_2:
/[$WS]/  : no_keyword, paint(upto, SSL_IDENTIFIER), => IN_SSL_NON_KEYWORD_IDENTIFIER_3
'{' : paint(upto, SSL_IDENTIFIER), paint(include, SSL_OPERATOR), no_keyword, => IN_SSL_INDEXER_1
/[^$CS]/ : paint(upto, SSL_IDENTIFIER), redo, no_keyword, => IN_SSL_DEFAULT

state IN_SSL_NON_KEYWORD_IDENTIFIER_3:
/[$WS]/ : #stay
'{' : paint(upto, SSL_DEFAULT), paint(include, SSL_OPERATOR), => IN_SSL_INDEXER_1
/./ : paint(upto, SSL_DEFAULT), redo, => IN_SSL_DEFAULT

################ Moved here on -> ################

state IN_SSL_BRACE_IS_INDEXER:
/[$WS]+/ : #stay
'{' : paint(upto, SSL_DEFAULT), paint(include, SSL_OPERATOR), => IN_SSL_INDEXER_1
/./ : paint(upto, SSL_DEFAULT), redo, => IN_SSL_DEFAULT


state IN_SSL_INDEXER_1:
/\s+/ : #stay
/[$NMSTART]/ : paint(upto, SSL_DEFAULT), => IN_SSL_INDEXER_2
/./ : paint(upto, SSL_DEFAULT), redo, => IN_SSL_DEFAULT

#Bareword
state IN_SSL_INDEXER_2:
/[$CS]+/ : #stay, check for one of those ruby prefix things
/ *(?=\})/ : paint(upto, SSL_STRING), paint(include, SSL_DEFAULT), => IN_SSL_DEFAULT
/./ : paint(upto, SSL_IDENTIFIER), redo, => IN_SSL_DEFAULT

################ Regexes ################

state IN_SSL_PRE_REGEX_1:
/[$WS]+/  : #stay
/m?([\{\[\(\<])/ : paint(upto, SSL_DEFAULT), set_opposite_delimiter(1), => IN_SSL_REGEX1_TARGET
/m?([^\w\d])/ : paint(upto, SSL_DEFAULT), set_delimiter(1), => IN_SSL_REGEX1_TARGET

/s([\{\[\(\<])/ : paint(upto, SSL_DEFAULT), set_opposite_delimiter(1), => IN_SSL_REGEX2_TARGET1_OPPOSITE_1
/s([^\w\d])/ : paint(upto, SSL_DEFAULT), set_delimiter(1), => IN_SSL_REGEX2_TARGET1_SAME

/./ : paint(upto, SSL_DEFAULT), redo, => IN_SSL_DEFAULT

# Will be used for things like split(/.../, split /, etc etc
state IN_SSL_REGEX_1:
/\\./ : #stay
/\/[\w]*/ : paint(include, SSL_REGEX), => IN_SSL_DEFAULT
# Assume a # is in an x-type regex
/#[^\/]*$/ : paint(upto, SSL_REGEX), paint(include, SSL_COMMENT) # stay
/[\r\n]/ : #stay

# m{...}, m/.../, and second part of s*...*...*
state IN_SSL_REGEX1_TARGET:
delimiter: paint(include, SSL_REGEX), => IN_SSL_REGEX_POST
/\\./ #stay
# Assume a # is in an x-type regex, with hardwired slashes to get 90% cases.
/\#[^\/]*$/ : paint(upto, SSL_REGEX), paint(include, SSL_COMMENT) # stay

state IN_SSL_REGEX_POST:
/\w+/ : paint(include, SSL_REGEX), => IN_SSL_DEFAULT
// : => IN_SSL_DEFAULT

state IN_SSL_REGEX2_TARGET1_OPPOSITE_1:
/\\./ : #stay
delimiter: paint(include, SSL_REGEX), => IN_SSL_REGEX2_TARGET1_OPPOSITE_2
/\z/ : paint(upto, SSL_REGEX)

# s[...]/.../
state IN_SSL_REGEX2_TARGET1_OPPOSITE_2:
/\\./ : #stay
/[$WS]/ : #stay -- assume we're in {...} [ ... ]x
/\#.*$/ paint(upto, SSL_DEFAULT), paint(include, SSL_COMMENT) #stay
/([\{\[\(\<])/ : paint(upto, SSL_DEFAULT), set_opposite_delimiter(1), => IN_SSL_REGEX1_TARGET
/([^\w\d])/ : paint(upto, SSL_DEFAULT), set_delimiter(1), => IN_SSL_REGEX1_TARGET
/\z/ : paint(upto, SSL_DEFAULT)

# s/.../.../
state IN_SSL_REGEX2_TARGET1_SAME
/\\./ : #stay
delimiter: keep_delimiter, => IN_SSL_REGEX1_TARGET
/\z/ : paint(upto, SSL_REGEX)

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

# token-checking on '/' as start of a regex
token_check:
SSL_OPERATOR: accept ['(', '{', '[', ';', '..', '...']
SSL_WORD: accept [split, grep, map, print while, if unless until and or not xor]
SSL_DEFAULT: skip all
SSL_COMMENT: skip all

################ Fold Info ################

fold "{" SSL_OPERATOR +
fold "}" SSL_OPERATOR -
fold "[" SSL_OPERATOR +
fold "]" SSL_OPERATOR -
fold "(" SSL_OPERATOR +
fold ")" SSL_OPERATOR -

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

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

