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; }
@Nullable private static IElementType getGtTokenType(final PsiBuilder builder) { IElementType tokenType = builder.getTokenType(); if (tokenType != JavaTokenType.GT) return tokenType; if (builder.rawLookup(1) == JavaTokenType.GT) { if (builder.rawLookup(2) == JavaTokenType.GT) { if (builder.rawLookup(3) == JavaTokenType.EQ) { tokenType = JavaTokenType.GTGTGTEQ; } else { tokenType = JavaTokenType.GTGTGT; } } else if (builder.rawLookup(2) == JavaTokenType.EQ) { tokenType = JavaTokenType.GTGTEQ; } else { tokenType = JavaTokenType.GTGT; } } else if (builder.rawLookup(1) == JavaTokenType.EQ) { tokenType = JavaTokenType.GE; } return tokenType; }
private static void addCompletionVariant( ErrorState state, CompletionState completionState, PsiBuilder builder_, Object o, int offset) { boolean add = false; int diff = completionState.offset - offset; String text = completionState.convertItem(o); int length = text == null ? 0 : text.length(); if (length == 0) return; if (diff == 0) { add = true; } else if (diff > 0 && diff <= length) { CharSequence fragment = builder_.getOriginalText().subSequence(offset, completionState.offset); add = StringUtil.startsWithIgnoreCase(text, fragment.toString()); } else if (diff < 0) { for (int i = -1; ; i--) { IElementType type = builder_.rawLookup(i); int tokenStart = builder_.rawTokenTypeStart(i); if (state.whitespaceTokens.contains(type) || state.commentTokens.contains(type)) { diff = completionState.offset - tokenStart; } else if (type != null && tokenStart < completionState.offset) { CharSequence fragment = builder_.getOriginalText().subSequence(tokenStart, completionState.offset); if (StringUtil.startsWithIgnoreCase(text, fragment.toString())) { diff = completionState.offset - tokenStart; } break; } else break; } add = diff >= 0 && diff < length; } add = add && length > 1 && !(text.charAt(0) == '<' && text.charAt(length - 1) == '>') && !(text.charAt(0) == '\'' && text.charAt(length - 1) == '\'' && length < 5); if (add) { completionState.items.add(text); } }
private static void addCompletionVariant( @NotNull PsiBuilder builder, @NotNull CompletionState completionState, Object o) { int offset = builder.getCurrentOffset(); if (!builder.eof() && offset == builder.rawTokenTypeStart(1)) return; // suppress for zero-length tokens boolean add = false; int diff = completionState.offset - offset; String text = completionState.convertItem(o); int length = text == null ? 0 : text.length(); if (length == 0) return; if (diff == 0) { add = true; } else if (diff > 0 && diff <= length) { CharSequence fragment = builder.getOriginalText().subSequence(offset, completionState.offset); add = completionState.prefixMatches(fragment.toString(), text); } else if (diff < 0) { for (int i = -1; ; i--) { IElementType type = builder.rawLookup(i); int tokenStart = builder.rawTokenTypeStart(i); if (isWhitespaceOrComment(builder, type)) { diff = completionState.offset - tokenStart; } else if (type != null && tokenStart < completionState.offset) { CharSequence fragment = builder.getOriginalText().subSequence(tokenStart, completionState.offset); if (completionState.prefixMatches(fragment.toString(), text)) { diff = completionState.offset - tokenStart; } break; } else break; } add = diff >= 0 && diff < length; } add = add && length > 1 && !(text.charAt(0) == '<' && text.charAt(length - 1) == '>') && !(text.charAt(0) == '\'' && text.charAt(length - 1) == '\'' && length < 5); if (add) { completionState.addItem(builder, text); } }
public static boolean parseAsTree( ErrorState state, final PsiBuilder builder, int level, final IElementType chunkType, boolean checkBraces, final Parser parser, final Parser eatMoreCondition) { final LinkedList<Pair<PsiBuilder.Marker, PsiBuilder.Marker>> parenList = new LinkedList<Pair<PsiBuilder.Marker, PsiBuilder.Marker>>(); final LinkedList<Pair<PsiBuilder.Marker, Integer>> siblingList = new LinkedList<Pair<PsiBuilder.Marker, Integer>>(); PsiBuilder.Marker marker = null; final Runnable checkSiblingsRunnable = new Runnable() { @Override public void run() { main: while (!siblingList.isEmpty()) { final Pair<PsiBuilder.Marker, PsiBuilder.Marker> parenPair = parenList.peek(); final int rating = siblingList.getFirst().second; int count = 0; for (Pair<PsiBuilder.Marker, Integer> pair : siblingList) { if (pair.second != rating || parenPair != null && pair.first == parenPair.second) break main; if (++count >= MAX_CHILDREN_IN_TREE) { PsiBuilder.Marker parentMarker = pair.first.precede(); parentMarker.setCustomEdgeTokenBinders( WhitespacesBinders.GREEDY_LEFT_BINDER, null); while (count-- > 0) { siblingList.removeFirst(); } parentMarker.done(chunkType); siblingList.addFirst(Pair.create(parentMarker, rating + 1)); continue main; } } break; } } }; boolean checkParens = state.braces != null && checkBraces; int totalCount = 0; int tokenCount = 0; if (checkParens) { int tokenIdx = -1; while (builder.rawLookup(tokenIdx) == TokenType.WHITE_SPACE) tokenIdx--; LighterASTNode doneMarker = builder.rawLookup(tokenIdx) == state.braces[0].getLeftBraceType() ? builder.getLatestDoneMarker() : null; if (doneMarker != null && doneMarker.getStartOffset() == builder.rawTokenTypeStart(tokenIdx) && doneMarker.getTokenType() == TokenType.ERROR_ELEMENT) { parenList.add( Pair.create(((PsiBuilder.Marker) doneMarker).precede(), (PsiBuilder.Marker) null)); } } while (true) { final IElementType tokenType = builder.getTokenType(); if (checkParens && (tokenType == state.braces[0].getLeftBraceType() || tokenType == state.braces[0].getRightBraceType() && !parenList.isEmpty())) { if (marker != null) { marker.done(chunkType); siblingList.addFirst(Pair.create(marker, 1)); marker = null; tokenCount = 0; } if (tokenType == state.braces[0].getLeftBraceType()) { final Pair<PsiBuilder.Marker, Integer> prev = siblingList.peek(); parenList.addFirst(Pair.create(builder.mark(), prev == null ? null : prev.first)); } checkSiblingsRunnable.run(); builder.advanceLexer(); if (tokenType == state.braces[0].getRightBraceType()) { final Pair<PsiBuilder.Marker, PsiBuilder.Marker> pair = parenList.removeFirst(); pair.first.done(chunkType); // drop all markers inside parens while (!siblingList.isEmpty() && siblingList.getFirst().first != pair.second) { siblingList.removeFirst(); } siblingList.addFirst(Pair.create(pair.first, 1)); checkSiblingsRunnable.run(); } } else { if (marker == null) { marker = builder.mark(); marker.setCustomEdgeTokenBinders(WhitespacesBinders.GREEDY_LEFT_BINDER, null); } final boolean result = (!parenList.isEmpty() || eatMoreCondition.parse(builder, level + 1)) && parser.parse(builder, level + 1); if (result) { tokenCount++; totalCount++; } if (!result) { break; } } if (tokenCount >= MAX_CHILDREN_IN_TREE && marker != null) { marker.done(chunkType); siblingList.addFirst(Pair.create(marker, 1)); checkSiblingsRunnable.run(); marker = null; tokenCount = 0; } } if (marker != null) { marker.drop(); } for (Pair<PsiBuilder.Marker, PsiBuilder.Marker> pair : parenList) { pair.first.drop(); } return totalCount != 0; }
@Nullable public IElementType rawLookup(int step) { return myBuilder.rawLookup(step); }
/** * 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; }