@Override public void doTriggeredFunction(OGLGraphics g) { out.println("GL Vendor: " + g.getGLVendor()); out.println("GL Version: " + g.getGLVersion()); out.println("GL Renderer: " + g.getGLRenderer()); out.println("GL Extensions:"); Common.printWrapped(out, g.getGLExtensions(), 80); out.println(); }
/** Writes an object. */ public void writeObject(JSONObject object) throws IOException { if (object.isUndefined()) writeString("undefined"); else if (object.isNull()) writeString("null"); else if (object.isArray()) { writeString("["); for (int i = 0; i < object.length(); i++) { writeObject(object.get(i)); if (i < object.length() - 1) writeString(","); } writeString("]"); } else if (object.isObject()) { writeString("{"); int i = 0; int len = object.getMemberCount(); for (String member : object.getMemberNames()) { writeString("\""); writeString(Common.withEscChars(member)); writeString("\":"); writeObject(object.get(member)); if (i < len - 1) writeString(","); i++; } writeString("}"); } else { Object value = object.getValue(); if (value instanceof Boolean) writeString(object.getBoolean()); else if (value instanceof Byte) writeString(object.getByte()); else if (value instanceof Short) writeString(object.getShort()); else if (value instanceof Integer) writeString(object.getInt()); else if (value instanceof Float) writeString(object.getFloat()); else if (value instanceof Long) writeString(object.getLong()); else if (value instanceof Double) writeString(object.getDouble()); else { writeString("\""); writeString(Common.withEscChars(object.getString())); writeString("\""); } } }
/** * Class used for breaking up a stream of characters into lexicographical tokens. Spaces, newlines, * tabs, and breaks in the stream are added if desired, otherwise, they are stripped out. * * <p>Special delimiter characters take precedence over String delimiters. String delimiter * characters take precedence over regular delimiters. Delimiter characters take parsing priority * over other characters. Delimiter evaluation priority goes: CommentDelimiter, Delimiter. * Identifier evaluation priority goes: Keyword, CaseInsensitiveKeyword, Identifier. * * @author Matthew Tropiano * @since 2.3.0, this now supports integers/floating-point numbers with exponent notation, and * separates the configuration for how Lexers scan for information with {@link LexerKernel}. */ public class Lexer { public static boolean DEBUG = Common.parseBoolean(System.getProperty(Lexer.class.getName() + ".debug"), false); /** Default lexer name. */ public static final String DEFAULT_NAME = "Lexer"; /** Lexer end-of-stream char. */ public static final char END_OF_STREAM = '\ufffe'; /** Lexer end-of-stream char. */ public static final char END_OF_LEXER = '\uffff'; /** Lexer newline char. */ public static final char NEWLINE = '\n'; /** The lexer kernel to use. */ private LexerKernel kernel; /** Stream stack. */ private Stack<Stream> streamStack; /** The current state. */ private int state; /** List of error messages. */ private List<String> preprocessorErrorList; /** Current token builder. */ private StringBuilder builder; /** Current string end char. */ private char stringEnd; /** If true, we are in a delimiter break. */ private boolean delimBreak; /** Saved character for delimiter test. */ private char delimBreakChar; /** Current special type. */ private int specialType; /** * Creates a new lexer around a String, that will be wrapped into a StringReader. This will also * assign this lexer a default name. * * @param kernel the lexer kernel to use for defining how to parse the input text. * @param in the string to read from. */ public Lexer(LexerKernel kernel, String in) { this(kernel, null, in); } /** * Creates a new lexer around a String, that will be wrapped into a StringReader. * * @param kernel the lexer kernel to use for defining how to parse the input text. * @param name the name of this lexer. * @param in the reader to read from. */ public Lexer(LexerKernel kernel, String name, String in) { this(kernel, name, new StringReader(in)); } /** * Creates a new lexer around a reader. This will also assign this lexer a default name. * * @param kernel the kernel to use for this lexer. * @param in the reader to read from. */ public Lexer(LexerKernel kernel, Reader in) { this(kernel, null, in); } /** * Creates a new lexer around a reader. * * @param kernel the kernel to use for this lexer. * @param name the name of this lexer. * @param in the reader to read from. */ public Lexer(LexerKernel kernel, String name, Reader in) { this.kernel = kernel; streamStack = new Stack<Stream>(); state = TYPE_UNKNOWN; builder = new StringBuilder(); preprocessorErrorList = new List<String>(); pushStream(name, in); } /** @return the lexer's current stream name. */ public String getCurrentStreamName() { if (streamStack.isEmpty()) return "LEXER END"; return streamStack.peek().streamName; } /** * Gets the lexer's current stream's line number. * * @return the lexer's current stream's line number, or -1 if at Lexer end. */ public int getCurrentLine() { if (streamStack.isEmpty()) return -1; return streamStack.peek().lineNum; } /** * Pushes a stream onto the stream stack. This will reset the token state as well. * * @param name the name of the stream. * @param in the reader reader. */ public void pushStream(String name, Reader in) { streamStack.push(new Stream(name, in)); } /** * Gets the current stream. * * @return the name of the current stream. */ public Stream currentStream() { return streamStack.peek(); } /** * Gets the next token. If there are no tokens left to read, this will return null. * * @return the next token, or null if no more tokens to read. * @throws IOException if a token cannot be read by the underlying Reader. */ public Token nextToken() throws IOException { boolean breakloop = false; while (!breakloop) { char c = 0; if (isOnDelimBreak()) { c = delimBreakChar; clearDelimBreak(); } else c = readChar(); switch (getState()) { case TYPE_END_OF_LEXER: { breakloop = true; } break; case TYPE_UNKNOWN: { if (isLexerEnd(c)) { setState(TYPE_END_OF_LEXER); breakloop = true; } else if (isStreamEnd(c)) { if (kernel.willIncludeStreamBreak()) { setState(TYPE_END_OF_STREAM); breakloop = true; } streamStack.pop(); } else if (isNewline(c)) { if (kernel.willIncludeNewlines()) { setState(TYPE_DELIM_NEWLINE); breakloop = true; } } else if (isSpace(c)) { if (kernel.willIncludeSpaces()) { setState(TYPE_DELIM_SPACE); breakloop = true; } } else if (isTab(c)) { if (kernel.willIncludeTabs()) { setState(TYPE_DELIM_TAB); breakloop = true; } } else if (isWhitespace(c)) { } else if (isPoint(c) && isDelimiterStart(c)) { setState(TYPE_POINT); saveChar(c); } else if (isPoint(c) && !isDelimiterStart(c)) { setState(TYPE_FLOAT); saveChar(c); } else if (isSpecialStart(c)) { setState(TYPE_SPECIAL); setSpecialType(c); saveChar(c); } else if (isStringStart(c)) { setState(TYPE_STRING); setStringStartAndEnd(c); } else if (isDelimiterStart(c)) { setState(TYPE_DELIMITER); saveChar(c); } else if (isUnderscore(c)) { setState(TYPE_IDENTIFIER); saveChar(c); } else if (isLetter(c)) { setState(TYPE_IDENTIFIER); saveChar(c); } else if (c == '0') { setState(TYPE_HEX_INTEGER0); saveChar(c); } else if (isDigit(c)) { setState(TYPE_NUMBER); saveChar(c); } else { setState(TYPE_ILLEGAL); saveChar(c); } } break; // end TYPE_START_OF_LEXER case TYPE_ILLEGAL: { if (isStreamEnd(c)) { setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setDelimBreak(c); breakloop = true; } else if (isSpecialStart(c)) { setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setDelimBreak(c); breakloop = true; } else if (isDelimiterStart(c)) { setDelimBreak(c); breakloop = true; } else if (isLetter(c)) { saveChar(c); } else if (isDigit(c)) { saveChar(c); } else { saveChar(c); } } break; // end TYPE_ILLEGAL case TYPE_POINT: // decimal point is seen, but it is a delimiter. { if (isStreamEnd(c)) { setState(TYPE_DELIMITER); setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setState(TYPE_DELIMITER); setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setState(TYPE_DELIMITER); setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setState(TYPE_DELIMITER); setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setState(TYPE_DELIMITER); setDelimBreak(c); breakloop = true; } else if (isSpecialStart(c)) { setState(TYPE_DELIMITER); setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setState(TYPE_DELIMITER); setDelimBreak(c); breakloop = true; } else if (isDigit(c)) { setState(TYPE_FLOAT); saveChar(c); } else { setState(TYPE_DELIMITER); if (kernel.getDelimTable().containsKey(getCurrentLexeme() + c)) saveChar(c); else { setDelimBreak(c); breakloop = true; } } } break; // end TYPE_POINT case TYPE_FLOAT: { if (isStreamEnd(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isExponent(c)) { setState(TYPE_EXPONENT); saveChar(c); } else if (isSpecialStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isDigit(c)) { saveChar(c); } else if (isDelimiterStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else { setState(TYPE_ILLEGAL); saveChar(c); } } break; // end TYPE_FLOAT case TYPE_IDENTIFIER: { if (isStreamEnd(c)) { setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setDelimBreak(c); breakloop = true; } else if (isSpecialStart(c)) { setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setDelimBreak(c); breakloop = true; } else if (isDelimiterStart(c)) { setDelimBreak(c); breakloop = true; } else if (isLetter(c)) { saveChar(c); } else if (isDigit(c)) { saveChar(c); } else if (isUnderscore(c)) { saveChar(c); } else { setState(TYPE_ILLEGAL); saveChar(c); } } break; // end TYPE_IDENTIFIER case TYPE_SPECIAL: { if (isStreamEnd(c)) { setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setDelimBreak(c); breakloop = true; } else if (isSpecialStart(c)) { setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setDelimBreak(c); breakloop = true; } else if (isDelimiterStart(c)) { setDelimBreak(c); breakloop = true; } else if (isLetter(c)) { saveChar(c); } else if (isDigit(c)) { saveChar(c); } else { setState(TYPE_ILLEGAL); saveChar(c); } } break; // end TYPE_IDENTIFIER case TYPE_HEX_INTEGER0: { if (isStreamEnd(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isPoint(c)) { setState(TYPE_FLOAT); saveChar(c); } else if (isSpecialStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isDelimiterStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (c == 'x' || c == 'X') { setState(TYPE_HEX_INTEGER1); saveChar(c); } else if (isLetter(c)) { setState(TYPE_ILLEGAL); saveChar(c); } else if (isDigit(c)) { setState(TYPE_NUMBER); saveChar(c); } else { setState(TYPE_ILLEGAL); saveChar(c); } } break; // end TYPE_HEX_INTEGER0 case TYPE_HEX_INTEGER1: { if (isStreamEnd(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isPoint(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isSpecialStart(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isDelimiterStart(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isHexDigit(c)) { setState(TYPE_HEX_INTEGER); saveChar(c); } else if (isLetter(c)) { setState(TYPE_ILLEGAL); saveChar(c); } else { setState(TYPE_ILLEGAL); saveChar(c); } } break; // end TYPE_HEX_INTEGER1 case TYPE_HEX_INTEGER: { if (isStreamEnd(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isSpecialStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isDelimiterStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isHexDigit(c)) { saveChar(c); } else if (isLetter(c)) { setState(TYPE_ILLEGAL); saveChar(c); } else { setState(TYPE_ILLEGAL); saveChar(c); } } break; // end TYPE_HEX_INTEGER case TYPE_NUMBER: { if (isStreamEnd(c)) { setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setDelimBreak(c); breakloop = true; } else if (isPoint(c)) { setState(TYPE_FLOAT); saveChar(c); } else if (isExponent(c)) { setState(TYPE_EXPONENT); saveChar(c); } else if (isSpecialStart(c)) { setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setDelimBreak(c); breakloop = true; } else if (isDelimiterStart(c)) { setDelimBreak(c); breakloop = true; } else if (isLetter(c)) { setState(TYPE_ILLEGAL); saveChar(c); } else if (isDigit(c)) { saveChar(c); } else { setState(TYPE_ILLEGAL); saveChar(c); } } break; // end TYPE_NUMBER case TYPE_EXPONENT: { if (isStreamEnd(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isExponentSign(c)) { setState(TYPE_EXPONENT_POWER); saveChar(c); } else if (isSpecialStart(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isDelimiterStart(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isLetter(c)) { setState(TYPE_ILLEGAL); saveChar(c); } else if (isDigit(c)) { setState(TYPE_EXPONENT_POWER); saveChar(c); } else { setState(TYPE_ILLEGAL); saveChar(c); } } break; // end TYPE_EXPONENT case TYPE_EXPONENT_POWER: { if (isStreamEnd(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isSpecialStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else if (isDigit(c)) { saveChar(c); } else if (isDelimiterStart(c)) { setState(TYPE_NUMBER); setDelimBreak(c); breakloop = true; } else { setState(TYPE_ILLEGAL); saveChar(c); } } break; // end TYPE_EXPONENT_POWER case TYPE_STRING: { if (isStreamEnd(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isNewline(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else if (isStringEnd(c)) { breakloop = true; } else if (isStringEscape(c)) { c = readChar(); if (isStringEnd(c)) saveChar(c); else if (isStringEscape(c)) saveChar(c); else switch (c) { case '0': saveChar('\0'); break; case 'b': saveChar('\b'); break; case 't': saveChar('\t'); break; case 'n': saveChar('\n'); break; case 'f': saveChar('\f'); break; case 'r': saveChar('\r'); break; case '/': saveChar('/'); break; case 'u': { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 4; i++) { c = readChar(); if (!isHexDigit(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else sb.append(c); } if (!breakloop) { saveChar((char) (Integer.parseInt(sb.toString(), 16) & 0x0ffff)); } } break; case 'x': { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 2; i++) { c = readChar(); if (!isHexDigit(c)) { setState(TYPE_ILLEGAL); setDelimBreak(c); breakloop = true; } else sb.append(c); } if (!breakloop) { saveChar((char) (Integer.parseInt(sb.toString(), 16) & 0x0ff)); } } break; } } else { saveChar(c); } } break; // end TYPE_STRING case TYPE_DELIMITER: { if (isStreamEnd(c)) { setDelimBreak(c); breakloop = true; } else if (kernel.getCommentStartTable().containsKey(getCurrentLexeme() + c)) { clearCurrentLexeme(); setState(TYPE_COMMENT); } else if (kernel.getCommentLineTable().containsKey(getCurrentLexeme() + c)) { clearCurrentLexeme(); setState(TYPE_LINE_COMMENT); } else if (kernel.getDelimTable().containsKey(getCurrentLexeme() + c)) { saveChar(c); } else if (isNewline(c)) { setDelimBreak(c); breakloop = true; } else if (isSpace(c)) { setDelimBreak(c); breakloop = true; } else if (isTab(c)) { setDelimBreak(c); breakloop = true; } else if (isWhitespace(c)) { setDelimBreak(c); breakloop = true; } else if (isSpecialStart(c)) { setDelimBreak(c); breakloop = true; } else if (isStringStart(c)) { setDelimBreak(c); breakloop = true; } else { setDelimBreak(c); breakloop = true; } } break; // end TYPE_DELIMITER case TYPE_COMMENT: { if (isStreamEnd(c)) { clearCurrentLexeme(); setState(TYPE_UNKNOWN); } else if (kernel.getCommentEndTable().containsKey(getCurrentLexeme())) { clearCurrentLexeme(); setState(TYPE_UNKNOWN); } else if (isCommentEndDelimiterStart(c)) { setState(TYPE_DELIM_COMMENT); saveChar(c); } } break; // end TYPE_COMMENT case TYPE_DELIM_COMMENT: { if (isStreamEnd(c)) { clearCurrentLexeme(); setState(TYPE_COMMENT); } else if (kernel.getCommentEndTable().containsKey(getCurrentLexeme() + c)) { clearCurrentLexeme(); setState(TYPE_UNKNOWN); } else if (isWhitespace(c)) { clearCurrentLexeme(); setState(TYPE_COMMENT); } else { clearCurrentLexeme(); saveChar(c); } } break; // end TYPE_DELIM_COMMENT case TYPE_LINE_COMMENT: { if (isStreamEnd(c)) { clearCurrentLexeme(); setState(TYPE_UNKNOWN); } else if (isNewline(c)) { clearCurrentLexeme(); setState(TYPE_UNKNOWN); } } break; // end TYPE_DELIM_COMMENT } } // send token. int type = getState(); String lexeme = getCurrentLexeme(); clearCurrentLexeme(); switch (getState()) { case TYPE_DELIM_SPACE: { type = TYPE_DELIM_SPACE; lexeme = " "; } break; case TYPE_DELIM_TAB: { type = TYPE_DELIM_TAB; lexeme = "\t"; } break; case TYPE_DELIM_NEWLINE: { type = TYPE_DELIM_NEWLINE; lexeme = ""; } break; case TYPE_DELIMITER: { type = TYPE_DELIMITER; if (kernel.getCommentStartTable().containsKey(lexeme)) type = kernel.getCommentStartTable().get(lexeme); else if (kernel.getCommentEndTable().containsKey(lexeme)) type = kernel.getCommentEndTable().get(lexeme); else if (kernel.getCommentLineTable().containsKey(lexeme)) type = kernel.getCommentLineTable().get(lexeme); else if (kernel.getDelimTable().containsKey(lexeme)) type = kernel.getDelimTable().get(lexeme); } break; case TYPE_IDENTIFIER: { type = TYPE_IDENTIFIER; if (kernel.getKeywordTable().containsKey(lexeme)) type = kernel.getKeywordTable().get(lexeme); else if (kernel.getCaseInsensitiveKeywordTable().containsKey(lexeme)) type = kernel.getCaseInsensitiveKeywordTable().get(lexeme); } break; case TYPE_SPECIAL: type = specialType; break; } Token out = null; if (getState() != TYPE_END_OF_LEXER) { out = makeToken(type, lexeme); setState(TYPE_UNKNOWN); } if (DEBUG) System.out.println(out); return out; } /** * Reads the next character. * * @return the character read, or {@link #END_OF_LEXER} if no more characters. * @throws IOException if a token cannot be read by the underlying Reader. */ protected char readChar() throws IOException { if (streamStack.isEmpty()) return END_OF_LEXER; return streamStack.peek().readChar(); } /** @return the current state. */ protected int getState() { return state; } /** * Sets the current state. * * @param state the new state. */ protected void setState(int state) { this.state = state; } /** @return if we are in a delimiter break. */ protected boolean isOnDelimBreak() { return delimBreak; } /** Clears if we are in a delimiter break. */ protected void clearDelimBreak() { delimBreak = false; } /** * Sets if we are in a delimiter break. * * @param delimChar the delimiter character that starts the break. */ protected void setDelimBreak(char delimChar) { delimBreakChar = delimChar; delimBreak = true; } /** * Saves a character for the next token. * * @param c the character to save into the current token. */ protected void saveChar(char c) { builder.append(c); } /** * Sets the end character for a string. * * @param c the character to set. */ protected void setStringStartAndEnd(char c) { if (isStringStart(c)) stringEnd = getStringEnd(c); } /** * Sets and looks up the special type using a delimiter character. * * @param c the character to use. */ protected void setSpecialType(char c) { if (isSpecialStart(c)) specialType = getSpecialType(c); } /** * Gets the current token lexeme. * * @return the current contents of the token lexeme builder buffer. */ protected String getCurrentLexeme() { return builder.toString(); } /** Clears the current token lexeme buffer. */ protected void clearCurrentLexeme() { builder.delete(0, builder.length()); } /** * Creates a new token using the current stream name, line, and line number. * * @param type the token type to apply. * @param lexeme the token's lexeme. * @return a new Token object. */ protected Token makeToken(int type, String lexeme) { return new Token( streamStack.peek().streamName, lexeme, streamStack.peek().line, streamStack.peek().lineNum, type); } /** * Convenience method for <code>c == '_'</code>. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isUnderscore(char c) { return c == '_'; } /** * Convenience method for {@link Character#isLetter(char)}. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isLetter(char c) { return Character.isLetter(c); } /** * Convenience method for {@link Character#isDigit(char)}. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isDigit(char c) { return Character.isDigit(c); } /** * Returns true if this is a hex digit (0-9, A-F, a-f). * * @param c the character to test. * @return true if so, false if not. */ protected boolean isHexDigit(char c) { return (c >= 0x0030 && c <= 0x0039) || (c >= 0x0041 && c <= 0x0046) || (c >= 0x0061 && c <= 0x0066); } /** * Convenience method for {@link Character#isWhitespace(char)}. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isWhitespace(char c) { return Character.isWhitespace(c); } /** * Checks if a character is a decimal point (depends on locale/kernel). * * @param c the character to test. * @return true if so, false if not. */ protected boolean isPoint(char c) { return kernel.getDecimalSeparator() == c; } /** * Checks if char is the exponent character in a number. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isExponent(char c) { return c == 'E' || c == 'e'; } /** * Checks if char is the exponent sign character in a number. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isExponentSign(char c) { return c == '+' || c == '-'; } /** * Checks if a char is a space. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isSpace(char c) { return c == ' '; } /** * Checks if a char is a tab. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isTab(char c) { return c == '\t'; } /** * Checks if this is a character that is a String escape character. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isStringEscape(char c) { return c == '\\'; } /** * Checks if this is a character that starts a String. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isStringStart(char c) { return kernel.getStringDelimTable().containsKey(c); } /** * Checks if this is a character that starts a special token. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isSpecialStart(char c) { return kernel.getSpecialDelimTable().containsKey(c); } /** * Checks if this is a character that ends a String. * * @param c the character to test. * @return true if so, false if not. */ protected boolean isStringEnd(char c) { return stringEnd == c; } /** * Gets the character that ends a String, using the starting character. * * @param c the starting character. * @return the corresponding end character, or the null character ('\0') if this does not end a * string. */ protected char getStringEnd(char c) { if (!isStringStart(c)) return '\0'; return kernel.getStringDelimTable().get(c); } /** * Gets the special type for a special char. * * @param c the character input. * @return the corresponding type, or {@link LexerKernel#TYPE_UNKNOWN} if no type. */ protected int getSpecialType(char c) { if (!kernel.getSpecialDelimTable().containsKey(c)) return TYPE_UNKNOWN; return kernel.getSpecialDelimTable().get(c); } /** * Checks if this is a (or the start of a) delimiter character. * * @param c the character input. * @return true if so, false if not. */ protected boolean isDelimiterStart(char c) { return kernel.getDelimStartTable().contains(c); } /** * Checks if this is a (or the start of a) block-comment-ending delimiter character. * * @param c the character input. * @return true if so, false if not. */ protected boolean isCommentEndDelimiterStart(char c) { return kernel.getEndCommentDelimStartTable().contains(c); } /** * Checks if a char equals {@link #END_OF_STREAM}. * * @param c the character input. * @return true if so, false if not. */ protected boolean isStreamEnd(char c) { return c == END_OF_STREAM; } /** * Checks if a char equals {@link #END_OF_LEXER}. * * @param c the character input. * @return true if so, false if not. */ protected boolean isLexerEnd(char c) { return c == END_OF_LEXER; } /** * Checks if a char equals {@link #NEWLINE}. * * @param c the character input. * @return true if so, false if not. */ protected boolean isNewline(char c) { return c == NEWLINE; } /** * Adds a preprocessor error message to error list along with the current token's information * (like line number, etc.). * * @param errorMessage the error message. * @param lexeme the current lexeme. */ protected void addPreprocessorErrorMessage(String errorMessage, String lexeme) { String error = "(" + getCurrentStreamName() + ") " + "Line " + (streamStack.peek().lineNum) + ", Token \"" + lexeme + "\": " + errorMessage; preprocessorErrorList.add(error); } /** * Gets the list of error messages. * * @return an array of error messages. */ public String[] getErrorMessages() { String[] out = new String[preprocessorErrorList.size()]; int i = 0; for (String s : preprocessorErrorList) out[i++] = s; return out; } /** Lexer token object. */ public static class Token { private String streamName; private String lexeme; private String lineText; private int tokenLine; private int type; private Token(String streamName, String lexeme, String lineText, int tokenLine, int type) { this.streamName = streamName; this.lexeme = lexeme; this.lineText = lineText; this.tokenLine = tokenLine; this.type = type; } /** @return the name of the stream that this token came from. */ public String getStreamName() { return streamName; } /** @return this token's lexeme. */ public String getLineText() { return lineText; } /** @return the line number within the stream that this token appeared. */ public int getLine() { return tokenLine; } /** @return this token's lexeme. */ public String getLexeme() { return lexeme; } /** @return this token's type. */ public int getType() { return type; } /** * Sets this token's type. * * @param type a type corresponding to a type in the lexer or lexer kernel. */ public void setType(int type) { this.type = type; } @Override public String toString() { return "TOKEN (" + streamName + ") id: " + type + "\t Line: " + tokenLine + "\tLexeme: " + lexeme; } } /** Stream encapsulation object. */ protected class Stream { /** Name of the stream. */ private String streamName; /** The InputStreamReader. */ private BufferedReader reader; /** The current line. */ private String line; /** The current line number. */ private int lineNum; /** The current character number. */ private int charNum; /** * Creates a new stream. * * @param name the stream name. * @param in the reader used. */ protected Stream(String name, Reader in) { streamName = name; reader = new BufferedReader(in); line = null; lineNum = 0; charNum = 0; } /** @return the stream name. */ public String getStreamName() { return streamName; } /** * Reads a character from the stream. * * @return the read character or {@link Lexer#END_OF_STREAM} if no more characters. * @throws IOException if a character cannot be read. */ public char readChar() throws IOException { if (line == null || charNum == line.length()) { line = reader.readLine(); lineNum++; if (line != null) line += '\n'; charNum = 0; } if (line != null) return line.charAt(charNum++); else return END_OF_STREAM; } } }
public Double readFrom(RESPReader reader) { String out = reader.readString(); return out != null ? Common.parseDouble(out) : null; }
public boolean[] readFrom(RESPReader reader) { String[] ret = ReturnType.ARRAY.readFrom(reader); boolean[] out = new boolean[ret.length]; for (int i = 0; i < ret.length; i++) out[i] = Common.parseLong(ret[i]) != 0; return out; }