📄 tokenizer.java
字号:
// Copyright (c) 2003-2004 Brian Wellington (bwelling@xbill.org)//// Copyright (C) 2003-2004 Nominum, Inc.// // Permission to use, copy, modify, and distribute this software for any// purpose with or without fee is hereby granted, provided that the above// copyright notice and this permission notice appear in all copies.//// THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR ANY// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT// OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.//package org.xbill.DNS;import java.io.*;import org.xbill.DNS.utils.*;/** * Tokenizer is used to parse DNS records and zones from text format, * * @author Brian Wellington * @author Bob Halley */public class Tokenizer {private static String delim = " \t\n;()\"";private static String quotes = "\"";/** End of file */public static final int EOF = 0;/** End of line */public static final int EOL = 1;/** Whitespace; only returned when wantWhitespace is set */public static final int WHITESPACE = 2;/** An identifier (unquoted string) */public static final int IDENTIFIER = 3;/** A quoted string */public static final int QUOTED_STRING = 4;/** A comment; only returned when wantComment is set */public static final int COMMENT = 5;private PushbackInputStream is;private boolean ungottenToken;private int multiline;private boolean quoting;private String delimiters;private Token current;private StringBuffer sb;private boolean wantClose;private String filename;private int line;public static class Token { /** The type of token. */ public int type; /** The value of the token, or null for tokens without values. */ public String value; private Token() { type = -1; value = null; } private Token set(int type, StringBuffer value) { if (type < 0) throw new IllegalArgumentException(); this.type = type; this.value = value == null ? null : value.toString(); return this; } /** * Converts the token to a string containing a representation useful * for debugging. */ public String toString() { switch (type) { case EOF: return "<eof>"; case EOL: return "<eol>"; case WHITESPACE: return "<whitespace>"; case IDENTIFIER: return "<identifier: " + value + ">"; case QUOTED_STRING: return "<quoted_string: " + value + ">"; case COMMENT: return "<comment: " + value + ">"; default: return "<unknown>"; } } /** Indicates whether this token contains a string. */ public boolean isString() { return (type == IDENTIFIER || type == QUOTED_STRING); } /** Indicates whether this token contains an EOL or EOF. */ public boolean isEOL() { return (type == EOL || type == EOF); }}class TokenizerException extends TextParseException { String message; public TokenizerException(String filename, int line, String message) { super(filename + ":" + line + ": " + message); this.message = message; } public String getBaseMessage() { return message; }}/** * Creates a Tokenizer from an arbitrary input stream. * @param is The InputStream to tokenize. */publicTokenizer(InputStream is) { if (!(is instanceof BufferedInputStream)) is = new BufferedInputStream(is); this.is = new PushbackInputStream(is, 2); ungottenToken = false; multiline = 0; quoting = false; delimiters = delim; current = new Token(); sb = new StringBuffer(); filename = "<none>"; line = 1;}/** * Creates a Tokenizer from a string. * @param s The String to tokenize. */publicTokenizer(String s) { this(new ByteArrayInputStream(s.getBytes()));}/** * Creates a Tokenizer from a file. * @param f The File to tokenize. */publicTokenizer(File f) throws FileNotFoundException { this(new FileInputStream(f)); wantClose = true; filename = f.getName();}private intgetChar() throws IOException { int c = is.read(); if (c == '\r') { int next = is.read(); if (next != '\n') is.unread(next); c = '\n'; } if (c == '\n') line++; return c;}private voidungetChar(int c) throws IOException { if (c == -1) return; is.unread(c); if (c == '\n') line--;}private intskipWhitespace() throws IOException { int skipped = 0; while (true) { int c = getChar(); if (c != ' ' && c != '\t') { if (!(c == '\n' && multiline > 0)) { ungetChar(c); return skipped; } } skipped++; }}private voidcheckUnbalancedParens() throws TextParseException { if (multiline > 0) throw exception("unbalanced parentheses");}/** * Gets the next token from a tokenizer. * @param wantWhitespace If true, leading whitespace will be returned as a * token. * @param wantComment If true, comments are returned as tokens. * @return The next token in the stream. * @throws TextParseException The input was invalid. * @throws IOException An I/O error occurred. */public Tokenget(boolean wantWhitespace, boolean wantComment) throws IOException { int type; int c; if (ungottenToken) { ungottenToken = false; if (current.type == WHITESPACE) { if (wantWhitespace) return current; } else if (current.type == COMMENT) { if (wantComment) return current; } else { if (current.type == EOL) line++; return current; } } int skipped = skipWhitespace(); if (skipped > 0 && wantWhitespace) return current.set(WHITESPACE, null); type = IDENTIFIER; sb.setLength(0); while (true) { c = getChar(); if (c == -1 || delimiters.indexOf(c) != -1) { if (c == -1) { if (quoting) throw exception("EOF in " + "quoted string"); else if (sb.length() == 0) return current.set(EOF, null); else return current.set(type, sb); } if (sb.length() == 0 && type != QUOTED_STRING) { if (c == '(') { multiline++; skipWhitespace(); continue; } else if (c == ')') { if (multiline <= 0) throw exception("invalid " + "close " + "parenthesis"); multiline--; skipWhitespace(); continue; } else if (c == '"') { if (!quoting) { quoting = true; delimiters = quotes; type = QUOTED_STRING; } else { quoting = false; delimiters = delim; skipWhitespace(); } continue; } else if (c == '\n') { return current.set(EOL, null); } else if (c == ';') { while (true) { c = getChar(); if (c == '\n' || c == -1) break; sb.append((char)c); } if (wantComment) { ungetChar(c); return current.set(COMMENT, sb); } else if (c == -1 && type != QUOTED_STRING) { checkUnbalancedParens(); return current.set(EOF, null); } else if (multiline > 0) { skipWhitespace(); sb.setLength(0); continue; } else return current.set(EOL, null); } else throw new IllegalStateException(); } else ungetChar(c); break; } else if (c == '\\') { c = getChar(); if (c == -1) throw exception("unterminated escape sequence"); sb.append('\\'); } else if (quoting && c == '\n') { throw exception("newline in quoted string"); } sb.append((char)c); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -