📄 parsedmessage.java
字号:
package ergo.util;
// $Id: ParsedMessage.java,v 1.3 1999/08/13 01:20:43 sigue Exp $
/*
* Copyright (C) 1999 Carl L. Gay and Antranig M. Basman.
* See the file copyright.txt, distributed with this software,
* for further information.
*/
import java.util.Vector;
/**
* ParsedMessage class. A lot less powerful than full regular
* expressions, but enough for my purposes and easier to use and
* faster than the regexp code I found on the net.
*
* Usage: ParsedMessage m = new ParsedMessage("Revision: 1.4", "\s \f");
* float revision = (float) m.matchAt(1);
*
* Special characters in the "regular expressions":
* <space>: match a single space character.
* Note that a non-escaped space char matches zero or more space
* chars in the input string, but does NOT count as a match.
* This is almost always the right thing so it's a special case.
* a: any string of alphanumeric characters
* c: any single character
* f: Matches a simple floating point number (no exponents, no + sign,
* no error checking)
* i: Matches an integer
* r: Matches rest of input string
* s: any string of non-whitespace characters
* w: a word. this is a totally random conglomeration of chars
* that happened to be useful to me. In particular, it includes '*'.
* <escape-char>: Matches the escape character.
*/
public class ParsedMessage {
public String message;
public int endIndex = 0;
private char escapeChar = '%';
private Vector fields = new Vector();
// Basic constructor, only specifies an input message and a "regexp"
public ParsedMessage (String msg, String regexp) throws ParseException {
parse(msg, regexp, Integer.MAX_VALUE);
}
// Allows the number of fields parsed to be limited to nfields.
public ParsedMessage(String msg, String regexp, int nfields) throws ParseException {
parse(msg, regexp, nfields);
}
// Allows the escape char to be specfied as well.
public ParsedMessage (String msg, String regexp, int nfields, char escape) throws ParseException {
this(msg, regexp, nfields);
escapeChar = escape;
}
public char escapeChar () {
return escapeChar;
}
private void parse (String msg, String regexp, int nfields)
throws ParseException {
message = msg;
int ml = msg.length();
int rl = regexp.length();
int mi = endIndex; // msg index
int ri = 0; // regexp index
boolean escaped = false; // last char was escape char?
for (; fields.size() < nfields; ) {
if (mi >= ml || ri >= rl) { // Why does this fail silently when we run out of characters?
// AMB at 0.6....
if (nfields < Integer.MAX_VALUE && fields.size() < nfields)
throw new ParseException("Too few fields parsed");
break;
}
char mc = msg.charAt(mi);
char rc = regexp.charAt(ri);
int cstart = mi; // current match start index
boolean firstp=false; // Is this the first character of a match?
if (rc == escapeChar) { // first match the escaped escape character itself...
// I suspect this case could be handled more concisely...
if (escaped) {
if (rc != mc)
throw new ParseException("No Match at " + mi
+ ". Expected '"
+ rc + "'. Got '" + mc + "'.");
else
mi++;
}
else
escaped = true;
}
else if (!escaped) { // not matching escape char, and not escaped....
if (rc == ' ') { // Match whitespace (but don't add a field!)
for (; mi < ml && Character.isWhitespace(msg.charAt(mi)); )
mi++;
}
else {
if (rc != mc) // literal character match?
throw new ParseException("No match at " + mi
+ ". Expected '"
+ rc + "'. Got '" + mc + "'.");
mi++;
}
escaped = false;
}
else { // escaped == true
switch (rc) {
case 'i': // Parse an integer.
for (firstp = true; mi < ml; mi++) {
mc = msg.charAt(mi);
if(! (Character.isDigit(mc) || (firstp && mc == '-')))
break;
firstp = false;
}
if (cstart == mi) // nothing changed
throw new ParseException("No match at " + mi
+ ". Integer expected.");
try {
fields.addElement(new Integer(msg.substring(cstart, mi)));
} catch (NumberFormatException nfe) {
throw new ParseException("No match at " + mi
+ ". Integer expected.");
}
//Debug.println("I: " + fields.elementAt(fields.size() - 1));
break;
case 'f': // simple floating point number.
for (firstp = true; mi < ml; mi++) {
mc = msg.charAt(mi);
if (! (Character.isDigit(mc) || mc == '.' || (firstp && mc == '-')))
break;
firstp = false;
}
if (cstart == mi) // nothing changed
throw new ParseException("No match at " + mi
+ ". Simple float expected.");
try {
fields.addElement(new Double(msg.substring(cstart, mi)));
} catch (NumberFormatException nfe) {
throw new ParseException("No match at " + mi
+ ". Integer expected.");
}
//Debug.println("F: " + fields.elementAt(fields.size() - 1));
break;
case 'c': // Match any single character.
fields.addElement(new Character(mc));
mi++;
//Debug.println("C: " + mc);
break;
case 'a': // Parse a word. (alphanumeric)
for (; mi < ml && Character.isLetterOrDigit(msg.charAt(mi)); mi++) {}
if (cstart == mi)
throw new ParseException("No match at " + mi
+ ". Alphanumeric expected.");
fields.addElement(msg.substring(cstart, mi));
//Debug.println("A: " + fields.elementAt(fields.size() - 1));
break;
case 's': // Parse a string of non-white chars.
for (; mi < ml && !Character.isWhitespace(msg.charAt(mi)); mi++) {}
if (cstart == mi)
throw new ParseException("No match at " + mi
+ ". Non-whitespace string expected.");
fields.addElement(msg.substring(cstart, mi));
break;
case 'w': // Parse a "word" (something useful for NNGS)
for (; mi < ml; mi++) {
mc = msg.charAt(mi);
if (! (Character.isLetterOrDigit(mc) || mc == '*'))
break;
}
if (cstart == mi)
throw new ParseException("No match at " + mi
+ ". Word expected.");
fields.addElement(msg.substring(cstart, mi));
//Debug.println("W: " + fields.elementAt(fields.size() - 1));
break;
case ' ': // Literal match a single space char
if (mc != ' ')
throw new ParseException("No match at " + mi
+ ". Expected ' ', got '"
+ mc + "'.");
mi++;
break;
case 'r': // Rest of message. Consumes none of message.
fields.addElement(msg.substring(mi));
mi = ml;
//Debug.println("R: " + fields.elementAt(fields.size() - 1));
break;
default:
throw new ParseException("Unrecognized escape sequence: "
+ escapeChar + rc);
} // switch
escaped = false; // done processing escape sequence.
}
ri++;
}
endIndex = mi;
}
/**
* Return a parsed field object.
*/
public String stringAt (int fieldnum) throws ParseException {
Object o = matchAt(fieldnum);
return o.toString();
}
public int intAt (int fieldnum) throws ParseException {
Object o = matchAt(fieldnum);
if (! (o instanceof Integer))
throw new ParseException("Illegal field access - not an Integer.");
return ((Integer)o).intValue();
}
public double doubleAt (int fieldnum) throws ParseException {
Object o = matchAt(fieldnum);
if (! (o instanceof Double))
throw new ParseException("Illegal field access - not a Double.");
return ((Double)o).doubleValue();
}
public Object matchAt (int fieldnum) throws ParseException {
if (fieldnum >= fields.size())
throw new ParseException("Illegal field access - asked for "
+ fieldnum + ".");
return fields.elementAt(fieldnum);
}
/**
* Continue parsing this message where we left off the last
* time, but with a new parse string.
*/
public void continueParse (String regexp) throws ParseException {
parse(message, regexp, Integer.MAX_VALUE);
}
public ParsedMessage continueParseQuietly (String regexp) {
try {
parse(message, regexp, Integer.MAX_VALUE);
return this;
}
catch (ParseException pe) {
// System.out.println(pe);
}
return null;
}
/**
* Same as above but allow the user to specify the number of
* fields in the regular expression that should be used.
*/
public void continueParse (String regexp, int nfields) throws ParseException {
parse(message, regexp, nfields);
}
/**
* Return any part of the message that has not yet been parsed.
*/
public String rest () {
return message.substring(endIndex);
}
public String message () {
return message;
}
public int endIndex () {
return endIndex;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -