public class ResolutionException extends Exception
{
	//
	// Construction
	//

	public ResolutionException( String message )
	{
		super( message );
	}

	public ResolutionException( String message, Throwable cause )
	{
		super( message, cause );
	}

	public ResolutionException( Throwable cause )
	{
		super( cause );
	}

	// //////////////////////////////////////////////////////////////////////////
	// Private

	private static final long serialVersionUID = 1L;
} public class Util
{
	public static String literalRegEx( String expression )
	{
		return "\\Q" + expression + "\\E";
	}

	public static String replace( String string, String occurence, String replacement )
	{
		return string.replaceAll( literalRegEx( occurence ), replacement );
	}

	public static String streamToString( InputStream stream ) throws IOException
	{
		StringBuilder builder = new StringBuilder();
		String line;

		try
		{
			BufferedReader reader = new BufferedReader( new InputStreamReader( stream, "UTF-8" ) );
			while( ( line = reader.readLine() ) != null )
				builder.append( line ).append( "\n" );
		}
		finally
		{
			stream.close();
		}

		return builder.toString();
	}

	public static String rejsonToJson( InputStream stream ) throws IOException
	{
		String rejson = streamToString( stream );
		String json = rejsonToJson( rejson, true );
		json = rejsonToJson( json, false );
		return json;
	}

	public static String rejsonToJson( String rejson, boolean doubleQuote )
	{
		Matcher matcher = doubleQuote ? DOUBLE_QUOTED_STRING.matcher( rejson ) : SINGLE_QUOTED_STRING.matcher( rejson );
		StringBuilder json = new StringBuilder();
		int start = 0, end = 0, lastEnd = 0;
		while( matcher.find() )
		{
			lastEnd = end;
			start = matcher.start();
			end = matcher.end();
			if( ( start > 0 ) && ( rejson.charAt( start - 1 ) == 'r' ) )
			{
				// Convert Python-style r"" string to Java-compatible pattern
				String string = rejson.substring( start + 1, end - 1 );
				json.append( rejson.substring( lastEnd, start - 1 ) );
				json.append( '\"' );
				json.append( pythonRegExToJavaPattern( string, doubleQuote ) );
				json.append( '\"' );
			}
			/*
			 * else if( !doubleQuote ) { // From single quote to double quote
			 * String string = rejson.substring( start + 1, end - 1 );
			 * json.append( rejson.substring( lastEnd, start - 1 ) );
			 * json.append( '\"' ); json.append( string.replaceAll( "\"",
			 * "\\\\\"" ) ); json.append( '\"' ); }
			 */
			else
			{
				// As is
				json.append( rejson.substring( lastEnd, end ) );
			}
		}
		json.append( rejson.substring( end ) );
		// System.out.println( json );
		return json.toString();
	}

	public static String pythonRegExToJavaPattern( String pattern, boolean doubleQuote )
	{
		pattern = pattern.replaceAll( "\\\\", "\\\\\\\\" );
		pattern = pattern.replaceAll( "\\{", "\\\\\\\\{" );
		pattern = pattern.replaceAll( "\\}", "\\\\\\\\}" );
		if( !doubleQuote )
			pattern = pattern.replaceAll( "\"", "\\\\\"" );
		// System.out.println( pattern );
		return pattern;
	}

	public static String escapeHtml( String text )
	{
		text = text.replace( "&", "&amp;" );
		text = text.replace( "<", "&lt;" );
		text = text.replace( ">", "&gt;" );
		text = text.replace( "\"", "&quot;" );
		text = text.replace( "'", "&#39;" );
		return text;
	}

	public static String asHtml( String text )
	{
		text = escapeHtml( text );
		text = text.replace( " ", "&nbsp;" );
		return text;
	}

	private static final Pattern DOUBLE_QUOTED_STRING = Pattern.compile( "\"(?>\\\\.|.)*?\"" );

	private static final Pattern SINGLE_QUOTED_STRING = Pattern.compile( "'(?>\\\\.|.)*?'" );
} public abstract class Formatter
{
	//
	// Static operations
	//

	public static Formatter getByName( String name ) throws ResolutionException
	{
		if( Character.isLowerCase( name.charAt( 0 ) ) )
			name = Character.toUpperCase( name.charAt( 0 ) ) + name.substring( 1 ) + "Formatter";

		Formatter formatter = getByFullName( name );
		if( formatter != null )
			return formatter;
		else
		{
			// Try contrib package
			String pack = Jygments.class.getPackage().getName() + ".contrib";
			formatter = getByFullName( pack + "." + name );
			if( formatter == null )
			{
				// Try this package
				pack = Formatter.class.getPackage().getName();
				formatter = getByFullName( pack + "." + name );
			}
			return formatter;
		}
	}

	public static Formatter getByFullName( String fullName ) throws ResolutionException
	{
		try
		{
			return (Formatter) Jygments.class.getClassLoader().loadClass( fullName ).newInstance();
		}
		catch( InstantiationException x )
		{
		}
		catch( IllegalAccessException x )
		{
		}
		catch( ClassNotFoundException x )
		{
		}

		return null;
	}

	public Formatter( Style style, boolean full, String title, String encoding )
	{
		this.style = style;
		this.title = title != null ? title : "";
		this.encoding = encoding != null ? encoding : "utf8";
	}

	public Style getStyle()
	{
		return style;
	}

	public String getTitle()
	{
		return title;
	}

	public String getEncoding()
	{
		return encoding;
	}

	public abstract void format( Iterable<Token> tokenSource, Writer writer ) throws IOException;

	// //////////////////////////////////////////////////////////////////////////
	// Private

	private final Style style;

	private final String title;

	private final String encoding;
} public class Token
{
	//
	// Construction
	//

	public Token( int pos, TokenType tokenType, String value )
	{
		this.pos = pos;
		this.tokenType = tokenType;
		this.value = value;
	}

	//
	// Attributes
	//

	public int getPos()
	{
		return pos;
	}

	public TokenType getType()
	{
		return tokenType;
	}

	public String getValue()
	{
		return value;
	}

	// //////////////////////////////////////////////////////////////////////////
	// Private

	private final int pos;

	private final TokenType tokenType;

	private final String value;
} public class TokenType
{
	//
	// Constants
	//

	public static final TokenType Token = create( "Token", "" );

	// Main

	public static final TokenType Whitespace = create( "Whitespace", "w", Token );

	public static final TokenType Text = create( "Text", "", Token );

	public static final TokenType Error = create( "Error", "err", Token );

	public static final TokenType Other = create( "Other", "x", Token );

	// Keywords

	public static final TokenType Keyword = create( "Keyword", "k", Text );

	public static final TokenType Keyword_Constant = create( "Keyword.Constant", "kc", Keyword );

	public static final TokenType Keyword_Declaration = create( "Keyword.Declaration", "kd", Keyword );

	public static final TokenType Keyword_Namespace = create( "Keyword.Namespace", "kn", Keyword );

	public static final TokenType Keyword_Pseudo = create( "Keyword.Pseudo", "kp", Keyword );

	public static final TokenType Keyword_Reserved = create( "Keyword.Reserved", "kr", Keyword );

	public static final TokenType Keyword_Type = create( "Keyword.Type", "kt", Keyword );

	// Names

	public static final TokenType Name = create( "Name", "n", Text );

	public static final TokenType Name_Attribute = create( "Name.Attribute", "na", Name );

	public static final TokenType Name_Builtin = create( "Name.Builtin", "nb", Name );

	public static final TokenType Name_Builtin_Pseudo = create( "Name.Builtin.Pseudo", "bp", Name_Builtin );

	public static final TokenType Name_Class = create( "Name.Class", "nc", Name );

	public static final TokenType Name_Constant = create( "Name.Constant", "no", Name );

	public static final TokenType Name_Decorator = create( "Name.Decorator", "nd", Name );

	public static final TokenType Name_Entity = create( "Name.Entity", "ni", Name );

	public static final TokenType Name_Exception = create( "Name.Exception", "ne", Name );

	public static final TokenType Name_Function = create( "Name.Function", "nf", Name );

	public static final TokenType Name_Property = create( "Name.Property", "py", Name );

	public static final TokenType Name_Label = create( "Name.Label", "nl", Name );

	public static final TokenType Name_Namespace = create( "Name.Namespace", "nn", Name );

	public static final TokenType Name_Other = create( "Name.Other", "nx", Name );

	public static final TokenType Name_Tag = create( "Name.Tag", "nt", Name );

	public static final TokenType Name_Variable = create( "Name.Variable", "nv", Name );

	public static final TokenType Name_Variable_Class = create( "Name.Variable.Class", "vc", Name_Variable );

	public static final TokenType Name_Variable_Global = create( "Name.Variable.Global", "vg", Name_Variable );

	public static final TokenType Name_Variable_Instance = create( "Name.Variable.Instance", "vi", Name_Variable );

	// Literals

	public static final TokenType Literal = create( "Literal", "l", Text );

	public static final TokenType Literal_Date = create( "Literal.Date", "ld", Literal );

	// Strings

	public static final TokenType String = create( "String", "s", Text );

	public static final TokenType String_Backtick = create( "String.Backtick", "sb", String );

	public static final TokenType String_Char = create( "String.Char", "sc", String );

	public static final TokenType String_Doc = create( "String.Doc", "sd", String );

	public static final TokenType String_Double = create( "String.Double", "s2", String );

	public static final TokenType String_Escape = create( "String.Escape", "se", String );

	public static final TokenType String_Heredoc = create( "String.Heredoc", "sh", String );

	public static final TokenType String_Interpol = create( "String.Interpol", "si", String );

	public static final TokenType String_Other = create( "String.Other", "sx", String );

	public static final TokenType String_Regex = create( "String.Regex", "sr", String );

	public static final TokenType String_Single = create( "String.Single", "s1", String );

	public static final TokenType String_Symbol = create( "String.Symbol", "ss", String );

	// Numbers

	public static final TokenType Number = create( "Number", "m", Text );

	public static final TokenType Number_Float = create( "Number.Float", "mf", Number );

	public static final TokenType Number_Hex = create( "Number.Hex", "mh", Number );

	public static final TokenType Number_Integer = create( "Number.Integer", "mi", Number );

	public static final TokenType Number_Integer_Long = create( "Number.Integer.Long", "il", Number_Integer );

	public static final TokenType Number_Oct = create( "Number.Oct", "mo", Number );

	// Operators

	public static final TokenType Operator = create( "Operator", "o", Text );

	public static final TokenType Operator_Word = create( "Operator.Word", "ow", Operator );

	// Punctuation

	public static final TokenType Punctuation = create( "Punctuation", "p", Text );

	// Comments

	public static final TokenType Comment = create( "Comment", "c", Text );

	public static final TokenType Comment_Multiline = create( "Comment.Multiline", "cm", Comment );

	public static final TokenType Comment_Preproc = create( "Comment.Preproc", "cp", Comment );

	public static final TokenType Comment_Single = create( "Comment.Single", "c1", Comment );

	public static final TokenType Comment_Special = create( "Comment.Special", "cs", Comment );

	// Generics

	public static final TokenType Generic = create( "Generic", "g", Text );

	public static final TokenType Generic_Deleted = create( "Generic.Deleted", "gd", Generic );

	public static final TokenType Generic_Emph = create( "Generic.Emph", "ge", Generic );

	public static final TokenType Generic_Error = create( "Generic.Error", "gr", Generic );

	public static final TokenType Generic_Heading = create( "Generic.Heading", "gh", Generic );

	public static final TokenType Generic_Inserted = create( "Generic.Inserted", "gi", Generic );

	public static final TokenType Generic_Output = create( "Generic.Output", "go", Generic );

	public static final TokenType Generic_Prompt = create( "Generic.Prompt", "gp", Generic );

	public static final TokenType Generic_Strong = create( "Generic.Strong", "gs", Generic );

	public static final TokenType Generic_Subheading = create( "Generic.Subheading", "gu", Generic );

	public static final TokenType Generic_Traceback = create( "Generic.Traceback", "gt", Generic );

	//
	// Static attributes
	//

	public static TokenType getTokenTypeByName( String name )
	{
		return tokenTypesByName.get( name );
	}

	public static TokenType getTokenTypeByShortName( String shortName )
	{
		return tokenTypesByShortName.get( shortName );
	}

	public static Collection<TokenType> getTokenTypes()
	{
		return tokenTypesByName.values();
	}

	//
	// Attributes
	//

	public String getName()
	{
		return name;
	}

	public String getShortName()
	{
		return shortName;
	}

	public TokenType getParent()
	{
		return parent;
	}

	//
	// Object
	//

	@Override
	public String toString()
	{
		return name;
	}

	// //////////////////////////////////////////////////////////////////////////
	// Private

	private static Map<String, TokenType> tokenTypesByName;

	private static Map<String, TokenType> tokenTypesByShortName;

	private static final TokenType create( String name, String shortName )
	{
		return create( name, shortName, null );
	}

	private static final TokenType create( String name, String shortName, TokenType parent )
	{
		TokenType tokenType = new TokenType( name, shortName, parent );

		if( tokenTypesByName == null )
			tokenTypesByName = new HashMap<String, TokenType>();
		if( tokenTypesByShortName == null )
			tokenTypesByShortName = new HashMap<String, TokenType>();

		tokenTypesByName.put( name, tokenType );
		tokenTypesByShortName.put( shortName, tokenType );

		return tokenType;
	}

	private final String name;

	private final String shortName;

	private final TokenType parent;

	private TokenType( String name, String shortName, TokenType parent )
	{
		this.name = name;
		this.shortName = shortName;
		this.parent = parent;
	}
} public class ColorStyleElement extends StyleElement
{
	//
	// Types
	//

	public enum Type
	{
		Foreground, Background, Border
	}

	//
	// Static attributes
	//

	public static ColorStyleElement getColorStyleElementByName( String name )
	{
		if( name.startsWith( "bg:" ) )
			return background( name.substring( 3 ) );
		if( name.startsWith( "border:" ) )
			return border( name.substring( 7 ) );
		return foreground( name );
	}

	public static ColorStyleElement foreground( String color )
	{
		return new ColorStyleElement( color, Type.Foreground, color );
	}

	public static ColorStyleElement background( String color )
	{
		return new ColorStyleElement( "bg:" + color, Type.Background, color );
	}

	public static ColorStyleElement border( String color )
	{
		return new ColorStyleElement( "border:" + color, Type.Border, color );
	}

	//
	// Attributes
	//

	public String getColor()
	{
		return color;
	}

	public Type getType()
	{
		return type;
	}

	// //////////////////////////////////////////////////////////////////////////
	// Protected

	protected ColorStyleElement( String name, Type type, String color )
	{
		super( name );
		this.type = type;
		this.color = color;
	}

	// //////////////////////////////////////////////////////////////////////////
	// Private

	private final String color;

	private final Type type;
} public class EffectStyleElement extends StyleElement
{
	//
	// Constants
	//

	public static final EffectStyleElement Bold = create( "bold" );

	public static final EffectStyleElement NoBold = create( "nobold" );

	public static final EffectStyleElement Italic = create( "italic" );

	public static final EffectStyleElement NoItalic = create( "noitalic" );

	public static final EffectStyleElement Underline = create( "underline" );

	public static final EffectStyleElement NoUnderline = create( "nounderline" );

	// //////////////////////////////////////////////////////////////////////////
	// Protected

	protected EffectStyleElement( String name )
	{
		super( name );
	}

	private static EffectStyleElement create( String name )
	{
		EffectStyleElement fontStyleElement = new EffectStyleElement( name );
		add( fontStyleElement );
		return fontStyleElement;
	}
} public class FontStyleElement extends StyleElement
{
	//
	// Constants
	//

	public static final FontStyleElement Roman = create( "roman" );

	public static final FontStyleElement Sans = create( "sans" );

	public static final FontStyleElement Mono = create( "mono" );

	// //////////////////////////////////////////////////////////////////////////
	// Protected

	protected FontStyleElement( String name )
	{
		super( name );
	}

	private static FontStyleElement create( String name )
	{
		FontStyleElement fontStyleElement = new FontStyleElement( name );
		add( fontStyleElement );
		return fontStyleElement;
	}
} public class Style extends NestedDef<Style>
{
	//
	// Static operations
	//

	public static Style getByName( String name ) throws ResolutionException
	{
		if( Character.isLowerCase( name.charAt( 0 ) ) )
			name = Character.toUpperCase( name.charAt( 0 ) ) + name.substring( 1 ) + "Style";

		Style style = getByFullName( name );
		if( style != null )
			return style;
		else
		{
			// Try contrib package
			String pack = Jygments.class.getPackage().getName() + ".contrib";
			name = pack + "." + name;
			style = getByFullName( name );
			if( style == null )
				throw new ResolutionException( "Could not load style: " + name );
			return style;
		}
	}

	@SuppressWarnings("unchecked")
	public static Style getByFullName( String fullName ) throws ResolutionException
	{
		// Try cache
		Style style = styles.get( fullName );
		if( style != null )
			return style;

		try
		{
			return (Style) Jygments.class.getClassLoader().loadClass( fullName ).newInstance();
		}
		catch( InstantiationException x )
		{
		}
		catch( IllegalAccessException x )
		{
		}
		catch( ClassNotFoundException x )
		{
		}

		InputStream stream = Jygments.class.getClassLoader().getResourceAsStream( fullName.replace( '.', '/' ) + ".json" );
		if( stream != null )
		{
			ObjectMapper objectMapper = new ObjectMapper();
			objectMapper.getFactory().configure( JsonParser.Feature.ALLOW_COMMENTS, true );
			try
			{
				Map<String, Object> json = objectMapper.readValue( stream, HashMap.class );
				style = new Style();
				style.addJson( json );
				style.resolve();

				// Cache it
				Style existing = styles.putIfAbsent( fullName, style );
				if( existing != null )
					style = existing;

				return style;
			}
			catch( JsonParseException x )
			{
				throw new ResolutionException( x );
			}
			catch( JsonMappingException x )
			{
				throw new ResolutionException( x );
			}
			catch( IOException x )
			{
				throw new ResolutionException( x );
			}
		}

		return null;
	}

	//
	// Attributes
	//

	public Map<TokenType, List<StyleElement>> getStyleElements()
	{
		return styleElements;
	}

	//
	// Operations
	//

	public void addStyleElement( TokenType tokenType, StyleElement styleElement )
	{
		List<StyleElement> styleElementsForTokenType = styleElements.get( tokenType );
		if( styleElementsForTokenType == null )
		{
			styleElementsForTokenType = new ArrayList<StyleElement>();
			styleElements.put( tokenType, styleElementsForTokenType );
		}
		styleElementsForTokenType.add( styleElement );
	}

	public void resolve() throws ResolutionException
	{
		resolve( this );
	}

	//
	// Def
	//

	@Override
	public boolean resolve( Style style ) throws ResolutionException
	{
		if( super.resolve( style ) )
		{
			boolean done = false;
			while( !done )
			{
				done = true;
				for( TokenType tokenType : TokenType.getTokenTypes() )
				{
					if( tokenType != TokenType.Token )
					{
						if( !styleElements.containsKey( tokenType ) )
						{
							boolean doneOne = false;
							TokenType parent = tokenType.getParent();
							while( parent != null )
							{
								if( parent == TokenType.Token )
								{
									doneOne = true;
									break;
								}

								List<StyleElement> parentElements = styleElements.get( parent );
								if( parentElements != null )
								{
									styleElements.put( tokenType, parentElements );
									doneOne = true;
									break;
								}

								parent = parent.getParent();
							}

							if( !doneOne )
								done = false;
						}
					}
				}
			}

			return true;
		}
		else
			return false;
	}

	// //////////////////////////////////////////////////////////////////////////
	// Protected

	protected void add( String tokenTypeName, String... styleElementNames )
	{
		ArrayList<String> list = new ArrayList<String>( styleElementNames.length );
		for( String styleElementName : styleElementNames )
			list.add( styleElementName );
		addDef( new StyleElementDef( tokenTypeName, list ) );
	}

	@SuppressWarnings("unchecked")
	protected void addJson( Map<String, Object> json ) throws ResolutionException
	{
		for( Map.Entry<String, Object> entry : json.entrySet() )
		{
			String tokenTypeName = entry.getKey();
			if( entry.getValue() instanceof Iterable<?> )
			{
				for( String styleElementName : (Iterable<String>) entry.getValue() )
					add( tokenTypeName, styleElementName );
			}
			else if( entry.getValue() instanceof String )
				add( tokenTypeName, (String) entry.getValue() );
			else
				throw new ResolutionException( "Unexpected value in style definition: " + entry.getValue() );
		}
	}

	// //////////////////////////////////////////////////////////////////////////
	// Private

	private static final ConcurrentMap<String, Style> styles = new ConcurrentHashMap<String, Style>();

	private final Map<TokenType, List<StyleElement>> styleElements = new HashMap<TokenType, List<StyleElement>>();
} public class StyleElement
{
	static
	{
		// Force these classes to load
		new ColorStyleElement( null, null, null );
		new EffectStyleElement( null );
		new FontStyleElement( null );
	}

	//
	// Static attributes
	//

	public static StyleElement getStyleElementByName( String name )
	{
		StyleElement styleElement = styleElementsByName.get( name );
		if( styleElement == null )
			styleElement = ColorStyleElement.getColorStyleElementByName( name );
		return styleElement;
	}

	//
	// Attributes
	//

	public String getName()
	{
		return name;
	}

	//
	// Object
	//

	@Override
	public String toString()
	{
		return name;
	}

	// //////////////////////////////////////////////////////////////////////////
	// Protected

	protected static final void add( StyleElement styleElement )
	{
		if( styleElementsByName == null )
			styleElementsByName = new HashMap<String, StyleElement>();

		styleElementsByName.put( styleElement.name, styleElement );
	}

	protected StyleElement( String name )
	{
		this.name = name;
	}

	// //////////////////////////////////////////////////////////////////////////
	// Private

	private static Map<String, StyleElement> styleElementsByName;

	private final String name;
}
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.Map;
import com.threecrickets.jygments.ResolutionException;
import com.threecrickets.jygments.Util;
import com.threecrickets.jygments.format.Formatter;
import com.threecrickets.jygments.grammar.Token;
import com.threecrickets.jygments.grammar.TokenType;
import com.threecrickets.jygments.style.ColorStyleElement;
import com.threecrickets.jygments.style.EffectStyleElement;
import com.threecrickets.jygments.style.FontStyleElement;
import com.threecrickets.jygments.style.Style;
import com.threecrickets.jygments.style.StyleElement;
/**
 * Copyright 2010-2016 Three Crickets LLC.
 * <p>
 * The contents of this file are subject to the terms of a BSD license. See
 * attached license.txt.
 * <p>
 * Alternatively, you can obtain a royalty free commercial license with less
 * limitations, transferable or non-transferable, directly from Three Crickets
 * at http://threecrickets.com/
 */

package com.threecrickets.jygments.contrib;



/**
 * @author Tal Liron
 */
public class HtmlFormatter extends Formatter
{
	//
	// Construction
	//

	public HtmlFormatter() throws ResolutionException
	{
		this( Style.getByName( "default" ), false, null, null );
	}

	public HtmlFormatter( Style style, boolean full, String title, String encoding )
	{
		super( style, full, title, encoding );
	}

	//
	// Formatter
	//

	@Override
	public void format( Iterable<Token> tokenSource, Writer writer ) throws IOException
	{
		writer.write( getDocHeader1() );
		writer.write( "  <title>" );
		writer.write( Util.escapeHtml( getTitle() ) );