# Main ECMAScript-262 definition
# 
# ***** 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 *****
# Author(s):
#   Eric Promislow <ericp@activestate.com>
#
# Used by JavaScript, ActionScript, and other JS-like languages

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

start_style CSL_DEFAULT
end_style CSL_REGEX

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

keyword_style CSL_IDENTIFIER => CSL_WORD

# Some info on the styles we're using here

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

# We need to do some processing to determine when a / in default state 
# starts a regex, and when it starts an RE
# Same with /<\w/ for e4x unquoted xml strings
# -- in fact, it's the same as for regexes, as both denote an object

initial IN_CSL_DEFAULT

state IN_CSL_DEFAULT:

# Just ignore these things -- they're here for ancient browsers

'<!--' : paint(upto, CSL_DEFAULT), paint(include, CSL_COMMENT)
'-->' : paint(upto, CSL_DEFAULT), paint(include, CSL_COMMENT)
'<![CDATA[' : paint(upto, CSL_DEFAULT), paint(include, CSL_COMMENT)
']]>' : paint(upto, CSL_DEFAULT), paint(include, CSL_COMMENT)

'/*' : paint(upto, CSL_DEFAULT), => IN_CSL_COMMENT_1

'//' : paint(upto, CSL_DEFAULT), => IN_CSL_COMMENT_LINE_1

/[$WS]+/  : #stay

# We have to lex numbers in states in case we reach EOF right after the
# "e" in a floating pt constant, for example

/0[Xx][0-9a-fA-F]+/ : paint(upto, CSL_DEFAULT), paint(include, CSL_NUMBER)
/[-+]?[0-9]/ : paint(upto, CSL_DEFAULT), => IN_CSL_NUMBER_1

# A "." can start a number only if it doesn't follow a
# name, many keywords, string, regex, number, or a few 
# closing operators.

/\.\d/ : paint(upto, CSL_DEFAULT), => IN_CSL_NUMBER_2
/[-+]\./ : paint(upto, CSL_DEFAULT), => IN_CSL_NUMBER_2

'"' : paint(upto, CSL_DEFAULT), => IN_CSL_DSTRING
'\'' : paint(upto, CSL_DEFAULT), => IN_CSL_SSTRING

# Conditional check to see if it's preferred
'/' token_check : paint(upto, CSL_DEFAULT), => IN_CSL_REGEX

# '<' if token_check  : paint(upto, CSL_DEFAULT), => IN_CSL_XML # E4X stuff

/$NAMESEQ/ : paint(upto, CSL_DEFAULT), paint(include, CSL_IDENTIFIER)

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

/[$OP]/ : paint(upto, CSL_DEFAULT), redo, => IN_CSL_OP1

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

state IN_CSL_COMMENT_1 : 
'*/' : paint(include, CSL_COMMENTBLOCK), => IN_CSL_DEFAULT

state IN_CSL_COMMENT_LINE_1:
/[\r\n]/ : paint(upto, CSL_COMMENT), => IN_CSL_DEFAULT

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

state IN_CSL_DSTRING:
'"' : paint(include, CSL_STRING), => IN_CSL_DEFAULT
/\\[\r\n]/ : paint(include, CSL_STRING), => IN_CSL_DSTRING_LINECONT
/\\./ : #stay, Don't miscount backslash at end
/$/ : paint(upto, CSL_STRING), => IN_CSL_DEFAULT
'\r' : paint(upto, CSL_STRING), => IN_CSL_DEFAULT

# Work around the single-line match limit.

state IN_CSL_DSTRING_LINECONT:
/\\[\r\n]/ : #stay
/\\./ : => IN_CSL_DSTRING
'"' : paint(include, CSL_STRING), => IN_CSL_DEFAULT
/./ : => IN_CSL_DSTRING
/^$/ : paint(upto, CSL_STRING), => IN_CSL_DEFAULT # End empty lines here

state IN_CSL_SSTRING:
'\'' : paint(include, CSL_STRING), => IN_CSL_DEFAULT
/\\[\r\n]/ : paint(include, CSL_STRING), => IN_CSL_SSTRING_LINECONT
/\\./ : #
/$/ : paint(upto, CSL_STRING), => IN_CSL_DEFAULT
'\r' : paint(upto, CSL_STRING), => IN_CSL_DEFAULT # /$/ doesn't match here with pcre

state IN_CSL_SSTRING_LINECONT:
/\\[\r\n]/ : #stay
/\\./ : => IN_CSL_SSTRING
"'" : paint(include, CSL_STRING), => IN_CSL_DEFAULT
/./ : => IN_CSL_SSTRING
/^$/ : paint(upto, CSL_STRING), => IN_CSL_DEFAULT # End empty lines here

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

state IN_CSL_NUMBER_1 :
'.' : => IN_CSL_NUMBER_2
/[\d]/ : #stay
/[Ee][-+]?/ : => IN_CSL_NUMBER_3
/./ : paint(upto, CSL_NUMBER), redo, => IN_CSL_DEFAULT

state IN_CSL_NUMBER_2:
/[\d]/ : #stay
/[Ee][-+]?/ : => IN_CSL_NUMBER_3
'.' : paint(upto, CSL_NUMBER), paint(include, CSL_OPERATOR),  => IN_CSL_DEFAULT
/./ : paint(upto, CSL_NUMBER), redo, => IN_CSL_DEFAULT

state IN_CSL_NUMBER_3:
/[^\d]/ : paint(upto, CSL_NUMBER), redo, => IN_CSL_DEFAULT

state IN_CSL_REGEX:
/\\./ : #stay
/\/[\w]*/ : paint(include, CSL_REGEX), => IN_CSL_DEFAULT
# JavaScript doesn't do x-type regexes, but here's how we'll do it in Perl:
#### /#[^\/]*/ : paint(upto, CSL_REGEX), paint(include, CSL_COMMENT) # stay
#### /[\r\n]/ : #stay
/[\r\n]/ : paint(include, CSL_REGEX), => IN_CSL_DEFAULT

# 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_CSL_OP1:
# Single-char operator -- all ops work as standalone chars

/[$OP](?:(?![$OP])|$)/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT

# Otherwise look from longest to smallest
/>>>?=?/  : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
'>=' : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
/!==?/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
/&&?=?/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
/<<?=?/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
/===?/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
/-[-=>]/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
/\.\.\.?/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
/\^\^?=?/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
/\|\|?=?/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
/[%*+\/>]=/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
'::' : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
'++' : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT
# The fallback
/[$OP]/ : paint(include, CSL_OPERATOR), => IN_CSL_DEFAULT

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

# We might want to generalize this... by allowing named tokens.
# Currently we just wrap things with a token-check

# How to avoid specifying too much:

# Only reject list: accept all others
# Only accept list: reject everything else
# Only skip list: reject everything else, but 
# having only a set of skip items is redundant, as we'll end up rejecting

# If a style has two of the lists, the missing one is the default

# If a style has all three lists, anything else is rejected

token_check:
CSL_OPERATOR: reject [")", "++", "--", "]", "}"]

CSL_WORD: reject [class false function null private protected public super
this true get "include" set]

# All other keywords prefer an RE

CSL_DEFAULT: skip all
CSL_COMMENT: skip all
CSL_COMMENTBLOCK: skip all

# Default is to reject / as the start of a regex if it follows
# an unhandled style

#### CSL_IDENTIFIER: reject all
#### CSL_NUMBER: reject all
#### CSL_REGEX: reject all
#### CSL_STRING: reject all

# Fold info tokens

# Sometimes this should line up, when we're initializing an object.
# Hard to get this right without doing the same thing we do with
# Perl's notion of "variable indexer" vs. "operator".

fold "{" CSL_OPERATOR +
fold "}" CSL_OPERATOR -

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

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