|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.editor.ext.java; import java.util.List; import java.util.ArrayList; import org.netbeans.editor.TokenID; import org.netbeans.editor.TokenContextPath; import org.netbeans.editor.TokenProcessor; import org.netbeans.editor.TokenCategory; /** * Token processor that parses the text and produces jc expressions. * * @author Miloslav Metelka * @version 1.00 */ final class JCTokenProcessor implements TokenProcessor { private static final int CONSTANT = JCExpression.CONSTANT; private static final int VARIABLE = JCExpression.VARIABLE; private static final int OPERATOR = JCExpression.OPERATOR; private static final int UNARY_OPERATOR = JCExpression.UNARY_OPERATOR; private static final int DOT = JCExpression.DOT; private static final int DOT_OPEN = JCExpression.DOT_OPEN; private static final int ARRAY_OPEN = JCExpression.ARRAY_OPEN; private static final int ARRAY = JCExpression.ARRAY; private static final int PARENTHESIS_OPEN = JCExpression.PARENTHESIS_OPEN; private static final int PARENTHESIS = JCExpression.PARENTHESIS; private static final int METHOD_OPEN = JCExpression.METHOD_OPEN; private static final int METHOD = JCExpression.METHOD; private static final int CONSTRUCTOR = JCExpression.CONSTRUCTOR; private static final int CONVERSION = JCExpression.CONVERSION; private static final int TYPE = JCExpression.TYPE; private static final int NEW = JCExpression.NEW; private static final int INSTANCEOF = JCExpression.INSTANCEOF; private static final int GENERIC_TYPE = JCExpression.GENERIC_TYPE; private static final int GENERIC_TYPE_OPEN = JCExpression.GENERIC_TYPE_OPEN; private static final int ANNOTATION = JCExpression.ANNOTATION; private static final int IMPORT = JCExpression.IMPORT; private static final int CASE = JCExpression.CASE; private static final int NO_EXP = -1; /** Buffer that is scanned */ private char[] buffer; /** Start position of the buffer in the document */ private int bufferStartPos; /** Delta of the token processor buffer offsets against the offsets given * in the source buffer. */ private int bufferOffsetDelta; /** The scanning was stopped by request by the token processor */ private boolean stopped; /** Stack of the expressions. */ private ArrayList expStack = new ArrayList(); /** TokenID of the last found token except Syntax.EOT and Syntax.EOL */ private TokenID lastValidTokenID; /** Text of the last found token except Syntax.EOT and Syntax.EOL */ private String lastValidTokenText; // helper variables private TokenID curTokenID; private int curTokenPosition; private String curTokenText; private int endScanOffset; private boolean java15; JCTokenProcessor(int endScanOffset) { this.endScanOffset = endScanOffset; } /** * Set whether Java 1.5 features should be enabled. * * @param java15 true to parse expression as being in java 1.5 syntax. */ void setJava15(boolean java15) { this.java15 = java15; } /** Get the expression stack from the bottom to top */ final List getStack() { return expStack; } /** Get the last token that was processed that wasn't * either Syntax.EOT or Syntax.EOL. */ final TokenID getLastValidTokenID() { return lastValidTokenID; } final String getLastValidTokenText() { return lastValidTokenText; } final int getCurrentOffest() { return curTokenPosition; } /** Was the scanning stopped by request by the token processor */ final boolean isStopped() { return stopped; } final JCExpression getResultExp() { JCExpression result = peekExp(); return result; } private void clearStack() { expStack.clear(); } /** Push exp to top of stack */ private void pushExp(JCExpression exp) { expStack.add(exp); } /** Pop exp from top of stack */ private JCExpression popExp() { int cnt = expStack.size(); return (cnt > 0) ? (JCExpression)expStack.remove(cnt - 1) : null; } /** Look at the exp at top of stack */ private JCExpression peekExp() { int cnt = expStack.size(); return (cnt > 0) ? (JCExpression)expStack.get(cnt - 1) : null; } /** Look at the second exp on stack */ private JCExpression peekExp2() { int cnt = expStack.size(); return (cnt > 1) ? (JCExpression)expStack.get(cnt - 2) : null; } /** Look at the third exp on stack */ private JCExpression peekExp(int ind) { int cnt = expStack.size(); return (cnt >= ind) ? (JCExpression)expStack.get(cnt - ind) : null; } private JCExpression createTokenExp(int id) { JCExpression exp = new JCExpression(id); addTokenTo(exp); return exp; } /** Add the token to a given expression */ private void addTokenTo(JCExpression exp) { exp.addToken(curTokenID, curTokenPosition, curTokenText); } private int getValidExpID(JCExpression exp) { return (exp != null) ? exp.getExpID() : NO_EXP; } /** Check whether there can be any joining performed * for current expressions on the stack. * @param tokenID tokenID of the current token * @return true to continue, false if errorneous construction found */ private boolean checkJoin(TokenID tokenID) { boolean ret = true; boolean cont = true; while (cont) { cont = false; JCExpression top = peekExp(); JCExpression top2 = peekExp2(); int top2ID = getValidExpID(top2); switch (getValidExpID(top)) { case CONSTANT: case VARIABLE: case METHOD: case CONSTRUCTOR: case ARRAY: case DOT: case PARENTHESIS: case OPERATOR: // operator on top of stack switch (top2ID) { case UNARY_OPERATOR: switch (tokenID.getNumericID()) { case JavaTokenContext.DOT_ID: case JavaTokenContext.LPAREN_ID: case JavaTokenContext.LBRACKET_ID: case JavaTokenContext.PLUS_PLUS_ID: case JavaTokenContext.MINUS_MINUS_ID: break; default: // Join if (top2.getParameterCount() == 0) { popExp(); // pop top top2.addParameter(top); } break; } break; case DOT_OPEN: if (tokenID.getCategory() == JavaTokenContext.OPERATORS) { switch( tokenID.getNumericID() ) { case JavaTokenContext.LPAREN_ID: break; default: popExp(); top2.addParameter(top); top2.setExpID(DOT); } } break; case CONVERSION: if (tokenID.getCategory() == JavaTokenContext.OPERATORS) { switch (tokenID.getNumericID()) { case JavaTokenContext.RPAREN_ID: case JavaTokenContext.COMMA_ID: JCExpression top3 = peekExp(3); if (top3 != null) { switch (top3.getExpID()) { case JCExpression.PARENTHESIS_OPEN: case JCExpression.METHOD_OPEN: popExp(); // pop top top2.addParameter(top); // add last to conversion break; } } break; } } break; } break; } } int leftOpID = JCExpression.getOperatorID(tokenID); if (leftOpID >= 0) { switch (JCExpression.getOperatorPrecedence(leftOpID)) { case 0: // stop ID - try to join the exps on stack JCExpression lastVar = null; JCExpression rightOp = peekExp(); int rightOpID = -1; rightOpID = JCExpression.getOperatorID(rightOp); switch (JCExpression.getOperatorPrecedence(rightOpID)) { case 0: // stop - nothing to join rightOp = null; break; case 1: // single item - move to next and add this one lastVar = rightOp; rightOp = peekExp2(); rightOpID = JCExpression.getOperatorID(rightOp); switch (JCExpression.getOperatorPrecedence(rightOpID)) { case 0: // stop - only one item on the stack rightOp = null; break; case 1: // two items without operator - error ret = false; rightOp = null; break; default: popExp(); // pop item rightOp.addParameter(lastVar); // add item as parameter lastVar = null; } break; } if (rightOp != null) { popExp(); // pop rightOp cont = true; ArrayList opStack = new ArrayList(); // operator stack JCExpression leftOp = null; do { if (leftOp == null) { leftOp = popExp(); if (leftOp == null) { break; } leftOpID = JCExpression.getOperatorID(leftOp); } switch (JCExpression.getOperatorPrecedence(leftOpID)) { case 0: // stop here pushExp(leftOp); // push last exp back to stack cont = false; break; case 1: // item found lastVar = leftOp; leftOp = null; // ask for next pop break; default: // operator found int leftOpPrec = JCExpression.getOperatorPrecedence(leftOpID); int rightOpPrec = JCExpression.getOperatorPrecedence(rightOpID); boolean rightPrec; if (leftOpPrec > rightOpPrec) { // left has greater priority rightPrec = false; } else if (leftOpPrec < rightOpPrec) { // right has greater priority rightPrec = true; } else { // equal priorities rightPrec = JCExpression.isOperatorRightAssociative(rightOpID); } if (rightPrec) { // right operator has precedence if (lastVar != null) { rightOp.addParameter(lastVar); } if (opStack.size() > 0) { // at least one right stacked op lastVar = rightOp; // rightOp becomes item rightOp = (JCExpression)opStack.remove(opStack.size() - 1); // get stacked op rightOpID = rightOp.getOperatorID(rightOp); } else { // shift the leftOp to rightOp leftOp.addParameter(rightOp); lastVar = null; rightOp = leftOp; rightOpID = leftOpID; leftOp = null; // ask for next poping } } else { // left operator has precedence if (lastVar != null) { leftOp.addParameter(lastVar); lastVar = null; } opStack.add(rightOp); // push right operator to stack // rightOp.addParameter(leftOp); rightOp = leftOp; // shift left op to right op rightOpID = leftOpID; leftOp = null; } } } while (cont); // add possible valid last item if (lastVar != null) { rightOp.addParameter(lastVar); } // pop the whole stack adding the current right op to the stack exp for (int i = opStack.size() - 1; i >= 0; i--) { JCExpression op = (JCExpression)opStack.get(i); op.addParameter(rightOp); rightOp = op; } rightOp.swapOperatorParms(); pushExp(rightOp); // push the top operator } break; } } return ret; } public boolean token(TokenID tokenID, TokenContextPath tokenContextPath, int tokenOffset, int tokenLen) { tokenOffset += bufferOffsetDelta; if (tokenID != null){ TokenCategory category = tokenID.getCategory(); if (JavaTokenContext.KEYWORDS.equals(category)){ if (tokenOffset+tokenLen+bufferStartPos == endScanOffset) tokenID = JavaTokenContext.IDENTIFIER; } } // assign helper variables if (tokenID != null) { lastValidTokenID = tokenID; } curTokenID = tokenID; curTokenPosition = bufferStartPos + tokenOffset; curTokenText = new String(buffer, tokenOffset, tokenLen); lastValidTokenText = curTokenText; boolean err = false; // whether the parser cannot understand given tokens stopped = false; checkJoin(tokenID); JCExpression top = peekExp(); // exp at top of stack int topID = getValidExpID(top); // id of the exp at top of stack JCExpression constExp = null; // possibly assign constant into this exp JCType kwdType = null; // keyword constant type (used in conversions) if (tokenID == null) { // invalid token-id err = true; } else { // valid token-id if (tokenContextPath.contains(JavaTokenContext.contextPath)){ switch (tokenID.getNumericID()) { // test the token ID case JavaTokenContext.BOOLEAN_ID: kwdType = JavaCompletion.BOOLEAN_TYPE; break; case JavaTokenContext.BYTE_ID: kwdType = JavaCompletion.BYTE_TYPE; break; case JavaTokenContext.CHAR_ID: kwdType = JavaCompletion.CHAR_TYPE; break; case JavaTokenContext.DOUBLE_ID: kwdType = JavaCompletion.DOUBLE_TYPE; break; case JavaTokenContext.FLOAT_ID: kwdType = JavaCompletion.FLOAT_TYPE; break; case JavaTokenContext.INT_ID: kwdType = JavaCompletion.INT_TYPE; break; case JavaTokenContext.LONG_ID: kwdType = JavaCompletion.LONG_TYPE; break; case JavaTokenContext.SHORT_ID: kwdType = JavaCompletion.SHORT_TYPE; break; case JavaTokenContext.TRUE_ID: case JavaTokenContext.FALSE_ID: constExp = createTokenExp(CONSTANT); constExp.setType("boolean"); // NOI18N break; case JavaTokenContext.NULL_ID: constExp = createTokenExp(CONSTANT); constExp.setType("null"); // NOI18N break; case JavaTokenContext.CLASS_ID: if (topID == DOT_OPEN) { pushExp(createTokenExp(VARIABLE)); } else { err = true; } break; case JavaTokenContext.NEW_ID: switch (topID) { case VARIABLE: case NEW: err = true; break; default: pushExp(createTokenExp(NEW)); break; } break; case JavaTokenContext.IMPORT_ID: pushExp(createTokenExp(IMPORT)); break; case JavaTokenContext.STATIC_ID: switch (topID) { case IMPORT: top.addParameter(createTokenExp(IMPORT)); break; default: err = true; break; } break; case JavaTokenContext.SUPER_ID: case JavaTokenContext.THIS_ID: pushExp(createTokenExp(VARIABLE)); break; case JavaTokenContext.ANNOTATION_ID: pushExp(createTokenExp(ANNOTATION)); break; case JavaTokenContext.INSTANCEOF_ID: switch (topID) { case CONSTANT: case VARIABLE: case METHOD: case CONSTRUCTOR: case ARRAY: case DOT: case PARENTHESIS: pushExp(createTokenExp(INSTANCEOF)); break; default: err = true; break; } break; case JavaTokenContext.CASE_ID: pushExp(createTokenExp(CASE)); break; // TODO - the following block should be in default: case JavaTokenContext.VOID_ID: case JavaTokenContext.ABSTRACT_ID: case JavaTokenContext.ASSERT_ID: case JavaTokenContext.BREAK_ID: case JavaTokenContext.CATCH_ID: case JavaTokenContext.CONST_ID: case JavaTokenContext.CONTINUE_ID: case JavaTokenContext.DEFAULT_ID: case JavaTokenContext.DO_ID: case JavaTokenContext.ELSE_ID: case JavaTokenContext.EXTENDS_ID: case JavaTokenContext.FINAL_ID: case JavaTokenContext.FINALLY_ID: case JavaTokenContext.FOR_ID: case JavaTokenContext.GOTO_ID: case JavaTokenContext.IF_ID: case JavaTokenContext.IMPLEMENTS_ID: case JavaTokenContext.INTERFACE_ID: case JavaTokenContext.NATIVE_ID: case JavaTokenContext.PACKAGE_ID: case JavaTokenContext.PRIVATE_ID: case JavaTokenContext.PROTECTED_ID: case JavaTokenContext.PUBLIC_ID: case JavaTokenContext.RETURN_ID: case JavaTokenContext.STRICTFP_ID: case JavaTokenContext.SWITCH_ID: case JavaTokenContext.SYNCHRONIZED_ID: case JavaTokenContext.THROW_ID: case JavaTokenContext.THROWS_ID: case JavaTokenContext.TRANSIENT_ID: case JavaTokenContext.TRY_ID: case JavaTokenContext.VOLATILE_ID: case JavaTokenContext.WHILE_ID: err = true; break; case JavaTokenContext.IDENTIFIER_ID: // identifier found e.g. 'a' { switch (topID) { case OPERATOR: case DOT_OPEN: case ARRAY_OPEN: case PARENTHESIS_OPEN: case METHOD_OPEN: case NEW: case IMPORT: case CONVERSION: case UNARY_OPERATOR: case INSTANCEOF: case NO_EXP: case GENERIC_TYPE_OPEN: case ANNOTATION: case CASE: pushExp(createTokenExp(VARIABLE)); break; default: err = true; break; } } break; case JavaTokenContext.EQ_ID: // Assignment operators case JavaTokenContext.PLUS_EQ_ID: case JavaTokenContext.MINUS_EQ_ID: case JavaTokenContext.MUL_EQ_ID: case JavaTokenContext.DIV_EQ_ID: case JavaTokenContext.AND_EQ_ID: case JavaTokenContext.OR_EQ_ID: case JavaTokenContext.XOR_EQ_ID: case JavaTokenContext.MOD_EQ_ID: case JavaTokenContext.LSHIFT_EQ_ID: case JavaTokenContext.RSSHIFT_EQ_ID: case JavaTokenContext.RUSHIFT_EQ_ID: case JavaTokenContext.LT_EQ_ID: case JavaTokenContext.GT_EQ_ID: case JavaTokenContext.EQ_EQ_ID: case JavaTokenContext.NOT_EQ_ID: case JavaTokenContext.AND_AND_ID: // Binary, result is boolean case JavaTokenContext.OR_OR_ID: case JavaTokenContext.LSHIFT_ID: // Always binary case JavaTokenContext.MUL_ID: case JavaTokenContext.DIV_ID: case JavaTokenContext.AND_ID: case JavaTokenContext.OR_ID: case JavaTokenContext.XOR_ID: case JavaTokenContext.MOD_ID: case JavaTokenContext.QUESTION_ID: case JavaTokenContext.COLON_ID: // Operator handling switch (topID) { case CONSTANT: case VARIABLE: case METHOD: case CONSTRUCTOR: case ARRAY: case DOT: case PARENTHESIS: case OPERATOR: case UNARY_OPERATOR: pushExp(createTokenExp(OPERATOR)); break; default: err = true; break; } break; case JavaTokenContext.LT_ID: { boolean genericType = false; if (java15) { // special treatment of Java 1.5 features switch (topID) { case VARIABLE: case DOT: popExp(); // pop the top expression JCExpression genExp = createTokenExp(GENERIC_TYPE_OPEN); genExp.addParameter(top); pushExp(genExp); genericType = true; // handled successfully as generic type break; default: // could possibly still be acceptable as operator '<' break; } } if (!err && !genericType) { // not generics -> handled compatibly // Operator handling switch (topID) { case CONSTANT: case VARIABLE: case METHOD: case CONSTRUCTOR: case ARRAY: case DOT: case PARENTHESIS: case OPERATOR: case UNARY_OPERATOR: pushExp(createTokenExp(OPERATOR)); break; default: err = true; break; } } break; } case JavaTokenContext.GT_ID: // ">" { boolean genericType = false; if (java15) { // special treatment of Java 1.5 features switch (topID) { case VARIABLE: // check for "List" case case DOT: // check for "List |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.