📄 lexer.java
字号:
macro.append('('); interpolate(macro, '"', null, "\"", "\"", false, false); macro.append(')'); pushMacro(macro); break; case '\'': macro = new CharBuffer(); macro.append('('); interpolate(macro, '\'', null, "\'", "\'", false, false); macro.append(')'); pushMacro(macro); break; case '@': if ((ch2 = read()) < 0) throw error(L.l("unexpected end of file")); switch (ch2) { case '{': ch2 = '}'; break; case '<': ch2 = '>'; break; case '(': ch2 = ')'; break; case '[': ch2 = ']'; break; } return lexString((char) ch2, null, true, false); case '<': if ((ch2 = read()) != '<') throw error(L.l("illegal character at `@'")); if (scanMultiline()) return LITERAL; break; case '/': macro = new CharBuffer(); macro.append("new RegExp("); interpolate(macro, '/', null, "@@/", "/", true, false); macro.append(","); macro.append(readRegexpFlags()); macro.append(")"); pushMacro(macro); break; default: return lexOp('@'); } break; } case '%': { int ch2 = read(); regexpOk = true; ungetc(ch2); return lexOp(ch); } case '#': { int ch2 = read(); if (line == 1 && lineCh == 2 && ch2 == '!') { for (; ch2 > 0 && ch2 != '\n'; ch2 = read()) { } ungetc(ch2); break; } if (ch2 >= 'a' && ch2 <= 'z' || ch2 >= 'A' && ch2 <= 'Z') { temp.clear(); for (; ch2 >= 'a' && ch2 <= 'z' || ch2 >= 'A' && ch2 <= 'Z'; ch2 = read()) { temp.append((char) ch2); } if (temp.toString().equals("line")) scanLine(ch2); else if (temp.toString().equals("file")) scanFile(ch2); else throw error(L.l("expected pragma at `{0}'", temp)); break; } if (ch2 < '0' || ch2 > '9') throw error(L.l("expected digit at {0}", badChar(ch2))); intValue = 0; for (; ch2 >= '0' && ch2 <= '9'; ch2 = read()) intValue = 10 * intValue + ch2 - '0'; if (ch2 == '=') return HASH_DEF; else if (ch2 == '#') return HASH_REF; else throw error(L.l("expected sharp variable at {0}", badChar(ch))); } default: if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch == '$') { regexpOk = false; return lexId(ch); } else { throw error(L.l("illegal character at {0}", badChar(ch))); } } } } /** * Returns the text object for the lexeme. */ CharBuffer getText() { return text; } boolean isEof() { return isEof; } /** * Used for error messages. */ String getToken() { return lineText.substring(beginLineCh, lineCh); } /** * Returns the Id */ ESId getId() { return id; } /** * Returns true if seen linefeed since the last. */ boolean seenLineFeed() { return hasLf; } ESParseException error(String text) { return new ESParseException(filename, beginLine, beginLineCh, line, lineCh, text); } private String hex(int value) { CharBuffer cb = new CharBuffer(); for (int b = 3; b >= 0; b--) { int v = (value >> (4 * b)) & 0xf; if (v < 10) cb.append((char) (v + '0')); else cb.append((char) (v - 10 + 'a')); } return cb.toString(); } private String badChar(int ch) { if (ch >= 0x20 && ch <= 0x7f) return "`" + (char) ch + "'"; else if (ch == '\n') return L.l("end of line"); else if (ch == -1) return L.l("end of file"); else return "`" + (char) ch + "' (\\u" + hex(ch) + ")"; } String getFilename() { if (lineMap != null) { LineMap.Line map = lineMap.getLine(line); if (map != null) return map.getSourceFilename(); } return filename; } long getLastModified() { if (is.getPath() == null) return 0; else return is.getPath().getLastModified(); } int getLine() { if (lineMap != null) { LineMap.Line map = lineMap.getLine(line); if (map != null) { return map.getSourceLine(line); } } return line; } String getLastFilename() { if (lineMap != null) { LineMap.Line map = lineMap.getLine(lastLine); if (map != null) return map.getSourceFilename(); } return lastFilename; } int getLastLine() { if (lineMap != null) { LineMap.Line map = lineMap.getLine(lastLine); if (map != null) { return map.getSourceLine(lastLine); } } return lastLine; } private void pushMacro(CharBuffer cb) throws ESParseException { if (peek >= 0) cb.append((char) read()); // Because of peek if (peek >= 0) cb.append((char) read()); // Because of peek if (macroText != null) macros.add(new Macro(macroText, macroIndex, macroOldLine)); macroText = cb; macroIndex = 0; macroOldLine = line; } /** * Update variables to handle a newline. */ private void newline() { line++; lineCh = 0; lineText.clear(); } /** * Handles all the goodies for a floating point number after the * dot or 'e' */ private int lexFloat(double value, int ch) throws ESParseException { int expt = 0; for (; ch >= '0' && ch <= '9'; ch = read()) { value = 10 * value + ch - '0'; expt--; } if (ch == 'e' || ch == 'E') { ch = read(); int sign = 1; if (ch == '-') { sign = -1; ch = read(); } else if (ch == '+') { ch = read(); } if (ch < '0' || ch > '9') throw error(L.l("expected exponent at {0}", badChar(ch))); int userExpt = 0; for (; ch >= '0' && ch <= '9'; ch = read()) { userExpt = 10 * userExpt + ch - '0'; } expt += sign * userExpt; } ungetc(ch); if (expt >= 0) literal = ESNumber.create(value * Math.pow(10, expt)); else literal = ESNumber.create(value / Math.pow(10, -expt)); return LITERAL; } /** * Lexeme for a number */ private int lexNumber(int ch) throws ESParseException { int radix = 10; double value = 0; boolean hasChar = true; if (ch == '0') { ch = read(); if (ch >= '0' && ch <= '9') radix = 8; else if (ch == 'x' || ch == 'X') { hasChar = false; radix = 16; ch = read(); } } for (; ch >= 0; ch = read()) { if (ch >= '0' && ch <= '9') { value = radix * value + ch - '0'; hasChar = true; if (radix == 8 && ch >= '8') throw error(L.l("expected octal digit at {0}", badChar(ch))); } else if (radix == 16 && ch >= 'a' && ch <= 'f') { hasChar = true; value = radix * value + ch - 'a' + 10; } else if (radix == 16 && ch >= 'A' && ch <= 'F') { hasChar = true; value = radix * value + ch - 'A' + 10; } else break; } if (! hasChar) throw error(L.l("expected hex digit at {0}", badChar(ch))); if (radix == 10 && ch == '.') { ch = read(); if (ch >= '0' && ch <= '9') return lexFloat(value, ch); else { ungetc(ch); literal = ESNumber.create(value); return LITERAL; } } else if (radix == 10 && (ch == 'e' || ch == 'E')) return lexFloat(value, ch); else { ungetc(ch); literal = ESNumber.create(value); return LITERAL; } } /** * Returns the number for a hex digit. */ private int hexDigit(int ch) throws ESParseException { if (ch >= '0' && ch <= '9') return ch - '0'; else if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10; else if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10; else throw error(L.l("expected hex digit at {0}", badChar(ch))); } /** * Lexeme for a string. */ private int lexString(char endCh, String endTail, boolean isRegexp, boolean isMultiline) throws ESParseException { text.setLength(0); int ch = read(); for (; ch >= 0; ch = read()) { if (ch == '\n') { if (isMultiline) { } else if (isRegexp) throw error(L.l("unexpected end of line in regular expression")); else throw error(L.l("unexpected end of line in string")); newline(); } if (ch != endCh) { } else if (endTail == null) { literal = ESString.create(text.toString()); return LITERAL; } else if (! text.endsWith(endTail)) { } else if (text.length() == endTail.length()) { literal = ESString.create(""); return LITERAL; } else { char tailCh = text.charAt(text.length() - endTail.length() - 1); if (tailCh == '\n') { text.setLength(text.length() - endTail.length() - 1); literal = ESString.create(text.toString()); return LITERAL; } } if (ch == '\\') { ch = read(); switch (ch) { case -1: if (isRegexp) throw error(L.l("unexpected end of file in regular expression")); else throw error(L.l("unexpected end of file in string")); case '\n': if (isRegexp) throw error(L.l("unexpected end of line in regular expression")); else throw error(L.l("unexpected end of line in string")); case 'b': if (isRegexp) text.append("\\b"); else text.append('\b'); break; case 'e': text.append((char) 0x1b); break; case 'f': text.append('\f'); break; case 'n': text.append('\n'); break; case 'r': text.append('\r'); break; case 't': text.append('\t'); break; case 'v': text.append((char) 0xb); break; case 'c': { ch = read(); if (ch >= 'a' && ch <= 'z') text.append((char) (ch - 'a' + 1)); else if (ch >= 'A' && ch <= 'Z') text.append((char) (ch - 'A' + 1)); else if (ch - '@' >= 0 && ch - '@' < ' ') text.append((char) (ch - '@')); else throw error(L.l("expected control character at {0}", badChar(ch))); } break; case 'o': { int value = 0; while ((ch = read()) >= '0' && ch <= '8') { value = 8 * value + ch - '0'; } ungetc(ch); text.append((char) value); } break; case 'x': { int value = 16 * hexDigit(read()); value += hexDigit(read()); text.append((char) value); } break; case 'u': { int value = 4096 * hexDigit(read()); value += 256 * hexDigit(read()); value += 16 * hexDigit(read()); value += hexDigit(read()); text.append((char) value); } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { int value = ch - '0'; if (ch != '0' && isRegexp) { text.append('\\'); text.append((char) ch); break; } if ((ch = read()) >= '0' && ch <= '7') { value = 8 * value + ch - '0'; if (value >= 040) { } else if ((ch = read()) >= '0' && ch <= '7') value = 8 * value + ch - '0'; else ungetc(ch); } else ungetc(ch); text.append((char) value); } break; default: if (isRegexp) text.append('\\'); text.append((char) ch); break; } } else { text.append((char) ch); } } if (ch != -1) { } else if (isRegexp) throw error(L.l("unexpected end of file in regular expression")); else throw error(L.l("unexpected end of file in string")); literal = ESString.create(text.toString()); return LITERAL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -