⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parsedmessage.java

📁 ErGo是一个很早的Java通用围棋服务器(IGS/NNGS)客户端程序。有全部源码和文档
💻 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 + -