Пример #1
0
  /**
   * 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;
  }
  @Nullable
  private PsiBuilder.Marker parseLambdaAfterParenth(
      final PsiBuilder builder, @Nullable final PsiBuilder.Marker typeList) {
    final boolean isLambda;
    final boolean isTyped;

    final IElementType nextToken1 = builder.lookAhead(1);
    final IElementType nextToken2 = builder.lookAhead(2);
    if (nextToken1 == JavaTokenType.RPARENTH && nextToken2 == JavaTokenType.ARROW) {
      isLambda = true;
      isTyped = false;
    } else if (nextToken1 == JavaTokenType.AT
        || ElementType.MODIFIER_BIT_SET.contains(nextToken1)
        || ElementType.PRIMITIVE_TYPE_BIT_SET.contains(nextToken1)) {
      isLambda = true;
      isTyped = true;
    } else if (nextToken1 == JavaTokenType.IDENTIFIER) {
      if (nextToken2 == JavaTokenType.COMMA
          || nextToken2 == JavaTokenType.RPARENTH && builder.lookAhead(3) == JavaTokenType.ARROW) {
        isLambda = true;
        isTyped = false;
      } else if (nextToken2 == JavaTokenType.ARROW) {
        isLambda = false;
        isTyped = false;
      } else {
        boolean arrow = false;

        final PsiBuilder.Marker marker = builder.mark();
        while (!builder.eof()) {
          builder.advanceLexer();
          final IElementType tokenType = builder.getTokenType();
          if (tokenType == JavaTokenType.ARROW) {
            arrow = true;
            break;
          }
          if (tokenType == JavaTokenType.RPARENTH) {
            arrow = builder.lookAhead(1) == JavaTokenType.ARROW;
            break;
          } else if (tokenType == JavaTokenType.LPARENTH
              || tokenType == JavaTokenType.SEMICOLON
              || tokenType == JavaTokenType.LBRACE
              || tokenType == JavaTokenType.RBRACE) {
            break;
          }
        }
        marker.rollbackTo();

        isLambda = arrow;
        isTyped = true;
      }
    } else {
      isLambda = false;
      isTyped = false;
    }

    return isLambda ? parseLambdaExpression(builder, isTyped, typeList) : null;
  }
Пример #3
0
  /**
   * Statement recovery function. Should not consume token, only check;
   *
   * @param b PerlBuilder
   * @param l parsing level
   * @return parsing result
   */
  public static boolean recoverStatement(PsiBuilder b, int l) {
    assert b instanceof PerlBuilder;

    if (!((PerlBuilder) b).isRecoveringStatement()) ((PerlBuilder) b).startRecovery();

    IElementType currentTokenType = b.getTokenType();

    //		System.err.println("Checking " + b.getTokenText() + currentTokenType);

    if (currentTokenType == null // got end of file
        || ((PerlBuilder) b).getBracesLevel() == 0
            && ( // we are not in braced statement
            UNCONDITIONAL_STATEMENT_RECOVERY_TOKENS.contains(
                    currentTokenType) // got semi, package, end of regex, use, compound or suffix
                || currentTokenType == RESERVED_SUB
                    && STATEMENT_RECOVERY_SUB_SUFFIX.contains(b.lookAhead(1)) // got sub definition
            )) {
      ((PerlBuilder) b).stopRecovery();
      return false;
    }

    if (currentTokenType == LEFT_BRACE) ((PerlBuilder) b).openBrace();
    else if (currentTokenType == RIGHT_BRACE) ((PerlBuilder) b).closeBrace();

    return true;
  }
Пример #4
0
 /**
  * Parsing label declaration LABEL:
  *
  * @param b PerlBuilder
  * @param l parsing level
  * @return parsing result
  */
 public static boolean parseLabelDeclaration(PsiBuilder b, int l) {
   if (CONVERTABLE_TOKENS.contains(b.getTokenType()) && b.lookAhead(1) == COLON) {
     PsiBuilder.Marker m = b.mark();
     b.advanceLexer();
     m.collapse(LABEL);
     b.advanceLexer();
     return true;
   }
   return false;
 }
Пример #5
0
  public static boolean convertBracedString(PsiBuilder b, int l) {

    if (CONVERTABLE_TOKENS.contains(b.getTokenType()) && b.lookAhead(1) == RIGHT_BRACE) {
      // fixme shouldn't we add string_sq here?
      PsiBuilder.Marker m = b.mark();
      b.advanceLexer();
      m.collapse(STRING_CONTENT);
      return true;
    }
    return false;
  }
Пример #6
0
  public static boolean parseAmbiguousSigil(PsiBuilder b, int l, IElementType sigilTokenType) {
    IElementType tokenType = b.getTokenType();
    if (tokenType == sigilTokenType) {
      if (PerlParserDefinition.WHITE_SPACE_AND_COMMENTS.contains(b.rawLookup(1))
          && b.lookAhead(1) != LEFT_BRACE) // space disallowed after * or % if it's not a cast
      return false;

      b.advanceLexer();
      return true;
    }

    return false;
  }
Пример #7
0
  /**
   * Checks and parses bareword filehandle for <FH> operations
   *
   * @param b PerlBuilder
   * @param l parsing level
   * @return parsing result
   */
  public static boolean parseReadHandle(PsiBuilder b, int l) {
    IElementType currentTokenType = b.getTokenType();
    IElementType nextTokenType = b.lookAhead(1);

    if (CONVERTABLE_TOKENS.contains(currentTokenType) && nextTokenType == OPERATOR_GT_NUMERIC) {
      PsiBuilder.Marker m = b.mark();
      b.advanceLexer();
      m.collapse(HANDLE);
      return true;
    }

    return false;
  }
Пример #8
0
  /**
   * 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;
  }
  public static void parseInclude(PsiBuilder builder) {
    PsiBuilder.Marker marker = builder.mark();

    IElementType nextElement = builder.lookAhead(1);

    if (nextElement != STRING_LITERAL && nextElement != STRING_INCLUDE_LITERAL)
      builder.error("Incorrect include name");
    else builder.advanceLexer();

    builder.advanceLexer();

    done(
        marker,
        nextElement == STRING_LITERAL ? CPsiSharpInclude.class : CPsiSharpIndepInclude.class);

    skipLines(builder);
  }
Пример #10
0
  /**
   * parser for print/say/printf filehandle
   *
   * @param b PerlBuilder
   * @param l parsing level
   * @return parsing result
   */
  public static boolean parsePrintHandle(PsiBuilder b, int l) {
    IElementType currentTokenType = b.getTokenType();
    IElementType nextTokenType = b.lookAhead(1);
    assert b instanceof PerlBuilder;

    if (CONVERTABLE_TOKENS.contains(currentTokenType) // it's identifier
        && !PRINT_HANDLE_NEGATE_SUFFIX.contains(nextTokenType) // no negation tokens
        && !PerlSubUtil.BUILT_IN.contains(
            b.getTokenText()) // it's not built in. crude, probably we should check any known sub
    ) {
      PsiBuilder.Marker m = b.mark();
      b.advanceLexer();
      m.collapse(HANDLE);
      return true;
    }

    return false;
  }
Пример #11
0
  /**
   * Merges sequence [package] identifier to a package
   *
   * @param b PerlBuilder
   * @param l parsing level
   * @return result
   */
  public static boolean mergePackageName(PsiBuilder b, int l) {
    IElementType tokenType = b.getTokenType();

    if (tokenType == PACKAGE) {
      b.advanceLexer();
      return true;
    } else if (PACKAGE_TOKENS.contains(tokenType) && CONVERTABLE_TOKENS.contains(b.lookAhead(1))) {
      PsiBuilder.Marker m = b.mark();
      b.advanceLexer();
      b.advanceLexer();
      m.collapse(PACKAGE);
      return true;
    } else if (PACKAGE_TOKENS.contains(tokenType) // explicit package name, like Foo::->method()
        || CONVERTABLE_TOKENS.contains(tokenType) // single word package
    ) {
      PsiBuilder.Marker m = b.mark();
      b.advanceLexer();
      m.collapse(PACKAGE);
      return true;
    }

    return false;
  }
 @Nullable
 public IElementType lookAhead(int step) {
   return myBuilder.lookAhead(step);
 }
  @Nullable
  private PsiBuilder.Marker parsePrimaryExpressionStart(final PsiBuilder builder) {
    IElementType tokenType = builder.getTokenType();

    if (LITERALS.contains(tokenType)) {
      final PsiBuilder.Marker literal = builder.mark();
      builder.advanceLexer();
      literal.done(JavaElementType.LITERAL_EXPRESSION);
      return literal;
    }

    if (tokenType == JavaTokenType.LBRACE) {
      return parseArrayInitializer(builder);
    }

    if (tokenType == JavaTokenType.NEW_KEYWORD) {
      return parseNew(builder, null);
    }

    if (tokenType == JavaTokenType.LPARENTH) {
      final PsiBuilder.Marker lambda = parseLambdaAfterParenth(builder, null);
      if (lambda != null) {
        return lambda;
      }

      final PsiBuilder.Marker parenth = builder.mark();
      builder.advanceLexer();

      final PsiBuilder.Marker inner = parse(builder);
      if (inner == null) {
        error(builder, JavaErrorMessages.message("expected.expression"));
      }

      if (!expect(builder, JavaTokenType.RPARENTH)) {
        if (inner != null) {
          error(builder, JavaErrorMessages.message("expected.rparen"));
        }
      }

      parenth.done(JavaElementType.PARENTH_EXPRESSION);
      return parenth;
    }

    if (TYPE_START.contains(tokenType)) {
      final PsiBuilder.Marker mark = builder.mark();

      final ReferenceParser.TypeInfo typeInfo =
          myParser.getReferenceParser().parseTypeInfo(builder, 0);
      if (typeInfo != null) {
        boolean optionalClassKeyword = typeInfo.isPrimitive || typeInfo.isArray;
        if (optionalClassKeyword || !typeInfo.hasErrors && typeInfo.isParameterized) {
          final PsiBuilder.Marker result =
              continueClassAccessOrMethodReference(builder, mark, optionalClassKeyword);
          if (result != null) {
            return result;
          }
        }
      }

      mark.rollbackTo();
    }

    PsiBuilder.Marker annotation = null;
    if (tokenType == JavaTokenType.AT) {
      annotation = myParser.getDeclarationParser().parseAnnotations(builder);
      tokenType = builder.getTokenType();
    }

    if (tokenType == JavaTokenType.IDENTIFIER) {
      if (builder.lookAhead(1) == JavaTokenType.ARROW) {
        return parseLambdaExpression(builder, false, null);
      }

      final PsiBuilder.Marker refExpr;
      if (annotation != null) {
        final PsiBuilder.Marker refParam = annotation.precede();
        refParam.doneBefore(JavaElementType.REFERENCE_PARAMETER_LIST, annotation);
        refExpr = refParam.precede();
      } else {
        refExpr = builder.mark();
        builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
      }

      builder.advanceLexer();
      refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
      return refExpr;
    }

    if (annotation != null) {
      annotation.rollbackTo();
      tokenType = builder.getTokenType();
    }

    PsiBuilder.Marker expr = null;
    if (tokenType == JavaTokenType.LT) {
      expr = builder.mark();

      if (!myParser.getReferenceParser().parseReferenceParameterList(builder, false, false)) {
        expr.rollbackTo();
        return null;
      }

      tokenType = builder.getTokenType();
      if (!THIS_OR_SUPER.contains(tokenType)) {
        expr.rollbackTo();
        return null;
      }
    }

    if (THIS_OR_SUPER.contains(tokenType)) {
      if (expr == null) {
        expr = builder.mark();
        builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
      }
      builder.advanceLexer();
      expr.done(
          builder.getTokenType() == JavaTokenType.LPARENTH
              ? JavaElementType.REFERENCE_EXPRESSION
              : tokenType == JavaTokenType.THIS_KEYWORD
                  ? JavaElementType.THIS_EXPRESSION
                  : JavaElementType.SUPER_EXPRESSION);
      return expr;
    }

    return null;
  }
Пример #14
0
  /**
   * Parses tokens as variables name; replaces:
   *
   * @param b PerlBuilder
   * @param l parsing level
   * @return parsing result
   */
  public static boolean parseVariableName(PsiBuilder b, int l) {
    IElementType currentTokenType = b.getTokenType();
    IElementType nextTokenType = b.rawLookup(1);

    PsiBuilder.Marker m;

    //		while (currentTokenType == SIGIL_SCALAR                                // sigil is here
    //				&& POST_SIGILS_SUFFIXES.contains(nextTokenType)            // next can be variable name
    //				)
    //		{
    //			if (m == null)
    //				m = b.mark();
    //			b.advanceLexer();
    //			currentTokenType = nextTokenType;
    //			nextTokenType = b.rawLookup(1);
    //		}
    //
    //		if (m != null)
    //			m.collapse(SCALAR_SIGILS);

    // checking for scalar cast
    if (currentTokenType == SIGIL_SCALAR && POST_SIGILS_SUFFIXES.contains(b.lookAhead(1)))
      return false;

    // $package::
    // $package::var
    if (PACKAGE_TOKENS.contains(currentTokenType)) {
      PsiBuilder.Marker mp = b.mark();
      b.advanceLexer();
      mp.collapse(PACKAGE);
      if (CONVERTABLE_TOKENS.contains(nextTokenType)) {
        PsiBuilder.Marker mv = b.mark();
        b.advanceLexer();
        mv.collapse(VARIABLE_NAME);
      }
      return true;
    }
    // $var
    else if (POSSIBLE_VARIABLE_NAME.contains(currentTokenType)) {
      if (currentTokenType == OPERATOR_BITWISE_XOR
          && CONTROL_VARIABLE_NAMES.contains(nextTokenType)) // branch for $^]
      {
        m = b.mark();
        b.advanceLexer();
        b.advanceLexer();
        m.collapse(VARIABLE_NAME);
      } else {
        PsiBuilder.Marker mv = b.mark();
        b.advanceLexer();
        mv.collapse(VARIABLE_NAME);
      }

      return true;
    }
    // ${var}
    else if (currentTokenType == LEFT_BRACE) {
      b.advanceLexer();
      currentTokenType = nextTokenType;
      nextTokenType = b.lookAhead(1);

      // ${package::}
      // ${package::var}
      if (PACKAGE_TOKENS.contains(currentTokenType)) {
        PsiBuilder.Marker mp = b.mark();
        b.advanceLexer();
        mp.collapse(PACKAGE);
        if (CONVERTABLE_TOKENS.contains(nextTokenType) && b.lookAhead(1) == RIGHT_BRACE) {
          PsiBuilder.Marker mv = b.mark();
          b.advanceLexer();
          mv.collapse(VARIABLE_NAME);
          b.advanceLexer();
          return true;
        } else if (nextTokenType == RIGHT_BRACE) {
          b.advanceLexer();
          return true;
        }
      }
      // ${var}
      else if (POSSIBLE_VARIABLE_NAME.contains(currentTokenType) && nextTokenType == RIGHT_BRACE) {
        PsiBuilder.Marker mv = b.mark();
        b.advanceLexer();
        mv.collapse(VARIABLE_NAME);
        b.advanceLexer();
        return true;
      }
    }

    return false;
  }
Пример #15
0
  /**
   * 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;
  }
Пример #16
0
 public static boolean mergeRequirePackageName(PsiBuilder b, int l) {
   if (CONVERTABLE_TOKENS.contains(b.getTokenType()) && b.lookAhead(1) == LEFT_PAREN) return false;
   return mergePackageName(b, l);
 }