/** * Named list operators * * @param b PerlBuilder * @param l Parsing level * @return parsing result */ public static boolean isListOperator(PsiBuilder b, int l) { PerlTokenData prevTokenData = ((PerlBuilder) b).lookupToken(-1); if (prevTokenData != null && prevTokenData.getTokenType() == OPERATOR_DEREFERENCE) return false; IElementType tokenType = b.getTokenType(); IElementType nextTokenType = b.lookAhead(1); if (CONVERTABLE_TOKENS.contains(tokenType) && nextTokenType != LEFT_PAREN // not function call && !PACKAGE_TOKENS.contains(nextTokenType) // not method Package:: && !(nextTokenType == IDENTIFIER && ((PerlBuilder) b) .isKnownPackage( ((PerlBuilder) b).lookupToken(1).getTokenText())) // not Method Package ) // todo we should check current namespace here return !PerlSubUtil.BUILT_IN_UNARY.contains(b.getTokenText()); else if (PACKAGE_TOKENS.contains(tokenType) && CONVERTABLE_TOKENS.contains(nextTokenType) && b.lookAhead(2) != LEFT_PAREN) return !PerlSubUtil.isUnary( b.getTokenText(), ((PerlBuilder) b).lookupToken(1).getTokenText()); return false; }
/** * Smart parser for ->, makes }->[ optional * * @param b PerlBuilder * @param l parsing level * @return parsing result */ public static boolean parseArrowSmart(PsiBuilder b, int l) { IElementType tokenType = b.getTokenType(); if (b.getTokenType() == OPERATOR_DEREFERENCE) { return consumeToken(b, OPERATOR_DEREFERENCE); } else { assert b instanceof PerlBuilder; PerlTokenData prevToken = ((PerlBuilder) b).lookupToken(-1); IElementType prevTokenType = prevToken == null ? null : prevToken.getTokenType(); // optional }->[ or ]->{ if ((prevTokenType == RIGHT_BRACE || prevTokenType == RIGHT_BRACKET) && (tokenType == LEFT_BRACE || tokenType == LEFT_BRACKET || tokenType == LEFT_PAREN)) return true; } return false; }
/** * Named unary operators * * @param b PerlBuilder * @param l parsing level * @return parsing result */ public static boolean isUnaryOperator(PsiBuilder b, int l) { assert b instanceof PerlBuilder; PerlTokenData prevTokenData = ((PerlBuilder) b).lookupToken(-1); if (prevTokenData != null && prevTokenData.getTokenType() == OPERATOR_DEREFERENCE) return false; IElementType tokenType = b.getTokenType(); IElementType nextTokenType = b.lookAhead(1); if (CONVERTABLE_TOKENS.contains(tokenType) && nextTokenType != LEFT_PAREN && !PACKAGE_TOKENS.contains(nextTokenType)) // todo we should check current namespace here return PerlSubUtil.BUILT_IN_UNARY.contains(b.getTokenText()); else if (PACKAGE_TOKENS.contains(tokenType) && CONVERTABLE_TOKENS.contains(SUB) && b.lookAhead(2) != LEFT_PAREN) { PerlTokenData nextToken = ((PerlBuilder) b).lookupToken(1); if (nextToken != null) return PerlSubUtil.isUnary(b.getTokenText(), nextToken.getTokenText()); } return false; }
/** * Parses invocable method As input we may have: PACKAGE_IDENTIFIER IDENTIFIER Foo::sub IDENTIFIER * PACKAGE_IDENTIFIER sub Foo:: IDENTIFIER IDENTIFIER sub Foo * * @param b PerlBuilder * @param l parsing level * @return parsing result */ public static boolean parseMethod(PsiBuilder b, int l) { IElementType currentTokenType = b.getTokenType(); IElementType nextTokenType = b.lookAhead(1); assert b instanceof PerlBuilder; // can be // Foo::method // Foo::Bar if (PACKAGE_TOKENS.contains(currentTokenType) && CONVERTABLE_TOKENS.contains(nextTokenType)) { PerlTokenData nextTokenData = ((PerlBuilder) b).lookupToken(1); PerlTokenData nextNextTokenData = ((PerlBuilder) b).lookupToken(2); IElementType nextNextTokenType = nextNextTokenData == null ? null : nextNextTokenData.getTokenType(); String canonicalPackageName = PerlPackageUtil.getCanonicalPackageName(b.getTokenText()); String potentialSubName = canonicalPackageName + "::" + nextTokenData.getTokenText(); if (nextNextTokenType == LEFT_PAREN // Package::Identifier( - what can it be? || ((PerlBuilder) b).isKnownSub(potentialSubName) // we know this sub || !((PerlBuilder) b).isKnownPackage(potentialSubName)) // we don't know such package return convertPackageIdentifier(b, l) && convertIdentifier(b, l, SUB); else return false; } // method else if (CONVERTABLE_TOKENS.contains(currentTokenType)) { PerlTokenData prevTokenData = ((PerlBuilder) b).lookupToken(-1); // ->sub if (prevTokenData != null && prevTokenData.getTokenType() == OPERATOR_DEREFERENCE) return convertIdentifier(b, l, SUB); // may be // method Foo:: // method Foo::Bar // method Foo::othermethod else if (PACKAGE_TOKENS.contains(nextTokenType)) { IElementType nextNextTokenType = b.lookAhead(2); // sub Foo::->method if (nextNextTokenType == OPERATOR_DEREFERENCE) return convertIdentifier(b, l, SUB); // identifier Package::identifier else if (CONVERTABLE_TOKENS.contains(nextNextTokenType)) { // identifier Package::identifier-> if (b.lookAhead(3) == OPERATOR_DEREFERENCE) return convertIdentifier(b, l, SUB); PerlTokenData nextTokenData = ((PerlBuilder) b).lookupToken(1); PerlTokenData nextNextTokenData = ((PerlBuilder) b).lookupToken(2); String packageOrSub = PerlPackageUtil.getCanonicalPackageName(nextTokenData.getTokenText()) + "::" + nextNextTokenData.getTokenText(); if (((PerlBuilder) b).isKnownSub(packageOrSub)) return convertIdentifier(b, l, SUB); else if (((PerlBuilder) b).isKnownPackage(packageOrSub)) return convertIdentifier(b, l, SUB) && mergePackageName(b, l); return convertIdentifier(b, l, SUB); } else // it's method Package:: return convertIdentifier(b, l, SUB) && convertPackageIdentifier(b, l); } // may be // method Foo else if (CONVERTABLE_TOKENS.contains(nextTokenType) && b.lookAhead(2) != OPERATOR_DEREFERENCE) { PerlTokenData nextTokenData = ((PerlBuilder) b).lookupToken(1); String potentialSubName = nextTokenData.getTokenText() + "::" + b.getTokenText(); if (((PerlBuilder) b).isKnownSub(potentialSubName)) return convertIdentifier(b, l, SUB) && convertIdentifier(b, l, PACKAGE); else return convertIdentifier(b, l, SUB); } // KnownPackage-> else if (nextTokenType == OPERATOR_DEREFERENCE && ((PerlBuilder) b).isKnownPackage(b.getTokenText())) return false; // it's just sub else return convertIdentifier(b, l, SUB); } return false; }