📄 lexer.java
字号:
private void scanMacroStatement(CharBuffer macro, int end, boolean isRegexp, boolean multiline) throws ESParseException { int ch; while ((ch = read()) >= 0 && ch != end) { macro.append((char) ch); switch (ch) { case '\\': ch = read(); macro.append((char) ch); break; case '\'': case '"': int testch = ch; while ((ch = read()) >= 0) { if (ch == '\\') { macro.append((char) ch); ch = read(); } else if (ch == testch) { macro.append((char) ch); break; } else if (ch == '\n') { if (! multiline) throw error("unexpected end of line in " + (isRegexp ? "regular expression" : "string")); newline(); } macro.append((char) ch); } break; case '(': scanMacroStatement(macro, ')', isRegexp, multiline); macro.append(')'); break; case '{': scanMacroStatement(macro, '}', isRegexp, multiline); macro.append('}'); break; case '\n': if (! multiline) throw error("unexpected end of line in " + (isRegexp ? "regular expression" : "string")); newline(); break; default: break; } } } private void interpolate(CharBuffer macro, int tail, String matchText, String beginStr, String endStr, boolean isRegexp, boolean multiline) throws ESParseException { int ch = read(); int ch1; macro.append(beginStr); int start = macro.length(); loop: for (; ch >= 0; ch = read()) { switch (ch) { case '\\': macro.append((char) ch); ch = read(); if (ch != -1) macro.append((char) ch); break; case '$': if ((ch = read()) == -1) break; if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch == '$') { macro.append(endStr); macro.append("+("); macro.append((char) ch); while ((ch = read()) >= 0 && (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '$') { macro.append((char) ch); } ungetc(ch); macro.append(")+"); macro.append(beginStr); } else if (ch == '{') { macro.append(endStr); macro.append("+("); scanMacroStatement(macro, '}', isRegexp, multiline); macro.append(")+"); macro.append(beginStr); } else if (ch == '(') { macro.append(endStr); macro.append("+("); scanMacroStatement(macro, ')', isRegexp, multiline); macro.append(")+"); macro.append(beginStr); } else { ungetc(ch); macro.append('$'); } break; default: if (ch == '\n') { newline(); if (! multiline) throw error("unexpected end of line in " + (isRegexp ? "regular expression" : "string")); } if (ch != tail) { } else if (matchText == null) { break loop; } else if (! macro.endsWith(matchText)) { } else if (macro.length() - start == matchText.length()) { macro.setLength(start); break loop; } else if (macro.charAt(macro.length() - matchText.length() - 1) == '\n') { macro.setLength(macro.length() - matchText.length() - 1); break loop; } macro.append((char) ch); break; } } macro.append(endStr); } private boolean scanMultiline() throws ESParseException { int ch; CharBuffer end = new CharBuffer(); boolean interpolate = true; boolean endNewline = true; if ((ch = read()) >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch == '$') { for (; ch >= 0 && ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch == '$' || ch >= '0' && ch <= '9'; ch = read()) { end.append((char) ch); } } else if (ch == '\'') { interpolate = false; for (ch = read(); ch >= 0 && ch != '\'' && ch != '\n'; ch = read()) { end.append((char) ch); } if (ch != '\'') throw error(L.l("multiline escape error at {0}", badChar(ch))); ch = read(); } else if (ch == '`') { interpolate = false; for (ch = read(); ch >= 0 && ch != '`' && ch != '\n'; ch = read()) { end.append((char) ch); } if (ch != '`') throw error(L.l("multiline escape error at {0}", badChar(ch))); endNewline = false; } else if (ch == '\"') { for (ch = read(); ch >= 0 && ch != '\"' && ch != '\n'; ch = read()) { end.append((char) ch); } if (ch != '\"') throw error(L.l("multiline escape error at {0}", badChar(ch))); ch = read(); } int oldLine = line; CharBuffer lineTail = null; if (endNewline) { lineTail = new CharBuffer(); for (; ch >= 0 && ch != '\n'; ch = read()) { lineTail.append((char) ch); } if (ch == '\r') { lineTail.append((char) ch); ch = read(); } if (ch == '\n') { newline(); lineTail.append((char) ch); } } CharBuffer macro = null; String endString = end.toString(); if (interpolate) { macro = new CharBuffer(); macro.append('('); interpolate(macro, '\n', endString, "@<<`" + endString + "`", "\n" + endString + '\n', false, true); macro.append("+'\\n')"); } else { if (endNewline) { lexString('\n', endString, false, true); text.append('\n'); literal = ESString.create(text); } else { lexString('\n', endString, false, true); line -= 2; } } if (endNewline) { pushMacro(lineTail); line = oldLine; } if (interpolate) { pushMacro(macro); line++; return false; } else return true; } private int readRegexpFlags() throws ESParseException { int ch; while (true) { switch ((ch = read())) { case 'x': _flags |= Pattern.COMMENTS; break; case 'i': _flags |= Pattern.CASE_INSENSITIVE; break; case 'g': break; case 'm': _flags |= Pattern.MULTILINE; break; case 's': break; default: ungetc(ch); return _flags; } } } /** * Lexeme for an Id. Reserved words are looked up in a * HashMap. */ private int lexId(int ch) throws ESParseException { text.setLength(0); text.append((char) ch); while (true) { ch = read(); if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch == '$' || ch >= '0' && ch <= '9') { text.append((char) ch); } else { ungetc(ch); break; } } Integer value = (Integer) reserved.get(text); if (value == null) { id = ESId.intern(text.toString()); return IDENTIFIER; } else { int intValue = value.intValue(); switch (intValue) { case NULL: literal = ESBase.esNull; return LITERAL; case UNDEFINED: literal = ESBase.esUndefined; return LITERAL; case FALSE: literal = ESBoolean.create(false); return LITERAL; case TRUE: literal = ESBoolean.create(true); return LITERAL; default: return value.intValue(); } } } /** * Lexeme for an operation */ private int lexOp(int ch) throws ESParseException { text.setLength(0); text.append((char) ch); loop: while ((ch = read()) >= 0) { switch (ch) { case '+': case '-': case '*': case '/': case '%': case '!': case '<': case '.': case '>': case '&': case '|': case '=': case '^': case '?': text.append((char) ch); op = (Op) ops.get(text); if (op == null) { text.setLength(text.length() - 1); ungetc(ch); break loop; } break; default: ungetc(ch); break loop; } } op = (Op) ops.get(text); // XXX: non-reachable if (op == null) throw error(L.l("expected operator at `{0}'", text.toString())); return op.lexeme; } /** * Return the operation for a lexeme. Binary operations like '*' will * return BIN_OP as the lexeme. Calling getOp() will get the actual * operation. */ int getOp() { return op.op; } int getPrecedence() { return op.precedence; } boolean isRightAssoc() { return op.isRightAssoc; } ESBase getLiteral() { return literal; } int getFlags() { return _flags; } private void scanLine(int ch) throws ESParseException { for (; ch == ' ' || ch == '\t'; ch = read()) { } if (ch < '0' || ch > '9') throw error(L.l("expected digit at {0}", badChar(ch))); line = 0; for (; ch >= '0' && ch <= '9'; ch = read()) line = 10 * line + ch - '0'; for (; ch == ' ' || ch == '\t'; ch = read()) { } if (ch != '#') throw error(L.l("expected `#' at {0}", badChar(ch))); } private void scanFile(int ch) throws ESParseException { for (; ch == ' ' || ch == '\t'; ch = read()) { } temp.clear(); for (; ch >= 0 && ch != ' ' && ch != '\t' && ch != '#'; ch = read()) temp.append((char) ch); if (temp.length() == 0) throw error(L.l("expected filename at {0}", badChar(ch))); filename = temp.toString(); for (; ch == ' ' || ch == '\t'; ch = read()) { } line = 0; for (; ch >= '0' && ch <= '9'; ch = read()) line = 10 * line + ch - '0'; if (line == 0) line = 1; for (; ch == ' ' || ch == '\t'; ch = read()) { } if (ch != '#') throw error(L.l("expected `#' at {0}", badChar(ch))); } /** * Reads the next character. */ private int read() throws ESParseException { lineCh++; if (peek >= 0) { int ch = peek; peek = peek2; peek2 = -1; return ch; } while (macroText != null) { if (macroIndex < macroText.length()) { int ch = macroText.charAt(macroIndex++); lineText.append((char) ch); return ch; } line = macroOldLine; if (macros.size() == 0) macroText = null; else { Macro macro = (Macro) macros.remove(macros.size() - 1); macroText = macro.text; macroIndex = macro.index; macroOldLine = macro.oldLine; } } try { int ch = is.readChar(); if (ch == '\r') { ch = is.readChar(); if (ch != '\n') { if (ch == '\r') peek = '\n'; else peek = ch; } ch = '\n'; } lineText.append((char) ch); return ch; } catch (CharConversionException e1) { throw error(L.l("expected {0} encoded character", is.getEncoding())); } catch (IOException e1) { throw new ESParseException(e1); } } private void ungetc(int ch) { peek2 = peek; peek = ch; if (lineCh > 0) lineCh--; /* if (ch == '\n') line--; */ } static class Op { int op; int lexeme; int precedence; boolean isRightAssoc; Op(int op, int lexeme, int precedence, boolean isRightAssoc) { this.op = op; this.lexeme = lexeme; this.precedence = precedence; this.isRightAssoc = isRightAssoc; } }; class Macro { CharBuffer text; int index; int oldLine; void clear() { text.clear(); index = 0; } Macro(CharBuffer cb, int index, int oldLine) { this.text = cb; this.index = index; this.oldLine = oldLine; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -