/**
 * Copyright (c) 2010, Benjamin Joffe
 * http://www.benjoffe.com/
 *
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted for NON-COMMERSIAL PURPOSES  providedthat the
 * following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

function syntaxHighlight(tokens)
{
  var s = '<ol><li>';
  for (var i=0; i<tokens.length; i++)
  {
    switch (tokens[i].type)
    {
      case TYPES.WHITESPACE :
        s += tokens[i].value.replace(/\s/g, '&nbsp;');
        break;
      case TYPES.IDENTIFIER :
        s += escapeHTML(tokens[i].value, '<span class="identifier">', '</span>');
        break;
      case TYPES.KEYWORD :
        s += escapeHTML(tokens[i].value, '<span class="keyword">', '</span>');
	break;
      case TYPES.NEWLINE :
        s += '&nbsp;<li>';
        break;
      case TYPES.NUMBER :
        s += escapeHTML(tokens[i].value, '<span class="number">', '</span>');
        break;
      case TYPES.STRING :
        s += escapeHTML(tokens[i].value, '<span class="string">', '</span>');
        break;
      case TYPES.COMMENT :
        s += escapeHTML(tokens[i].value, '<span class="comment">', '</span>');
        break;
      case TYPES.PUNCTUATOR :
        s += escapeHTML(tokens[i].value, '<span class="punctuator">', '</span>');
        break;
      case TYPES.COMMAND :
        s += escapeHTML(tokens[i].value, '<span class="command">', '</span>');
        break;
      case TYPES.REGEXP :
        s += escapeHTML(tokens[i].value, '<span class="regexp">', '</span>');
        break;
      case TYPES.BLOCK :
        s += escapeHTML(tokens[i].value, '<span class="block">', '</span>');
        break;
    }
  }
  s += '</ul>';
  return s;
}

if (true)
{
  a = {
    b: function()
    {
      c = {
        d: {}.x
      };
    }(),
    x: function()
    {
      b = 1 ? {}.x : {};
      a: {
        // labelled 
        }
      switch (true)
      {
        case 1 : yeah; break;
        case 2 : {
          blockStuff();
          a = {}.x;
        }
        default : {
          blockStuff();
        }
      }
    },
    y: 2
  }}
  


function escapeHTML(str, startTag, endTag)
{
  return startTag + 
	 str.replace(/\&/g, '&amp;').
	     replace(/</g, '&lt;').
	     replace(/\r\n|\r|\n/g, endTag+'&nbsp;<li>'+startTag) +
	 endTag;
}

var COMMAND = {
'abstract':1,'boolean':1,'break':1,'byte':1,'case':1,'catch':1,'char':1,'class':1,'const':1,'continue':1,'default':1,'delete':1,'do':1,'double':1,'else':1,'extends':1,'final':1,'finally':1,'float':1,'for':1,'function':1,'goto':1,'if':1,'implements':1,'import':1,'in':1,'instanceof':1,'int':1,'interface':1,'long':1,'native':1,'new':1,'package':1,'private':1,'protected':1,'public':1,'return':1,'short':1,'static':1,'super':1,'switch':1,'synchronized':1,'throw':1,'throws':1,'transient':1,'try':1,'typeof':1,'var':1,'void':1,'while':1,'with':1}
var KEYWORD = {
'true':1,'false':1,'null':1,'this':1}
var WHITESPACE = {
'\u0009': 1,'\u000B': 1,'\u000C': 1,'\u0020': 1,'\u00A0': 1}
var LINETERMINATOR = {
'\u000A': 1,'\u000D': 1,'\u000D\u000A': 1,'\u2028': 1,'\u2029': 1}
var NUMBER = {
'0': 1,'1': 1,'2': 1,'3': 1,'4': 1,'5': 1,'6': 1,'7': 1,'8': 1,'9': 1}
var PUNCTUATOR = {
'{': 1,'}': 1,'(': 1,')': 1,'[': 1,']': 1,';': 1,',': 1,'<': 1,'>': 1,'=': 1,'!': 1,'+': 1,'-': 1,'*': 1,'/':1,'%': 1,'&': 1,'|': 1,'^': 1,'~': 1,'?': 1,':': 1,'.': 1}
var STRING_DELIMITER = {
'"': 1,'\'': 1}
var HEX_NUMBER = {
'0': 1,'1': 1,'2': 1,'3': 1,'4': 1,'5': 1,'6': 1,'7': 1,'8': 1,'9': 1,'a': 1,'b': 1,'c': 1,'d': 1,'e': 1,'f': 1,'A': 1,'B': 1,'C': 1,'D': 1,'E': 1,'F': 1}
var REG_EXP_FLAG = {'g': 1,'i': 1,'m': 1}

var TYPES = {
  COMMENT: 0,
  NEWLINE: 1,
  WHITESPACE: 2,
  KEYWORD: 3,
  IDENTIFIER: 4,
  NUMBER: 5,
  STRING: 6,
  PUNCTUATOR: 7,
  COMMAND: 8,
  REGEXP: 9,
  BLOCK: 10,
  solve: function(type)
  {
    for (var i in this)
    {
      if (this[i]==type) return i;
    }
    return -1;
  }
}
