Search in sources :

Example 1 with TokenKind

use of org.eclipse.ceylon.langtools.tools.javac.parser.Tokens.TokenKind in project ceylon by eclipse.

the class JavacParser method term3.

/**
 *  Expression3    = PrefixOp Expression3
 *                 | "(" Expr | TypeNoParams ")" Expression3
 *                 | Primary {Selector} {PostfixOp}
 *
 *  {@literal
 *  Primary        = "(" Expression ")"
 *                 | Literal
 *                 | [TypeArguments] THIS [Arguments]
 *                 | [TypeArguments] SUPER SuperSuffix
 *                 | NEW [TypeArguments] Creator
 *                 | "(" Arguments ")" "->" ( Expression | Block )
 *                 | Ident "->" ( Expression | Block )
 *                 | [Annotations] Ident { "." [Annotations] Ident }
 *                 | Expression3 MemberReferenceSuffix
 *                   [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
 *                   | Arguments
 *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
 *                   ]
 *                 | BasicType BracketsOpt "." CLASS
 *  }
 *
 *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
 *  PostfixOp      = "++" | "--"
 *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
 *                 | BasicType
 *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
 *  Selector       = "." [TypeArguments] Ident [Arguments]
 *                 | "." THIS
 *                 | "." [TypeArguments] SUPER SuperSuffix
 *                 | "." NEW [TypeArguments] InnerCreator
 *                 | "[" Expression "]"
 *  TypeSelector   = "." Ident [TypeArguments]
 *  SuperSuffix    = Arguments | "." Ident [Arguments]
 */
protected JCExpression term3() {
    int pos = token.pos;
    JCExpression t;
    List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
    switch(token.kind) {
        case QUES:
            if ((mode & TYPE) != 0 && (mode & (TYPEARG | NOPARAMS)) == TYPEARG) {
                mode = TYPE;
                return typeArgument();
            } else
                return illegal();
        case PLUSPLUS:
        case SUBSUB:
        case BANG:
        case TILDE:
        case PLUS:
        case SUB:
            if (typeArgs == null && (mode & EXPR) != 0) {
                TokenKind tk = token.kind;
                nextToken();
                mode = EXPR;
                if (tk == SUB && (token.kind == INTLITERAL || token.kind == LONGLITERAL) && token.radix() == 10) {
                    mode = EXPR;
                    t = literal(names.hyphen, pos);
                } else {
                    t = term3();
                    return F.at(pos).Unary(unoptag(tk), t);
                }
            } else
                return illegal();
            break;
        case LPAREN:
            if (typeArgs == null && (mode & EXPR) != 0) {
                ParensResult pres = analyzeParens();
                switch(pres) {
                    case CAST:
                        accept(LPAREN);
                        mode = TYPE;
                        int pos1 = pos;
                        List<JCExpression> targets = List.of(t = term3());
                        while (token.kind == AMP) {
                            checkIntersectionTypesInCast();
                            accept(AMP);
                            targets = targets.prepend(term3());
                        }
                        if (targets.length() > 1) {
                            t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
                        }
                        accept(RPAREN);
                        mode = EXPR;
                        JCExpression t1 = term3();
                        return F.at(pos).TypeCast(t, t1);
                    case IMPLICIT_LAMBDA:
                    case EXPLICIT_LAMBDA:
                        t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
                        break;
                    default:
                        // PARENS
                        accept(LPAREN);
                        mode = EXPR;
                        t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec)));
                        accept(RPAREN);
                        t = toP(F.at(pos).Parens(t));
                        break;
                }
            } else {
                return illegal();
            }
            break;
        case THIS:
            if ((mode & EXPR) != 0) {
                mode = EXPR;
                t = to(F.at(pos).Ident(names._this));
                nextToken();
                if (typeArgs == null)
                    t = argumentsOpt(null, t);
                else
                    t = arguments(typeArgs, t);
                typeArgs = null;
            } else
                return illegal();
            break;
        case SUPER:
            if ((mode & EXPR) != 0) {
                mode = EXPR;
                t = to(F.at(pos).Ident(names._super));
                t = superSuffix(typeArgs, t);
                typeArgs = null;
            } else
                return illegal();
            break;
        case INTLITERAL:
        case LONGLITERAL:
        case FLOATLITERAL:
        case DOUBLELITERAL:
        case CHARLITERAL:
        case STRINGLITERAL:
        case TRUE:
        case FALSE:
        case NULL:
            if (typeArgs == null && (mode & EXPR) != 0) {
                mode = EXPR;
                t = literal(names.empty);
            } else
                return illegal();
            break;
        case NEW:
            if (typeArgs != null)
                return illegal();
            if ((mode & EXPR) != 0) {
                mode = EXPR;
                nextToken();
                if (token.kind == LT)
                    typeArgs = typeArguments(false);
                t = creator(pos, typeArgs);
                typeArgs = null;
            } else
                return illegal();
            break;
        case MONKEYS_AT:
            // Only annotated cast types and method references are valid
            List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
            if (typeAnnos.isEmpty()) {
                // else there would be no '@'
                throw new AssertionError("Expected type annotations, but found none!");
            }
            JCExpression expr = term3();
            if ((mode & TYPE) == 0) {
                // Type annotations on class literals no longer legal
                switch(expr.getTag()) {
                    case REFERENCE:
                        {
                            JCMemberReference mref = (JCMemberReference) expr;
                            mref.expr = toP(F.at(pos).AnnotatedType(typeAnnos, mref.expr));
                            t = mref;
                            break;
                        }
                    case SELECT:
                        {
                            JCFieldAccess sel = (JCFieldAccess) expr;
                            if (sel.name != names._class) {
                                return illegal();
                            } else {
                                log.error(token.pos, "no.annotations.on.dot.class");
                                return expr;
                            }
                        }
                    default:
                        return illegal(typeAnnos.head.pos);
                }
            } else {
                // Type annotations targeting a cast
                t = insertAnnotationsToMostInner(expr, typeAnnos, false);
            }
            break;
        case UNDERSCORE:
        case IDENTIFIER:
        case ASSERT:
        case ENUM:
            if (typeArgs != null)
                return illegal();
            if ((mode & EXPR) != 0 && peekToken(ARROW)) {
                t = lambdaExpressionOrStatement(false, false, pos);
            } else {
                t = toP(F.at(token.pos).Ident(ident()));
                loop: while (true) {
                    pos = token.pos;
                    final List<JCAnnotation> annos = typeAnnotationsOpt();
                    // index access rather than array creation level
                    if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS)
                        return illegal(annos.head.pos);
                    switch(token.kind) {
                        case LBRACKET:
                            nextToken();
                            if (token.kind == RBRACKET) {
                                nextToken();
                                t = bracketsOpt(t);
                                t = toP(F.at(pos).TypeArray(t));
                                if (annos.nonEmpty()) {
                                    t = toP(F.at(pos).AnnotatedType(annos, t));
                                }
                                // .class is only allowed if there were no annotations
                                JCExpression nt = bracketsSuffix(t);
                                if (nt != t && (annos.nonEmpty() || TreeInfo.containsTypeAnnotation(t))) {
                                    // t and nt are different if bracketsSuffix parsed a .class.
                                    // The check for nonEmpty covers the case when the whole array is annotated.
                                    // Helper method isAnnotated looks for annos deeply within t.
                                    syntaxError("no.annotations.on.dot.class");
                                }
                                t = nt;
                            } else {
                                if ((mode & EXPR) != 0) {
                                    mode = EXPR;
                                    JCExpression t1 = term();
                                    if (!annos.isEmpty())
                                        t = illegal(annos.head.pos);
                                    t = to(F.at(pos).Indexed(t, t1));
                                }
                                accept(RBRACKET);
                            }
                            break loop;
                        case LPAREN:
                            if ((mode & EXPR) != 0) {
                                mode = EXPR;
                                t = arguments(typeArgs, t);
                                if (!annos.isEmpty())
                                    t = illegal(annos.head.pos);
                                typeArgs = null;
                            }
                            break loop;
                        case DOT:
                            nextToken();
                            int oldmode = mode;
                            mode &= ~NOPARAMS;
                            typeArgs = typeArgumentsOpt(EXPR);
                            mode = oldmode;
                            if ((mode & EXPR) != 0) {
                                switch(token.kind) {
                                    case CLASS:
                                        if (typeArgs != null)
                                            return illegal();
                                        mode = EXPR;
                                        t = to(F.at(pos).Select(t, names._class));
                                        nextToken();
                                        break loop;
                                    case THIS:
                                        if (typeArgs != null)
                                            return illegal();
                                        mode = EXPR;
                                        t = to(F.at(pos).Select(t, names._this));
                                        nextToken();
                                        break loop;
                                    case SUPER:
                                        mode = EXPR;
                                        t = to(F.at(pos).Select(t, names._super));
                                        t = superSuffix(typeArgs, t);
                                        typeArgs = null;
                                        break loop;
                                    case NEW:
                                        if (typeArgs != null)
                                            return illegal();
                                        mode = EXPR;
                                        int pos1 = token.pos;
                                        nextToken();
                                        if (token.kind == LT)
                                            typeArgs = typeArguments(false);
                                        t = innerCreator(pos1, typeArgs, t);
                                        typeArgs = null;
                                        break loop;
                                }
                            }
                            List<JCAnnotation> tyannos = null;
                            if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) {
                                tyannos = typeAnnotationsOpt();
                            }
                            // typeArgs saved for next loop iteration.
                            t = toP(F.at(pos).Select(t, ident()));
                            if (tyannos != null && tyannos.nonEmpty()) {
                                t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
                            }
                            break;
                        case ELLIPSIS:
                            if (this.permitTypeAnnotationsPushBack) {
                                this.typeAnnotationsPushedBack = annos;
                            } else if (annos.nonEmpty()) {
                                // Don't return here -- error recovery attempt
                                illegal(annos.head.pos);
                            }
                            break loop;
                        case LT:
                            if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
                                // this is an unbound method reference whose qualifier
                                // is a generic type i.e. A<S>::m
                                int pos1 = token.pos;
                                accept(LT);
                                ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
                                args.append(typeArgument());
                                while (token.kind == COMMA) {
                                    nextToken();
                                    args.append(typeArgument());
                                }
                                accept(GT);
                                t = toP(F.at(pos1).TypeApply(t, args.toList()));
                                checkGenerics();
                                while (token.kind == DOT) {
                                    nextToken();
                                    mode = TYPE;
                                    t = toP(F.at(token.pos).Select(t, ident()));
                                    t = typeArgumentsOpt(t);
                                }
                                t = bracketsOpt(t);
                                if (token.kind != COLCOL) {
                                    // method reference expected here
                                    t = illegal();
                                }
                                mode = EXPR;
                                return term3Rest(t, typeArgs);
                            }
                            break loop;
                        default:
                            break loop;
                    }
                }
            }
            if (typeArgs != null)
                illegal();
            t = typeArgumentsOpt(t);
            break;
        case BYTE:
        case SHORT:
        case CHAR:
        case INT:
        case LONG:
        case FLOAT:
        case DOUBLE:
        case BOOLEAN:
            if (typeArgs != null)
                illegal();
            t = bracketsSuffix(bracketsOpt(basicType()));
            break;
        case VOID:
            if (typeArgs != null)
                illegal();
            if ((mode & EXPR) != 0) {
                nextToken();
                if (token.kind == DOT) {
                    JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
                    t = bracketsSuffix(ti);
                } else {
                    return illegal(pos);
                }
            } else {
                // Support the corner case of myMethodHandle.<void>invoke() by passing
                // a void type (like other primitive types) to the next phase.
                // The error will be reported in Attr.attribTypes or Attr.visitApply.
                JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
                nextToken();
                return ti;
            // return illegal();
            }
            break;
        default:
            return illegal();
    }
    return term3Rest(t, typeArgs);
}
Also used : TokenKind(org.eclipse.ceylon.langtools.tools.javac.parser.Tokens.TokenKind) List(org.eclipse.ceylon.langtools.tools.javac.util.List)

Example 2 with TokenKind

use of org.eclipse.ceylon.langtools.tools.javac.parser.Tokens.TokenKind in project ceylon by eclipse.

the class JavacParser method termRest.

JCExpression termRest(JCExpression t) {
    switch(token.kind) {
        case EQ:
            {
                int pos = token.pos;
                nextToken();
                mode = EXPR;
                JCExpression t1 = term();
                return toP(F.at(pos).Assign(t, t1));
            }
        case PLUSEQ:
        case SUBEQ:
        case STAREQ:
        case SLASHEQ:
        case PERCENTEQ:
        case AMPEQ:
        case BAREQ:
        case CARETEQ:
        case LTLTEQ:
        case GTGTEQ:
        case GTGTGTEQ:
            int pos = token.pos;
            TokenKind tk = token.kind;
            nextToken();
            mode = EXPR;
            JCExpression t1 = term();
            return F.at(pos).Assignop(optag(tk), t, t1);
        default:
            return t;
    }
}
Also used : TokenKind(org.eclipse.ceylon.langtools.tools.javac.parser.Tokens.TokenKind)

Aggregations

TokenKind (org.eclipse.ceylon.langtools.tools.javac.parser.Tokens.TokenKind)2 List (org.eclipse.ceylon.langtools.tools.javac.util.List)1