alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

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" case
                                    case GENERIC_TYPE: // check for "List" plus ">" case
                                        JCExpression top2 = peekExp2();
                                        switch (getValidExpID(top2)) {
                                            case GENERIC_TYPE_OPEN:
                                                popExp();
                                                top2.addParameter(top);
                                                top2.setExpID(GENERIC_TYPE);
                                                addTokenTo(top2);
                                                genericType = true;
                                                top = top2;
                                                break;

                                            default:
                                                err = topID == GENERIC_TYPE;
                                                break;
                                        }
                                        break;

                                    default:
                                        // Will be handled as operator
                                        break;
                                }
                            }


                            if (!err && !genericType) { // not generics - handled compatibly
                                // Operator handling
                                switch (topID) {
                                    case CONSTANT:
                                    case VARIABLE: // List>"
                        {
                            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" case
                                    case GENERIC_TYPE: // check for "List" plus ">" case
                                        JCExpression top2 = peekExp2();
                                        switch (getValidExpID(top2)) {
                                            case GENERIC_TYPE_OPEN:
                                                // Check whether outer is open as well
                                                JCExpression top3 = peekExp(3);
                                                if (getValidExpID(top3) == GENERIC_TYPE_OPEN) {
                                                    genericType = true;
                                                    popExp();
                                                    top2.addParameter(top);
                                                    top2.setExpID(GENERIC_TYPE);
                                                    addTokenTo(top2); // [TODO] revise possible spliting of the token

                                                    popExp();
                                                    top3.addParameter(top2);
                                                    top3.setExpID(GENERIC_TYPE);
                                                    addTokenTo(top3); // [TODO] revise possible spliting of the token

                                                    top = top3;

                                                } else { // inner is not generic type
                                                    err = true;
                                                }
                                                break;

                                            default:
                                                err = true;
                                                break;
                                        }
                                        break;

                                    default:
                                        // Will be handled as operator
                                        break;
                                }
                            }


                            if (!err && !genericType) { // not generics - handled compatibly
                                // Operator handling
                                switch (topID) {
                                    case CONSTANT:
                                    case VARIABLE: // List>>"
                        {
                            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" case
                                    case GENERIC_TYPE: // check for "List" plus ">" case
                                        JCExpression top2 = peekExp2();
                                        switch (getValidExpID(top2)) {
                                            case GENERIC_TYPE_OPEN:
                                                // Check whether outer is open as well
                                                JCExpression top3 = peekExp(3);
                                                JCExpression top4 = peekExp(4);
                                                if (getValidExpID(top3) == GENERIC_TYPE_OPEN
                                                    && getValidExpID(top4) == GENERIC_TYPE_OPEN
                                                ) {
                                                    genericType = true;
                                                    popExp();
                                                    top2.addParameter(top);
                                                    top2.setExpID(GENERIC_TYPE);
                                                    addTokenTo(top2); // [TODO] revise possible spliting of the token

                                                    popExp();
                                                    top3.addParameter(top2);
                                                    top3.setExpID(GENERIC_TYPE);
                                                    addTokenTo(top3); // [TODO] revise possible spliting of the token

                                                    popExp();
                                                    top4.addParameter(top3);
                                                    top4.setExpID(GENERIC_TYPE);
                                                    addTokenTo(top4); // [TODO] revise possible spliting of the token

                                                    top = top4;

                                                } else { // inner is not generic type
                                                    err = true;
                                                }
                                                break;

                                            default:
                                                err = true;
                                                break;
                                        }
                                        break;

                                    default:
                                        // Will be handled as operator
                                        break;
                                }
                            }


                            if (!err && !genericType) { // not generics - handled compatibly
                                // Operator handling
                                switch (topID) {
                                    case CONSTANT:
                                    case VARIABLE: // List" plus "," state
                                JCExpression top2 = peekExp2();
                                switch (getValidExpID(top2)) {
                                    case METHOD_OPEN:
                                        popExp();
                                        top2.addParameter(top);
                                        top = top2;
                                        break;

                                    case GENERIC_TYPE_OPEN:
                                        switch (topID) {
                                            case VARIABLE:
                                            case DOT:
                                            case GENERIC_TYPE:
                                                popExp();
                                                top2.addParameter(top);
                                                addTokenTo(top2); // add "," to open generics type
                                                top = top2;
                                                break;

                                            default:
                                                err = true;
                                                break;
                                        }
                                        break;

                                    default:
                                        err = true;
                                        break;
                                }
                                break;

                            case METHOD_OPEN:
                                addTokenTo(top);
                                break;

                            default:
                                err = true;
                                break;

                        }
                        break;

                    case JavaTokenContext.SEMICOLON_ID:
                        err = true;
                        break;

                    case JavaTokenContext.LPAREN_ID:
                        switch (topID) {
                            case VARIABLE:
                            case GENERIC_TYPE:
                                top.setExpID(METHOD_OPEN);
                                addTokenTo(top);
                                break;

                            case ARRAY: // a[0](
                                popExp();
                                JCExpression mtdExp = createTokenExp(METHOD);
                                mtdExp.addParameter(top);
                                pushExp(mtdExp);
                                break;

                            case ARRAY_OPEN:       // a[(
                            case PARENTHESIS_OPEN: // ((
                            case METHOD_OPEN:      // a((
                            case NO_EXP:
                            case OPERATOR:         // 3+(
                            case CONVERSION:       // (int)(                            
                                pushExp(createTokenExp(PARENTHESIS_OPEN));
                                break;

                            default:
                                err = true;
                                break;
                        }
                        break;

                    case JavaTokenContext.RPAREN_ID:
                        boolean mtd = false;
                        switch (topID) {
                            case CONSTANT:
                            case VARIABLE:
                            case ARRAY:
                            case DOT:
                            case TYPE:
                            case CONSTRUCTOR:
                            case CONVERSION:
                            case PARENTHESIS:
                            case OPERATOR:
                            case UNARY_OPERATOR:
                            case INSTANCEOF:
                            case METHOD:
                            case GENERIC_TYPE:
                                JCExpression top2 = peekExp2();
                                switch (getValidExpID(top2)) {
                                    case PARENTHESIS_OPEN:
                                        popExp();
                                        top2.addParameter(top);
                                        top2.setExpID(JCExpression.isValidType(top) ? CONVERSION : PARENTHESIS);
                                        addTokenTo(top2);
                                        break;

                                    case GENERIC_TYPE_OPEN:
                                        popExp();
                                        top2.setExpID(OPERATOR);
                                        top2.addParameter(top);
                                        top = top2;
                                        top2 = peekExp2();
                                        if (getValidExpID(top2) != METHOD_OPEN)
                                            break;

                                    case METHOD_OPEN:
                                        popExp();
                                        top2.addParameter(top);
                                        top = top2;
                                        mtd = true;
                                        break;

                                    case CONVERSION:
                                        popExp();
                                        top2.addParameter( top );
                                        top=top2;
                                        top2 = peekExp2();
                                        switch (getValidExpID(top2)) {
                                            case PARENTHESIS_OPEN:
                                                popExp();
                                                top2.addParameter( top );
                                                top2.setExpID( PARENTHESIS );
                                                top = top2;
                                                break;

                                            case METHOD_OPEN:
                                                popExp();
                                                top2.addParameter(top);
                                                top = top2;
                                                mtd = true;
                                                break;
                                        }
                                        break;

                                    default:
                                        err = true;
                                        break;
                                }
                                break;

                            case METHOD_OPEN:
                                mtd = true;
                                break;

                                //              case PARENTHESIS_OPEN: // empty parenthesis
                            default:
                                err = true;
                                break;
                        }

                        if (mtd) {
                            addTokenTo(top);
                            top.setExpID(METHOD);
                            JCExpression top2 = peekExp2();
                            switch (getValidExpID(top2)) {
                                case DOT_OPEN:
                                    JCExpression top3 = peekExp(3);
                                    if (getValidExpID(top3) == NEW) {
                                        popExp(); // pop top
                                        top2.addParameter(top); // add METHOD to DOT
                                        top2.setExpID(DOT);
                                        popExp(); // pop top2
                                        top3.setExpID(CONSTRUCTOR);
                                        top3.addParameter(top2); // add DOT to CONSTRUCTOR
                                    }
                                    break;

                                case NEW:
                                    top2.setExpID(CONSTRUCTOR);
                                    top2.addParameter(top);
                                    popExp(); // pop top
                                    break;
                            }
                        }
                        break;

                    case JavaTokenContext.LBRACKET_ID:
                        switch (topID) {
                            case VARIABLE:
                            case METHOD:
                            case DOT:
                            case ARRAY:
                            case TYPE: // ... int[ ...
                            case GENERIC_TYPE: // List "["
                            case PARENTHESIS: // ... ((String[]) obj)[ ...
                                popExp(); // top popped
                                JCExpression arrExp = createTokenExp(ARRAY_OPEN);
                                arrExp.addParameter(top);
                                pushExp(arrExp);
                                break;

                            default:
                                err = true;
                                break;
                        }
                        break;

                    case JavaTokenContext.ELLIPSIS_ID:
                        switch (topID) {
                            case VARIABLE:
                            case METHOD:
                            case DOT:
                            case ARRAY:
                            case TYPE: // ... int[ ...
                            case GENERIC_TYPE: // List "["
                                popExp(); // top popped
                                JCExpression arrExp = createTokenExp(ARRAY);
                                // Add "..." again to have the even token count like with "[" "]"
                                addTokenTo(arrExp);
                                arrExp.addParameter(top);
                                pushExp(arrExp);
                                break;

                            default:
                                err = true;
                                break;
                        }
                        break;

                    case JavaTokenContext.RBRACKET_ID:
                        switch (topID) {
                            case VARIABLE:
                            case METHOD:
                            case DOT:
                            case ARRAY:
                            case PARENTHESIS:
                            case CONSTANT:
                            case OPERATOR:
                            case UNARY_OPERATOR:
                            case INSTANCEOF:
                                JCExpression top2 = peekExp2();
                                switch (getValidExpID(top2)) {
                                    case ARRAY_OPEN:
                                        JCExpression top3 = peekExp(3);
                                        popExp(); // top popped
                                        if (getValidExpID(top3) == NEW) {
                                            popExp(); // top2 popped
                                            top3.setExpID(ARRAY);
                                            top3.addParameter(top2.getParameter(0));
                                            top3.addToken(top2.getTokenID(0), top2.getTokenOffset(0), top2.getTokenText(0));
                                            addTokenTo(top2);
                                        } else {
                                            top2.setExpID(ARRAY);
                                            top2.addParameter(top);
                                            addTokenTo(top2);
                                        }
                                        break;

                                    default:
                                        err = true;
                                        break;
                                }
                                break;

                            case ARRAY_OPEN:
                                top.setExpID(ARRAY);
                                addTokenTo(top);
                                break;

                            default:
                                err = true;
                                break;
                        }
                        break;

                    case JavaTokenContext.LBRACE_ID:
                        if (topID == ARRAY) {
                            JCExpression top2 = peekExp2();
                            if (getValidExpID(top2) == NEW) {
                                popExp(); // top popped
                                top2.setExpID(ARRAY);
                                top2.addParameter(top.getParameter(0));
                                top2.addToken(top.getTokenID(0), top.getTokenOffset(0), top.getTokenText(0));
                                top2.addToken(top.getTokenID(1), top.getTokenOffset(1), top.getTokenText(1));
                                stopped = true;
                                break;
                            }
                        }
                        err = true;
                        break;

                    case JavaTokenContext.RBRACE_ID:
                        err = true;
                        break;



                    case JavaTokenContext.LINE_COMMENT_ID:
                        // Skip line comment
                        break;

                    case JavaTokenContext.BLOCK_COMMENT_ID:
                        // Skip block comment
                        break;

                    case JavaTokenContext.CHAR_LITERAL_ID:
                        constExp = createTokenExp(CONSTANT);
                        constExp.setType("char"); // NOI18N
                        break;

                    case JavaTokenContext.STRING_LITERAL_ID:
                        constExp = createTokenExp(CONSTANT);
                        constExp.setType("java.lang.String"); // NOI18N
                        break;

                    case JavaTokenContext.INT_LITERAL_ID:
                    case JavaTokenContext.HEX_LITERAL_ID:
                    case JavaTokenContext.OCTAL_LITERAL_ID:
                        constExp = createTokenExp(CONSTANT);
                        constExp.setType("int"); // NOI18N
                        break;

                    case JavaTokenContext.LONG_LITERAL_ID:
                        constExp = createTokenExp(CONSTANT);
                        constExp.setType("long"); // NOI18N
                        break;

                    case JavaTokenContext.FLOAT_LITERAL_ID:
                        constExp = createTokenExp(CONSTANT);
                        constExp.setType("float"); // NOI18N
                        break;

                    case JavaTokenContext.DOUBLE_LITERAL_ID:
                        constExp = createTokenExp(CONSTANT);
                        constExp.setType("double"); // NOI18N
                        break;

                } // end of testing keyword type
            }
        }
            
            
        // Check whether a constant or data type keyword was found
        if (constExp != null) {
            switch (topID) {
            case DOT_OPEN:
                err = true;
                break;

            case ARRAY_OPEN:
            case PARENTHESIS_OPEN:
            case PARENTHESIS: // can be conversion
            case METHOD_OPEN:
            case OPERATOR:
            case UNARY_OPERATOR:
            case CONVERSION:
            case NO_EXP:
                pushExp(constExp);
                break;

            case GENERIC_TYPE_OPEN:
                top.setExpID(OPERATOR);
                top.addParameter(constExp);
                break;

            default:
                err = true;
                break;
            }
        }
        
        if (kwdType != null) { // keyword constant (in conversions)
            switch (topID) {
            case NEW: // possibly new kwdType[]
            case PARENTHESIS_OPEN: // conversion
                JCExpression kwdExp = createTokenExp(TYPE);
                addTokenTo(kwdExp);
                kwdExp.setType(kwdType.getClazz().getFullName());
                pushExp(kwdExp);
                break;

            default: // otherwise not recognized
                err = true;
                break;
            }
        }

        if (err) {
            clearStack();

            if (tokenID == JavaTokenContext.IDENTIFIER) {
                pushExp(createTokenExp(VARIABLE));
            }
        }
        
        return !stopped;
    }

    public int eot(int offset) {
        // Check for joins
        boolean reScan = true;
        while (reScan) {
            reScan = false;
            JCExpression top = peekExp();
            JCExpression top2 = peekExp2();
            int top2ID = getValidExpID(top2);
            if (top != null) {
                switch (getValidExpID(top)) {
                case VARIABLE:
                    switch (top2ID) {
                    case DOT_OPEN:
                        popExp();
                        top2.addParameter(top);
                        top2.setExpID(DOT);
                        reScan = true;
                        break;
                    case NEW:
                        popExp();
                        top2.addParameter(top);
                        top2.setExpID(CONSTRUCTOR);
                        reScan = true;
                        break;
                    case IMPORT:
                        popExp();
                        top2.addParameter(top);
                        break;
                    case ANNOTATION:
                    case CASE:
                    case GENERIC_TYPE_OPEN: // e.g. "List 1)
                        break;

                case IMPORT:
                    top.addParameter(JCExpression.createEmptyVariable(
                            bufferStartPos + bufferOffsetDelta + offset));
                    break;
                }
            } else { // nothing on the stack, create empty variable
                pushExp(JCExpression.createEmptyVariable(
                            bufferStartPos + bufferOffsetDelta + offset));
            }
        }
        //    System.out.println(this);
        return 0;
    }

    public void nextBuffer(char[] buffer, int offset, int len,
                           int startPos, int preScan, boolean lastBuffer) {
        this.buffer = new char[len + preScan];
        System.arraycopy(buffer, offset - preScan, this.buffer, 0, len + preScan);
        bufferOffsetDelta = preScan - offset;
        this.bufferStartPos = startPos - preScan;
    }

    public String toString() {
        int cnt = expStack.size();
        StringBuffer sb = new StringBuffer();
        if (stopped) {
            sb.append("Parsing STOPPED by request.\n"); // NOI18N
        }
        sb.append("Stack size is " + cnt + "\n"); // NOI18N
        if (cnt > 0) {
            sb.append("Stack expressions:\n"); // NOI18N
            for (int i = 0; i < cnt; i++) {
                JCExpression e = (JCExpression)expStack.get(i);
                sb.append("Stack["); // NOI18N
                sb.append(i);
                sb.append("]: "); // NOI18N
                sb.append(e.toString(0));
                sb.append('\n');
            }
        }
        return sb.toString();
    }

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

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.