parser.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,992 行 · 第 1/3 页

JAVA
1,992
字号
    switch (token) {    case EQ:      return new EqExpr(left, parseConcatExpr());    case LT:    case LE:    case GT:    case GE:    case NE:      return new CmpExpr(left, parseConcatExpr(), token);    case BETWEEN:      {	Expr min = parseConcatExpr();	token = scanToken();	if (token != AND)	  throw error(L.l("expected AND at '{0}'", tokenName(token)));	Expr max = parseConcatExpr();	return new BetweenExpr(left, min, max, isNot);      }    case IS:      {	token = scanToken();	isNot = false;	if (token == NOT) {	  token = scanToken();	  isNot = true;	}	if (token == NULL)	  return new IsNullExpr(left, isNot);	else	  throw error(L.l("expected NULL at '{0}'", tokenName(token)));      }    case LIKE:      {	token = scanToken();	if (token == STRING)	  return new LikeExpr(left, _lexeme, isNot);	else	  throw error(L.l("expected string at '{0}'", tokenName(token)));      }    case IN:      {	HashSet<String> values = parseInValues();	return new InExpr(left, values, isNot);      }    default:      _token = token;      return left;    }  }  /**   * Parses the IN values.   */  private HashSet<String> parseInValues()    throws SQLException  {    int token = scanToken();    if (token != '(')      throw error(L.l("Expected '('"));    HashSet<String> values = new HashSet<String>();    while ((token = scanToken()) != ')') {      if (token == STRING) {	values.add(_lexeme);      }      else	throw error(L.l("expected STRING at {0}", tokenName(token)));	      if ((token = scanToken()) != ',')	break;    }    if (token != ')')	throw error(L.l("expected ')' at {0}", tokenName(token)));    return values;  }  /**   * Parses a concat expression.   */  private Expr parseConcatExpr()    throws SQLException  {    Expr left = parseAddExpr();    while (true) {      int token = scanToken();      switch (token) {      case CONCAT:	left = new ConcatExpr(left, parseAddExpr());	break;      default:	_token = token;	return left;      }    }  }  /**   * Parses a +/- expression.   */  private Expr parseAddExpr()    throws SQLException  {    Expr left = parseMulExpr();    while (true) {      int token = scanToken();      switch (token) {      case '+':      case '-':	left = new BinaryExpr(left, parseMulExpr(), token);	break;      default:	_token = token;	return left;      }    }  }  /**   * Parses a mul/div expression   */  private Expr parseMulExpr()    throws SQLException  {    Expr left = parseTerm();    while (true) {      int token = scanToken();      switch (token) {      case '*':      case '/':      case '%':	left = new BinaryExpr(left, parseTerm(), token);	break;      default:	_token = token;	return left;      }    }  }  /**   * Parses a term.   */  private Expr parseTerm()    throws SQLException  {    int token = scanToken();    switch (token) {    case '+':      return parseTerm();    case '-':      return new UnaryExpr(parseTerm(), token);    case '(':      Expr expr = parseExpr();      int peekToken;      if ((peekToken = scanToken()) != ')')	throw error(L.l("expected ')' at {0}", tokenName(peekToken)));      return expr;    default:      _token = token;      return parseSimpleTerm();    }  }  /**   * Parses a simple term.   */  private Expr parseSimpleTerm()    throws SQLException  {    int token = scanToken();    switch (token) {    case IDENTIFIER:      {	String name = _lexeme;	token = scanToken();	if (token == '.') {	  token = scanToken();	  if (token == IDENTIFIER) {	    String column = _lexeme;	    return _query.bind(name, column);	  }	  else if (token == '*') {	    return new UnboundStarExpr(name);	  }	  else	    throw error("expected IDENTIFIER");	}	else if (token == '(') {	  FunExpr fun = null;	  if (name.equalsIgnoreCase("max"))	    fun = new MaxExpr();	  else if (name.equalsIgnoreCase("min"))	    fun = new MinExpr();	  else if (name.equalsIgnoreCase("sum"))	    fun = new SumExpr();	  else if (name.equalsIgnoreCase("avg"))	    fun = new AvgExpr();	  else if (name.equalsIgnoreCase("count")) {	    fun = new CountExpr();	    token = scanToken();	    if (token == '*') {	      fun.addArg(new UnboundStarExpr());	    }	    else	      _token = token;	  }	  else if (name.equalsIgnoreCase("exists")) {	    token = scanToken();	    if (token != SELECT)	      throw error(L.l("exists requires SELECT at '{0}'",			      tokenName(token)));	    ExistsQuery query = new ExistsQuery(_database, _sql);	    parseSelect(query);	    ExistsExpr expr = new ExistsExpr(query);	    query.setSubSelect(expr);	    _andExpr.add(new ExistsEvalExpr(expr));	    token = scanToken();	    if (token != ')')	      throw error(L.l("exists requires ')' at '{0}'",			      tokenName(token)));	    return expr;	  }	  else {	    String funName = (Character.toUpperCase(name.charAt(0)) +			      name.substring(1).toLowerCase());	    funName = "com.caucho.db.fun." + funName + "Expr";	    try {	      Class cl = Class.forName(funName);	      fun = (FunExpr) cl.newInstance();	    } catch (ClassNotFoundException e) {	      log.finer(e.toString());	    } catch (Throwable e) {	      log.log(Level.FINER, e.toString(), e);	    }	    if (fun == null)	      throw error(L.l("`{0}' is an unknown function.", name));	  }	  token = scanToken();	  while (token > 0 && token != ')') {	    _token = token;	    Expr arg = parseExpr();	    fun.addArg(arg);	    token = scanToken();	    if (token == ',')	      token = scanToken();	  }	  return fun;	}	else {	  _token = token;	  return _query.bind(null, name);	}      }    case STRING:      return new StringExpr(_lexeme);    case DOUBLE:    case INTEGER:    case LONG:      return NumberExpr.create(_lexeme);    case NULL:      return new NullExpr();    case TRUE:      return BooleanLiteralExpr.create(true);    case FALSE:      return BooleanLiteralExpr.create(false);    case '?':      ParamExpr param = new ParamExpr(_params.size());      _params.add(param);      return param;    default:      throw error(L.l("unexpected term {0}", tokenName(token)));    }  }  /**   * Parses an identifier.   */  private String parseIdentifier()    throws SQLException  {    int token = scanToken();    if (token != IDENTIFIER)      throw error(L.l("expected identifier at {0}", tokenName(token)));    return _lexeme;  }  /**   * Scan the next token.  If the lexeme is a string, its string   * representation is in "lexeme".   *   * @return integer code for the token   */  private int scanToken()    throws SQLException  {    if (_token > 0) {      int value = _token;      _token = -1;      return value;    }    int sign = 1;    int ch;    for (ch = read(); Character.isWhitespace((char) ch); ch = read()) {    }    switch (ch) {    case -1:    case '(':    case ')':    case '.':    case '*':    case '/':    case '%':    case ',':    case '?':      return ch;    case '+':      if ((ch = read()) >= '0' && ch <= '9')        break;      else {        unread(ch);        return '+';      }    case '-':      if ((ch = read()) >= '0' && ch <= '9') {        sign = -1;        break;      }      else {        unread(ch);        return '-';      }    case '=':      return EQ;    case '<':      if ((ch = read()) == '=')        return LE;      else if (ch == '>')        return NE;      else {        unread(ch);        return LT;      }    case '>':      if ((ch = read()) == '=')        return GE;      else {        unread(ch);        return GT;      }    case '|':      if ((ch = read()) == '|')        return CONCAT;      else {        throw error(L.l("'|' expected at {0}", charName(ch)));      }      // @@ is useless?    case '@':      if ((ch = read()) != '@')        throw error(L.l("`@' expected at {0}", charName(ch)));      return scanToken();    }    if (Character.isJavaIdentifierStart((char) ch)) {      CharBuffer cb = _cb;      cb.clear();      for (; ch > 0 && Character.isJavaIdentifierPart((char) ch); ch = read())        cb.append((char) ch);      unread(ch);      _lexeme = cb.toString();      String lower = _lexeme.toLowerCase();      int token = _reserved.get(lower);      if (token > 0)        return token;      else        return IDENTIFIER;    }    else if (ch >= '0' && ch <= '9') {      CharBuffer cb = _cb;      cb.clear();      int type = INTEGER;      if (sign < 0)        cb.append('-');      for (; ch >= '0' && ch <= '9'; ch = read())        cb.append((char) ch);      if (ch == '.') {        type = DOUBLE;        cb.append('.');        for (ch = read(); ch >= '0' && ch <= '9'; ch = read())          cb.append((char) ch);      }      if (ch == 'e' || ch == 'E') {        type = DOUBLE;        cb.append('e');        if ((ch = read()) == '+' || ch == '-') {          cb.append((char) ch);          ch = read();        }        if (! (ch >= '0' && ch <= '9'))          throw error(L.l("exponent needs digits at {0}",                          charName(ch)));        for (; ch >= '0' && ch <= '9'; ch = read())          cb.append((char) ch);      }      if (ch == 'F' || ch == 'D')        type = DOUBLE;      else if (ch == 'L') {        type = LONG;      }      else        unread(ch);      _lexeme = cb.toString();      return type;    }    else if (ch == '\'') {      CharBuffer cb = _cb;      cb.clear();      for (ch = read(); ch >= 0; ch = read()) {	if (ch == '\'') {	  if ((ch = read()) == '\'')	    cb.append('\'');	  else {	    unread(ch);	    break;	  }	}	else if (ch == '\\') {	  ch = read();	  if (ch >= 0)	    cb.append(ch);	}	else	  cb.append((char) ch);      }      _lexeme = cb.toString();      return STRING;    }    else if (ch == '#') {      // skip comment      while ((ch = read()) >= 0 && ch != '\n' && ch != '\r') {      }      // XXX: cleanup to avoid recursion      return scanToken();    }    throw error(L.l("unexpected char at {0} ({1})", "" + (char) ch,		    String.valueOf(ch)));  }  /**   * Returns the next character.   */  private int read()  {    if (_parseIndex < _sqlLength)      return _sqlChars[_parseIndex++];    else      return -1;  }  /**   * Unread the last character.   */  private void unread(int ch)  {    if (ch >= 0)      _parseIndex--;  }  /**   * Returns the name for a character   */  private String charName(int ch)  {    if (ch < 0)      return L.l("end of query");    else      return String.valueOf((char) ch);  }  /**   * Returns the name of a token   */  private String tokenName(int token)  {    switch (token) {    case AS: return "AS";    case ARG: return "?";    case FROM: return "FROM";    case IN: return "IN";    case SELECT: return "SELECT";    case WHERE: return "WHERE";    case OR: return "OR";    case AND: return "AND";    case NOT: return "NOT";    case BETWEEN: return "BETWEEN";    case TRUE: return "TRUE";    case FALSE: return "FALSE";    case NULL: return "NULL";    case GROUP: return "GROUP";    case ORDER: return "ORDER";    case BY: return "BY";    case ASC: return "ASC";    case DESC: return "DESC";    case LIMIT: return "LIMIT";    case -1:      return L.l("end of query");    default:      if (token < 128)        return "'" + String.valueOf((char) token) + "'";      else        return "'" + _lexeme + "'";    }  }  private SQLException error(String msg)  {    return new SQLParseException(msg + "\n" + _sql);  }  static {    _reserved = new IntMap();    _reserved.put("as", AS);    _reserved.put("from", FROM);    _reserved.put("in", IN);    _reserved.put("select", SELECT);    _reserved.put("distinct", DISTINCT);    _reserved.put("where", WHERE);    _reserved.put("order", ORDER);    _reserved.put("group", GROUP);    _reserved.put("by", BY);    _reserved.put("asc", ASC);    _reserved.put("desc", DESC);    _reserved.put("limit", LIMIT);    _reserved.put("offset", OFFSET);    _reserved.put("or", OR);    _reserved.put("and", AND);    _reserved.put("not", NOT);    _reserved.put("between", BETWEEN);    _reserved.put("like", LIKE);    _reserved.put("escape", ESCAPE);    _reserved.put("is", IS);    _reserved.put("true", TRUE);    _reserved.put("false", FALSE);    _reserved.put("unknown", UNKNOWN);    _reserved.put("null", NULL);    _reserved.put("create", CREATE);    _reserved.put("table", TABLE);    _reserved.put("insert", INSERT);    _reserved.put("into", INTO);    _reserved.put("values", VALUES);    _reserved.put("drop", DROP);    _reserved.put("update", UPDATE);    _reserved.put("set", SET);    _reserved.put("delete", DELETE);    _reserved.put("constraint", CONSTRAINT);    _reserved.put("unique", UNIQUE);    _reserved.put("check", CHECK);    _reserved.put("primary", PRIMARY);    _reserved.put("key", KEY);    _reserved.put("foreign", FOREIGN);  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?