All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cz.vutbr.web.csskit.antlr4.CSSToken Maven / Gradle / Ivy

package cz.vutbr.web.csskit.antlr4;

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.Pair;

import java.net.URL;
import java.util.Map;
import java.util.TreeMap;

/**
 * Token with encapsulation of LexerState during parse.
 * Models view at token text by removing syntactic sugar
 * from tokens with contains it,
 * e.g. STRING, URI, FUNCTION
 * @author kapy
 *
 */
public class CSSToken extends CommonToken {

	/**
	 * Extended with EOF_TOKEN
	 */
	private static final long serialVersionUID = 3L;

	/**
	 * Current lexer state
	 */
	protected CSSLexerState ls;

	/** Base URL for URIs */
	protected URL base;
	
	protected boolean valid = true;

	// token types
	public static final int FUNCTION = 1;
	public static final int URI = 2;
	public static final int STRING = 3;
	public static final int CLASSKEYWORD = 4;
	public static final int HASH = 5;
	public static final int UNCLOSED_STRING = 6;
    public static final int UNCLOSED_URI = 7;

	private final TypeMapper typeMapper;

	/**
	 * Creates CSSToken, this is base {@code emit()} constructor
	 * @param input Input stream
	 * @param type Type of token
	 * @param channel Channel of token
	 * @param start Start position in stream
	 * @param stop End position in stream
	 */
	public CSSToken(Pair input, int type, int channel, int start, int stop, TypeMapper typeMapper) {
		super(input, type, channel, start, stop);
		this.typeMapper = typeMapper; 
	}

	/**
	 * Creates CSSToken of given type with cloning lexer state
	 * automatically
	 * @param type Type of token
	 * @param state State of lexer, which will be copied
	 */
	public CSSToken(int type, CSSLexerState state, TypeMapper typeMapper) {
		this(type, state, 0, 0, typeMapper);
	}

	/**
	 * Creates CSSToken of given type with cloning lexer state
	 * automatically, allows to set text boundaries in input stream
	 * @param type Type of token
	 * @param state State of lexer, which will be copied
	 * @param start Start position in stream
	 * @param stop End position in stream
	 */
	public CSSToken(int type, CSSLexerState state, int start, int stop, TypeMapper typeMapper) {
		this(new Pair(null,null), type, Token.DEFAULT_CHANNEL, start, stop, typeMapper);
		this.ls = new CSSLexerState(state);
	}

	/**
	 * Sets lexer state for current token
	 * @param state Current lexer state
	 * @return Modified CSSToken
	 */
	public CSSToken setLexerState(CSSLexerState state) {
		this.ls = state;
		return this;
	}

	/**
	 * Gets lexer state at creation of token
	 * @return the lexer state
	 */
	public CSSLexerState getLexerState() {
		return ls;
	}

	/**
	 * Obtains the base URL used for the relative URIs
	 * @return the URL or null if not set
	 */
	public URL getBase()
    {
        return base;
    }

	/**
	 * Sets the base URL used for the relative URIs
	 * @param base the base URL to set
	 */
    public void setBase(URL base)
    {
        this.base = base;
    }

    public boolean isValid() {
        return valid;
    }

    public void setValid(boolean valid) {
        this.valid = valid;
    }

    /**
	 * Considers text as content of STRING token,
	 * and models view at this text as an common string,
	 * that is one character removed from the both beginning
	 * and the end.
	 * @param string Content of STRING token
	 * @return String with trimmed quotation marks
	 */
	public static String extractSTRING(String string) {
		return string.substring(1, string.length()-1);
	}

	public static String extractUNCLOSEDSTRING(String string) {
		return string.substring(1, string.length());
	}
	/**
	 * Considers text as content of URI token,
	 * and models view at this text as an common string,
	 * that is removed {@code 'url('} from the beginning
	 * and {@code ')'} from the and. If result of this operation
	 * is STRING, remove even quotation marks
	 * @param uri Content of URI token
	 * @return String with trimmed URI syntax sugar and
	 * optionally quotation marks
	 */
	public static String extractURI(String uri) {
		String ret = uri.substring(4, uri.length()-1).trim();
		// trim string
		if(ret.length() > 0 && (ret.charAt(0)=='\'' || ret.charAt(0)=='"'))
			ret = ret.substring(1, ret.length()-1);

		return ret;
	}

    public static String extractUNCLOSEDURI(String uri) {
        String ret = uri.substring(4).trim();
        // trim quotes (if any)
        if(ret.length() > 0) {
            final char fc = ret.charAt(0);
            if (fc == '\'' || fc == '"') {
                final char lc = (ret.length() > 1) ? ret.charAt(ret.length() - 1) : ' ';
                if (fc == lc)
                    ret = ret.substring(1, ret.length() - 1); //both quotes (finished string)
                else
                    ret = ret.substring(1, ret.length()); //left quote only (unfinished string)
            }
        }

        return ret;
    }
    
	/**
	 * Considers text as content of FUNCTION token,
	 * and models view at this text as an common string,
	 * that is removed {@code '('} from the end of string
	 * @param function Content of FUNCTION token
	 * @return String with trimmed FUNCTION open parenthesis
	 */
	public static String extractFUNCTION(String function) {
		return function.substring(0, function.length()-1);
	}

	/**
	 * Considers text as content of HASH token,
	 * and models view at this text as an common string,
	 * that is removed {@code '#'} from the beginning of string
	 * @param hash Content of HASH token
	 * @return String with trimmed HASH # character
	 */
	public static String extractHASH(String hash) {
		return hash.substring(1,hash.length());
	}

	/**
	 * Considers text as content of CLASSKEYWORD token,
	 * and models view at this text as an common string,
	 * that is removed {@code '.'} from the beginning of string
	 * @param className Content of CLASSKEYWORD token
	 * @return String with trimmed CLASSKEYWORD dot
	 */
	public static String extractCLASSKEYWORD(String className) {
		return className.substring(1,className.length());
	}

	/**
	 * Returns common text stored in token. Content is not modified.
	 * @return Model view of text in token
	 */
	@Override
	public String getText() {

		// sets text from input if not text directly available
		text = super.getText();

		int t;
		try {
			t = typeMapper.inverse().get(type);
		} catch (NullPointerException e) {
			return text;
		}
		switch (t) {
			case FUNCTION:
				return text.substring(0, text.length()-1);
			case URI:
				return extractURI(text);
            case UNCLOSED_URI:
                return extractUNCLOSEDURI(text);
			case STRING:
				return extractSTRING(text);
			case UNCLOSED_STRING:
				return extractUNCLOSEDSTRING(text);
			case CLASSKEYWORD:
				return extractCLASSKEYWORD(text);
			case HASH:
				return extractHASH(text);
			default:
				return text;
		}

	}



	@Override
    public String toString() {
    	StringBuilder sb = new StringBuilder();
    	sb.append("/").append(ls).append("/")
    		.append(super.toString());

    	return sb.toString();
    }

	/**
	 * Convert between type values defined in two classes.
	 */
	public static class TypeMapper {
		private final Map map;
		private final TypeMapper inverse;
		private TypeMapper(Map map, TypeMapper inverse) {
			this.map = map;
			this.inverse = inverse;
		}
		public TypeMapper(Class classA, Class classB, String... fieldNames) {
			map = new TreeMap();
			Map inverseMap = new TreeMap();
			for (String f : fieldNames) {
				try {
					int a = classA.getField(f).getInt(null);
					int b = classB.getField(f).getInt(null);
					map.put(a, b);
					inverseMap.put(b, a);
				} catch (IllegalAccessException e) {
					throw new RuntimeException(e);
				} catch (NoSuchFieldException e) {
					throw new RuntimeException(e);
				}
			}
			inverse = new TypeMapper(inverseMap, this);
		}
		public int get(int type) throws NullPointerException {
			return map.get(type);
		}
		public TypeMapper inverse() {
			return inverse;
		}
	}

    public static TypeMapper createDefaultTypeMapper(Class lexerClass) {
        return new TypeMapper(CSSToken.class, lexerClass, "FUNCTION", "URI", "STRING", "CLASSKEYWORD", "HASH", "UNCLOSED_STRING", "UNCLOSED_URI");
    }

	
	/**
	 * extract charset value from CHARSET token
     */
	public static String extractCHARSET(String charset){
	    final String arg = charset.replace("@charset","").replace(";","").trim();
	    if (arg.length() > 2)
	        return extractSTRING(arg);
	    else
	        return "";
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy