| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.jetbrains.python.parsing; |
| |
| import com.intellij.lang.PsiBuilder; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.psi.tree.IElementType; |
| import com.intellij.psi.tree.TokenSet; |
| import com.jetbrains.python.PyElementTypes; |
| import com.jetbrains.python.PyTokenTypes; |
| import org.jetbrains.annotations.Nullable; |
| |
| import static com.jetbrains.python.PyBundle.message; |
| |
| /** |
| * @author yole |
| */ |
| public class ExpressionParsing extends Parsing { |
| private static final Logger LOG = Logger.getInstance("#ru.yole.pythonlanguage.parsing.ExpressionParsing"); |
| |
| public ExpressionParsing(ParsingContext context) { |
| super(context); |
| } |
| |
| public boolean parsePrimaryExpression(boolean isTargetExpression) { |
| final IElementType firstToken = myBuilder.getTokenType(); |
| if (firstToken == PyTokenTypes.IDENTIFIER) { |
| if (isTargetExpression) { |
| buildTokenElement(PyElementTypes.TARGET_EXPRESSION, myBuilder); |
| } |
| else { |
| buildTokenElement(getReferenceType(), myBuilder); |
| } |
| return true; |
| } |
| else if (firstToken == PyTokenTypes.INTEGER_LITERAL) { |
| buildTokenElement(PyElementTypes.INTEGER_LITERAL_EXPRESSION, myBuilder); |
| return true; |
| } |
| else if (firstToken == PyTokenTypes.FLOAT_LITERAL) { |
| buildTokenElement(PyElementTypes.FLOAT_LITERAL_EXPRESSION, myBuilder); |
| return true; |
| } |
| else if (firstToken == PyTokenTypes.IMAGINARY_LITERAL) { |
| buildTokenElement(PyElementTypes.IMAGINARY_LITERAL_EXPRESSION, myBuilder); |
| return true; |
| } |
| else if (firstToken == PyTokenTypes.NONE_KEYWORD) { |
| buildTokenElement(PyElementTypes.NONE_LITERAL_EXPRESSION, myBuilder); |
| return true; |
| } |
| else if (firstToken == PyTokenTypes.TRUE_KEYWORD || |
| firstToken == PyTokenTypes.FALSE_KEYWORD || |
| firstToken == PyTokenTypes.DEBUG_KEYWORD) { |
| buildTokenElement(PyElementTypes.BOOL_LITERAL_EXPRESSION, myBuilder); |
| return true; |
| } |
| else if (PyTokenTypes.STRING_NODES.contains(firstToken)) { |
| return parseStringLiteralExpression(); |
| } |
| else if (firstToken == PyTokenTypes.LPAR) { |
| parseParenthesizedExpression(isTargetExpression); |
| return true; |
| } |
| else if (firstToken == PyTokenTypes.LBRACKET) { |
| parseListLiteralExpression(myBuilder, isTargetExpression); |
| return true; |
| } |
| else if (firstToken == PyTokenTypes.LBRACE) { |
| parseDictOrSetDisplay(); |
| return true; |
| } |
| else if (firstToken == PyTokenTypes.TICK) { |
| parseReprExpression(myBuilder); |
| return true; |
| } |
| else if (parseEllipsis()) { |
| return true; |
| } |
| return false; |
| } |
| |
| public boolean parseStringLiteralExpression() { |
| final PsiBuilder builder = myContext.getBuilder(); |
| if (PyTokenTypes.STRING_NODES.contains(builder.getTokenType())) { |
| final PsiBuilder.Marker marker = builder.mark(); |
| while (PyTokenTypes.STRING_NODES.contains(builder.getTokenType())) { |
| nextToken(); |
| } |
| marker.done(PyElementTypes.STRING_LITERAL_EXPRESSION); |
| return true; |
| } |
| return false; |
| } |
| |
| private void parseListLiteralExpression(final PsiBuilder builder, boolean isTargetExpression) { |
| LOG.assertTrue(builder.getTokenType() == PyTokenTypes.LBRACKET); |
| final PsiBuilder.Marker expr = builder.mark(); |
| builder.advanceLexer(); |
| if (builder.getTokenType() == PyTokenTypes.RBRACKET) { |
| builder.advanceLexer(); |
| expr.done(PyElementTypes.LIST_LITERAL_EXPRESSION); |
| return; |
| } |
| if (!parseSingleExpression(isTargetExpression)) { |
| builder.error(message("PARSE.expected.expression")); |
| } |
| if (builder.getTokenType() == PyTokenTypes.FOR_KEYWORD) { |
| parseComprehension(expr, PyTokenTypes.RBRACKET, PyElementTypes.LIST_COMP_EXPRESSION); |
| } |
| else { |
| while (builder.getTokenType() != PyTokenTypes.RBRACKET) { |
| if (!matchToken(PyTokenTypes.COMMA)) { |
| builder.error("expected ',' or ']'"); |
| } |
| if (atToken(PyTokenTypes.RBRACKET)) { |
| break; |
| } |
| if (!parseSingleExpression(isTargetExpression)) { |
| builder.error(message("PARSE.expected.expr.or.comma.or.bracket")); |
| break; |
| } |
| } |
| checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket")); |
| expr.done(PyElementTypes.LIST_LITERAL_EXPRESSION); |
| } |
| } |
| |
| private void parseComprehension(PsiBuilder.Marker expr, |
| @Nullable final IElementType endToken, |
| final IElementType exprType) { |
| assertCurrentToken(PyTokenTypes.FOR_KEYWORD); |
| while (true) { |
| myBuilder.advanceLexer(); |
| parseExpression(true, true); |
| parseComprehensionRange(exprType == PyElementTypes.GENERATOR_EXPRESSION); |
| while (myBuilder.getTokenType() == PyTokenTypes.IF_KEYWORD) { |
| myBuilder.advanceLexer(); |
| if (!parseOldExpression()) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| } |
| if (atToken(PyTokenTypes.FOR_KEYWORD)) { |
| continue; |
| } |
| if (endToken == null || matchToken(endToken)) { |
| break; |
| } |
| myBuilder.error(message("PARSE.expected.for.or.bracket")); |
| break; |
| } |
| expr.done(exprType); |
| } |
| |
| protected void parseComprehensionRange(boolean generatorExpression) { |
| checkMatches(PyTokenTypes.IN_KEYWORD, "'in' expected"); |
| boolean result; |
| if (generatorExpression) { |
| result = parseORTestExpression(false, false); |
| } |
| else { |
| result = parseTupleExpression(false, false, true); |
| } |
| if (!result) { |
| myBuilder.error("expression expected"); |
| } |
| } |
| |
| private void parseDictOrSetDisplay() { |
| LOG.assertTrue(myBuilder.getTokenType() == PyTokenTypes.LBRACE); |
| final PsiBuilder.Marker expr = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| |
| if (matchToken(PyTokenTypes.RBRACE)) { |
| expr.done(PyElementTypes.DICT_LITERAL_EXPRESSION); |
| return; |
| } |
| |
| final PsiBuilder.Marker firstExprMarker = myBuilder.mark(); |
| if (!parseSingleExpression(false)) { |
| myBuilder.error("expression expected"); |
| firstExprMarker.drop(); |
| expr.done(PyElementTypes.DICT_LITERAL_EXPRESSION); |
| return; |
| } |
| |
| if (matchToken(PyTokenTypes.COLON)) { |
| parseDictLiteralTail(expr, firstExprMarker); |
| } |
| else if (atToken(PyTokenTypes.COMMA) || atToken(PyTokenTypes.RBRACE)) { |
| firstExprMarker.drop(); |
| parseSetLiteralTail(expr); |
| } |
| else if (atToken(PyTokenTypes.FOR_KEYWORD)) { |
| firstExprMarker.drop(); |
| parseComprehension(expr, PyTokenTypes.RBRACE, PyElementTypes.SET_COMP_EXPRESSION); |
| } |
| else { |
| myBuilder.error("expression expected"); |
| firstExprMarker.drop(); |
| expr.done(PyElementTypes.DICT_LITERAL_EXPRESSION); |
| } |
| } |
| |
| private void parseDictLiteralTail(PsiBuilder.Marker startMarker, PsiBuilder.Marker firstKeyValueMarker) { |
| if (!parseSingleExpression(false)) { |
| myBuilder.error("expression expected"); |
| firstKeyValueMarker.done(PyElementTypes.KEY_VALUE_EXPRESSION); |
| if (atToken(PyTokenTypes.RBRACE)) { |
| myBuilder.advanceLexer(); |
| } |
| startMarker.done(PyElementTypes.DICT_LITERAL_EXPRESSION); |
| return; |
| } |
| firstKeyValueMarker.done(PyElementTypes.KEY_VALUE_EXPRESSION); |
| if (myBuilder.getTokenType() == PyTokenTypes.FOR_KEYWORD) { |
| parseComprehension(startMarker, PyTokenTypes.RBRACE, PyElementTypes.DICT_COMP_EXPRESSION); |
| } |
| else { |
| while (myBuilder.getTokenType() != PyTokenTypes.RBRACE) { |
| checkMatches(PyTokenTypes.COMMA, message("PARSE.expected.comma")); |
| if (!parseKeyValueExpression()) { |
| break; |
| } |
| } |
| checkMatches(PyTokenTypes.RBRACE, message("PARSE.expected.rbrace")); |
| startMarker.done(PyElementTypes.DICT_LITERAL_EXPRESSION); |
| } |
| } |
| |
| private boolean parseKeyValueExpression() { |
| final PsiBuilder.Marker marker = myBuilder.mark(); |
| if (!parseSingleExpression(false)) { |
| marker.drop(); |
| return false; |
| } |
| checkMatches(PyTokenTypes.COLON, message("PARSE.expected.colon")); |
| if (!parseSingleExpression(false)) { |
| myBuilder.error("value expression expected"); |
| marker.drop(); |
| return false; |
| } |
| marker.done(PyElementTypes.KEY_VALUE_EXPRESSION); |
| return true; |
| } |
| |
| private void parseSetLiteralTail(PsiBuilder.Marker startMarker) { |
| while (myBuilder.getTokenType() != PyTokenTypes.RBRACE) { |
| checkMatches(PyTokenTypes.COMMA, message("PARSE.expected.comma")); |
| if (!parseSingleExpression(false)) { |
| break; |
| } |
| } |
| checkMatches(PyTokenTypes.RBRACE, message("PARSE.expected.rbrace")); |
| startMarker.done(PyElementTypes.SET_LITERAL_EXPRESSION); |
| } |
| |
| private void parseParenthesizedExpression(boolean isTargetExpression) { |
| LOG.assertTrue(myBuilder.getTokenType() == PyTokenTypes.LPAR); |
| final PsiBuilder.Marker expr = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| if (myBuilder.getTokenType() == PyTokenTypes.RPAR) { |
| myBuilder.advanceLexer(); |
| expr.done(PyElementTypes.TUPLE_EXPRESSION); |
| } |
| else { |
| parseYieldOrTupleExpression(isTargetExpression); |
| if (myBuilder.getTokenType() == PyTokenTypes.FOR_KEYWORD) { |
| parseComprehension(expr, PyTokenTypes.RPAR, PyElementTypes.GENERATOR_EXPRESSION); |
| } |
| else { |
| checkMatches(PyTokenTypes.RPAR, message("PARSE.expected.rpar")); |
| expr.done(PyElementTypes.PARENTHESIZED_EXPRESSION); |
| } |
| } |
| } |
| |
| private void parseReprExpression(PsiBuilder builder) { |
| LOG.assertTrue(builder.getTokenType() == PyTokenTypes.TICK); |
| final PsiBuilder.Marker expr = builder.mark(); |
| builder.advanceLexer(); |
| parseExpression(); |
| checkMatches(PyTokenTypes.TICK, message("PARSE.expected.tick")); |
| expr.done(PyElementTypes.REPR_EXPRESSION); |
| } |
| |
| public boolean parseMemberExpression(boolean isTargetExpression) { |
| // in sequence a.b.... .c all members but last are always references, and the last may be target. |
| boolean recastFirstIdentifier = false; |
| boolean recastQualifier = false; |
| do { |
| boolean firstIdentifierIsTarget = isTargetExpression && ! recastFirstIdentifier; |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parsePrimaryExpression(firstIdentifierIsTarget)) { |
| expr.drop(); |
| return false; |
| } |
| |
| while (true) { |
| final IElementType tokenType = myBuilder.getTokenType(); |
| if (tokenType == PyTokenTypes.DOT) { |
| if (firstIdentifierIsTarget) { |
| recastFirstIdentifier = true; |
| expr.rollbackTo(); |
| break; |
| } |
| myBuilder.advanceLexer(); |
| checkMatches(PyTokenTypes.IDENTIFIER, message("PARSE.expected.name")); |
| if (isTargetExpression && ! recastQualifier && !atAnyOfTokens(PyTokenTypes.DOT, PyTokenTypes.LPAR, PyTokenTypes.LBRACKET)) { |
| expr.done(PyElementTypes.TARGET_EXPRESSION); |
| } |
| else { |
| expr.done(getReferenceType()); |
| } |
| expr = expr.precede(); |
| } |
| else if (tokenType == PyTokenTypes.LPAR) { |
| parseArgumentList(); |
| expr.done(PyElementTypes.CALL_EXPRESSION); |
| expr = expr.precede(); |
| } |
| else if (tokenType == PyTokenTypes.LBRACKET) { |
| myBuilder.advanceLexer(); |
| PsiBuilder.Marker sliceOrTupleStart = myBuilder.mark(); |
| PsiBuilder.Marker sliceItemStart = myBuilder.mark(); |
| if (atToken(PyTokenTypes.COLON)) { |
| sliceOrTupleStart.drop(); |
| PsiBuilder.Marker sliceMarker = myBuilder.mark(); |
| sliceMarker.done(PyElementTypes.EMPTY_EXPRESSION); |
| parseSliceEnd(expr, sliceItemStart); |
| } |
| else { |
| boolean hadExpression = parseSingleExpression(false); |
| if (atToken(PyTokenTypes.COLON)) { |
| sliceOrTupleStart.drop(); |
| parseSliceEnd(expr, sliceItemStart); |
| } |
| else if (atToken(PyTokenTypes.COMMA)) { |
| sliceItemStart.done(PyElementTypes.SLICE_ITEM); |
| if (!parseSliceListTail(expr, sliceOrTupleStart)) { |
| sliceOrTupleStart.rollbackTo(); |
| if (!parseTupleExpression(false, false, false)) { |
| myBuilder.error("tuple expression expected"); |
| } |
| checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket")); |
| expr.done(PyElementTypes.SUBSCRIPTION_EXPRESSION); |
| } |
| } |
| else { |
| if (!hadExpression) { |
| myBuilder.error("expression expected"); |
| } |
| sliceOrTupleStart.drop(); |
| sliceItemStart.drop(); |
| checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket")); |
| expr.done(PyElementTypes.SUBSCRIPTION_EXPRESSION); |
| } |
| } |
| if (isTargetExpression && ! recastQualifier) { |
| recastFirstIdentifier = true; // subscription is always a reference |
| recastQualifier = true; // recast non-first qualifiers too |
| expr.rollbackTo(); |
| break; |
| } |
| expr = expr.precede(); |
| } |
| else { |
| expr.drop(); |
| break; |
| } |
| recastFirstIdentifier = false; // it is true only after a break; normal flow always unsets it. |
| // recastQualifier is untouched, it remembers whether qualifiers were already recast |
| } |
| } |
| while (recastFirstIdentifier); |
| |
| return true; |
| } |
| |
| private boolean parseEllipsis() { |
| if (atToken(PyTokenTypes.DOT)) { |
| final PsiBuilder.Marker maybeEllipsis = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| if (matchToken(PyTokenTypes.DOT) && matchToken(PyTokenTypes.DOT)) { |
| maybeEllipsis.done(PyElementTypes.NONE_LITERAL_EXPRESSION); |
| return true; |
| } |
| maybeEllipsis.rollbackTo(); |
| } |
| return false; |
| } |
| |
| private static TokenSet BRACKET_OR_COMMA = TokenSet.create(PyTokenTypes.RBRACKET, PyTokenTypes.COMMA); |
| private static TokenSet BRACKET_COLON_COMMA = TokenSet.create(PyTokenTypes.RBRACKET, PyTokenTypes.COLON, PyTokenTypes.COMMA); |
| |
| public void parseSliceEnd(PsiBuilder.Marker exprStart, PsiBuilder.Marker sliceItemStart) { |
| myBuilder.advanceLexer(); |
| if (atToken(PyTokenTypes.RBRACKET)) { |
| PsiBuilder.Marker sliceMarker = myBuilder.mark(); |
| sliceMarker.done(PyElementTypes.EMPTY_EXPRESSION); |
| sliceItemStart.done(PyElementTypes.SLICE_ITEM); |
| nextToken(); |
| exprStart.done(PyElementTypes.SLICE_EXPRESSION); |
| return; |
| } |
| else { |
| if (atToken(PyTokenTypes.COLON)) { |
| PsiBuilder.Marker sliceMarker = myBuilder.mark(); |
| sliceMarker.done(PyElementTypes.EMPTY_EXPRESSION); |
| } |
| else { |
| parseSingleExpression(false); |
| } |
| if (!BRACKET_COLON_COMMA.contains(myBuilder.getTokenType())) { |
| myBuilder.error(message("PARSE.expected.colon.or.rbracket")); |
| } |
| if (matchToken(PyTokenTypes.COLON)) { |
| parseSingleExpression(false); |
| } |
| |
| sliceItemStart.done(PyElementTypes.SLICE_ITEM); |
| if (!BRACKET_OR_COMMA.contains(myBuilder.getTokenType())) { |
| myBuilder.error("']' or ',' expected"); |
| } |
| } |
| |
| parseSliceListTail(exprStart, null); |
| } |
| |
| private boolean parseSliceListTail(PsiBuilder.Marker exprStart, @Nullable PsiBuilder.Marker sliceOrTupleStart) { |
| boolean inSlice = sliceOrTupleStart == null; |
| while (atToken(PyTokenTypes.COMMA)) { |
| nextToken(); |
| PsiBuilder.Marker sliceItemStart = myBuilder.mark(); |
| parseTestExpression(false, false); |
| if (matchToken(PyTokenTypes.COLON)) { |
| inSlice = true; |
| parseTestExpression(false, false); |
| if (matchToken(PyTokenTypes.COLON)) { |
| parseTestExpression(false, false); |
| } |
| } |
| sliceItemStart.done(PyElementTypes.SLICE_ITEM); |
| if (!BRACKET_OR_COMMA.contains(myBuilder.getTokenType())) { |
| myBuilder.error("']' or ',' expected"); |
| break; |
| } |
| } |
| checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket")); |
| |
| if (inSlice) { |
| if (sliceOrTupleStart != null) { |
| sliceOrTupleStart.drop(); |
| } |
| exprStart.done(PyElementTypes.SLICE_EXPRESSION); |
| } |
| return inSlice; |
| } |
| |
| public void parseArgumentList() { |
| LOG.assertTrue(myBuilder.getTokenType() == PyTokenTypes.LPAR); |
| final PsiBuilder.Marker arglist = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| PsiBuilder.Marker genexpr = myBuilder.mark(); |
| int argNumber = 0; |
| while (myBuilder.getTokenType() != PyTokenTypes.RPAR) { |
| argNumber++; |
| if (argNumber > 1) { |
| if (argNumber == 2 && atToken(PyTokenTypes.FOR_KEYWORD) && genexpr != null) { |
| parseComprehension(genexpr, null, PyElementTypes.GENERATOR_EXPRESSION); |
| genexpr = null; |
| continue; |
| } |
| else if (matchToken(PyTokenTypes.COMMA)) { |
| if (atToken(PyTokenTypes.RPAR)) { |
| break; |
| } |
| } |
| else { |
| myBuilder.error(message("PARSE.expected.comma.or.rpar")); |
| break; |
| } |
| } |
| if (myBuilder.getTokenType() == PyTokenTypes.MULT || myBuilder.getTokenType() == PyTokenTypes.EXP) { |
| final PsiBuilder.Marker starArgMarker = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| if (!parseSingleExpression(false)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| starArgMarker.done(PyElementTypes.STAR_ARGUMENT_EXPRESSION); |
| } |
| else { |
| if (myBuilder.getTokenType() == PyTokenTypes.IDENTIFIER) { |
| final PsiBuilder.Marker keywordArgMarker = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| if (myBuilder.getTokenType() == PyTokenTypes.EQ) { |
| myBuilder.advanceLexer(); |
| if (!parseSingleExpression(false)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| keywordArgMarker.done(PyElementTypes.KEYWORD_ARGUMENT_EXPRESSION); |
| continue; |
| } |
| keywordArgMarker.rollbackTo(); |
| } |
| if (!parseSingleExpression(false)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| break; |
| } |
| } |
| } |
| |
| if (genexpr != null) { |
| genexpr.drop(); |
| } |
| checkMatches(PyTokenTypes.RPAR, message("PARSE.expected.rpar")); |
| arglist.done(PyElementTypes.ARGUMENT_LIST); |
| } |
| |
| public boolean parseExpressionOptional() { |
| return parseTupleExpression(false, false, false); |
| } |
| |
| public boolean parseExpressionOptional(boolean isTargetExpression) { |
| return parseTupleExpression(false, isTargetExpression, false); |
| } |
| |
| public void parseExpression() { |
| if (!parseExpressionOptional()) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| } |
| |
| public void parseExpression(boolean stopOnIn, boolean isTargetExpression) { |
| if (!parseTupleExpression(stopOnIn, isTargetExpression, false)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| } |
| |
| public boolean parseYieldOrTupleExpression(final boolean isTargetExpression) { |
| if (myBuilder.getTokenType() == PyTokenTypes.YIELD_KEYWORD) { |
| PsiBuilder.Marker yieldExpr = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| if (myBuilder.getTokenType() == PyTokenTypes.FROM_KEYWORD) { |
| myBuilder.advanceLexer(); |
| final boolean parsed = parseTupleExpression(false, isTargetExpression, false); |
| if (!parsed) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| yieldExpr.done(PyElementTypes.YIELD_EXPRESSION); |
| return parsed; |
| } |
| else { |
| parseTupleExpression(false, isTargetExpression, false); |
| yieldExpr.done(PyElementTypes.YIELD_EXPRESSION); |
| return true; |
| } |
| } |
| else { |
| return parseTupleExpression(false, isTargetExpression, false); |
| } |
| } |
| |
| protected boolean parseTupleExpression(boolean stopOnIn, boolean isTargetExpression, final boolean oldTest) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| boolean exprParseResult = oldTest ? parseOldTestExpression() : parseTestExpression(stopOnIn, isTargetExpression); |
| if (!exprParseResult) { |
| expr.drop(); |
| return false; |
| } |
| if (myBuilder.getTokenType() == PyTokenTypes.COMMA) { |
| while (myBuilder.getTokenType() == PyTokenTypes.COMMA) { |
| myBuilder.advanceLexer(); |
| PsiBuilder.Marker expr2 = myBuilder.mark(); |
| exprParseResult = oldTest ? parseOldTestExpression() : parseTestExpression(stopOnIn, isTargetExpression); |
| if (!exprParseResult) { |
| expr2.rollbackTo(); |
| break; |
| } |
| expr2.drop(); |
| } |
| expr.done(PyElementTypes.TUPLE_EXPRESSION); |
| } |
| else { |
| expr.drop(); |
| } |
| return true; |
| } |
| |
| public boolean parseSingleExpression(boolean isTargetExpression) { |
| return parseTestExpression(false, isTargetExpression); |
| } |
| |
| public boolean parseOldExpression() { |
| if (myBuilder.getTokenType() == PyTokenTypes.LAMBDA_KEYWORD) { |
| return parseLambdaExpression(false); |
| } |
| return parseORTestExpression(false, false); |
| } |
| |
| private boolean parseTestExpression(boolean stopOnIn, boolean isTargetExpression) { |
| if (myBuilder.getTokenType() == PyTokenTypes.LAMBDA_KEYWORD) { |
| return parseLambdaExpression(false); |
| } |
| PsiBuilder.Marker condExpr = myBuilder.mark(); |
| if (!parseORTestExpression( stopOnIn, isTargetExpression)) { |
| condExpr.drop(); |
| return false; |
| } |
| if (myBuilder.getTokenType() == PyTokenTypes.IF_KEYWORD) { |
| PsiBuilder.Marker conditionMarker = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| if (!parseORTestExpression(stopOnIn, isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| else { |
| if (myBuilder.getTokenType() != PyTokenTypes.ELSE_KEYWORD) { |
| if (atToken(PyTokenTypes.COLON)) { // it's regular if statement. Bracket wasn't closed or new line was lost |
| conditionMarker.rollbackTo(); |
| condExpr.drop(); |
| return true; |
| } |
| else { |
| myBuilder.error(message("PARSE.expected.else")); |
| } |
| } |
| else { |
| myBuilder.advanceLexer(); |
| if (!parseTestExpression(stopOnIn, isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| } |
| } |
| conditionMarker.drop(); |
| condExpr.done(PyElementTypes.CONDITIONAL_EXPRESSION); |
| } |
| else { |
| condExpr.drop(); |
| } |
| return true; |
| } |
| |
| private boolean parseOldTestExpression() { |
| if (myBuilder.getTokenType() == PyTokenTypes.LAMBDA_KEYWORD) { |
| return parseLambdaExpression(true); |
| } |
| return parseORTestExpression(false, false); |
| } |
| |
| private boolean parseLambdaExpression(final boolean oldTest) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| getFunctionParser().parseParameterListContents(PyTokenTypes.COLON, false, true); |
| boolean parseExpressionResult = oldTest ? parseOldTestExpression() : parseSingleExpression(false); |
| if (!parseExpressionResult) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.LAMBDA_EXPRESSION); |
| return true; |
| } |
| |
| protected boolean parseORTestExpression(boolean stopOnIn, boolean isTargetExpression) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parseANDTestExpression(stopOnIn, isTargetExpression)) { |
| expr.drop(); |
| return false; |
| } |
| while (myBuilder.getTokenType() == PyTokenTypes.OR_KEYWORD) { |
| myBuilder.advanceLexer(); |
| if (!parseANDTestExpression(stopOnIn, isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.BINARY_EXPRESSION); |
| expr = expr.precede(); |
| } |
| |
| expr.drop(); |
| return true; |
| } |
| |
| private boolean parseANDTestExpression(boolean stopOnIn, boolean isTargetExpression) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parseNOTTestExpression(stopOnIn, isTargetExpression)) { |
| expr.drop(); |
| return false; |
| } |
| while (myBuilder.getTokenType() == PyTokenTypes.AND_KEYWORD) { |
| myBuilder.advanceLexer(); |
| if (!parseNOTTestExpression(stopOnIn, isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.BINARY_EXPRESSION); |
| expr = expr.precede(); |
| } |
| |
| expr.drop(); |
| return true; |
| } |
| |
| private boolean parseNOTTestExpression(boolean stopOnIn, boolean isTargetExpression) { |
| if (myBuilder.getTokenType() == PyTokenTypes.NOT_KEYWORD) { |
| final PsiBuilder.Marker expr = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| if (!parseNOTTestExpression(stopOnIn, isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.PREFIX_EXPRESSION); |
| return true; |
| } |
| else { |
| return parseComparisonExpression(stopOnIn, isTargetExpression); |
| } |
| } |
| |
| private boolean parseComparisonExpression(boolean stopOnIn, boolean isTargetExpression) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parseStarExpression(isTargetExpression)) { |
| expr.drop(); |
| return false; |
| } |
| if (stopOnIn && atToken(PyTokenTypes.IN_KEYWORD)) { |
| expr.drop(); |
| return true; |
| } |
| while (PyTokenTypes.COMPARISON_OPERATIONS.contains(myBuilder.getTokenType())) { |
| if (atToken(PyTokenTypes.NOT_KEYWORD)) { |
| PsiBuilder.Marker notMarker = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| if (!atToken(PyTokenTypes.IN_KEYWORD)) { |
| notMarker.rollbackTo(); |
| break; |
| } |
| notMarker.drop(); |
| myBuilder.advanceLexer(); |
| } |
| else if (atToken(PyTokenTypes.IS_KEYWORD)) { |
| myBuilder.advanceLexer(); |
| if (myBuilder.getTokenType() == PyTokenTypes.NOT_KEYWORD) { |
| myBuilder.advanceLexer(); |
| } |
| } |
| else { |
| myBuilder.advanceLexer(); |
| } |
| |
| if (!parseBitwiseORExpression(isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.BINARY_EXPRESSION); |
| expr = expr.precede(); |
| } |
| |
| expr.drop(); |
| return true; |
| } |
| |
| private boolean parseStarExpression(boolean isTargetExpression) { |
| if (atToken(PyTokenTypes.MULT)) { |
| PsiBuilder.Marker starExpr = myBuilder.mark(); |
| nextToken(); |
| if (!parseBitwiseORExpression(isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| starExpr.drop(); |
| return false; |
| } |
| starExpr.done(PyElementTypes.STAR_EXPRESSION); |
| return true; |
| } |
| return parseBitwiseORExpression(isTargetExpression); |
| } |
| |
| private boolean parseBitwiseORExpression(boolean isTargetExpression) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parseBitwiseXORExpression(isTargetExpression)) { |
| expr.drop(); |
| return false; |
| } |
| while (atToken(PyTokenTypes.OR)) { |
| myBuilder.advanceLexer(); |
| if (!parseBitwiseXORExpression(isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.BINARY_EXPRESSION); |
| expr = expr.precede(); |
| } |
| |
| expr.drop(); |
| return true; |
| } |
| |
| private boolean parseBitwiseXORExpression(boolean isTargetExpression) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parseBitwiseANDExpression(isTargetExpression)) { |
| expr.drop(); |
| return false; |
| } |
| while (atToken(PyTokenTypes.XOR)) { |
| myBuilder.advanceLexer(); |
| if (!parseBitwiseANDExpression(isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.BINARY_EXPRESSION); |
| expr = expr.precede(); |
| } |
| |
| expr.drop(); |
| return true; |
| } |
| |
| private boolean parseBitwiseANDExpression(boolean isTargetExpression) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parseShiftExpression(isTargetExpression)) { |
| expr.drop(); |
| return false; |
| } |
| while (atToken(PyTokenTypes.AND)) { |
| myBuilder.advanceLexer(); |
| if (!parseShiftExpression(isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.BINARY_EXPRESSION); |
| expr = expr.precede(); |
| } |
| |
| expr.drop(); |
| return true; |
| } |
| |
| private boolean parseShiftExpression(boolean isTargetExpression) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parseAdditiveExpression(myBuilder, isTargetExpression)) { |
| expr.drop(); |
| return false; |
| } |
| while (PyTokenTypes.SHIFT_OPERATIONS.contains(myBuilder.getTokenType())) { |
| myBuilder.advanceLexer(); |
| if (!parseAdditiveExpression(myBuilder, isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.BINARY_EXPRESSION); |
| expr = expr.precede(); |
| } |
| |
| expr.drop(); |
| return true; |
| } |
| |
| private boolean parseAdditiveExpression(final PsiBuilder myBuilder, boolean isTargetExpression) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parseMultiplicativeExpression(isTargetExpression)) { |
| expr.drop(); |
| return false; |
| } |
| while (PyTokenTypes.ADDITIVE_OPERATIONS.contains(myBuilder.getTokenType())) { |
| myBuilder.advanceLexer(); |
| if (!parseMultiplicativeExpression(isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.BINARY_EXPRESSION); |
| expr = expr.precede(); |
| } |
| |
| expr.drop(); |
| return true; |
| } |
| |
| private boolean parseMultiplicativeExpression(boolean isTargetExpression) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parseUnaryExpression(isTargetExpression)) { |
| expr.drop(); |
| return false; |
| } |
| |
| while (PyTokenTypes.MULTIPLICATIVE_OPERATIONS.contains(myBuilder.getTokenType())) { |
| myBuilder.advanceLexer(); |
| if (!parseUnaryExpression(isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.BINARY_EXPRESSION); |
| expr = expr.precede(); |
| } |
| |
| expr.drop(); |
| return true; |
| } |
| |
| protected boolean parseUnaryExpression(boolean isTargetExpression) { |
| final IElementType tokenType = myBuilder.getTokenType(); |
| if (PyTokenTypes.UNARY_OPERATIONS.contains(tokenType)) { |
| final PsiBuilder.Marker expr = myBuilder.mark(); |
| myBuilder.advanceLexer(); |
| if (!parseUnaryExpression(isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.PREFIX_EXPRESSION); |
| return true; |
| } |
| else { |
| return parsePowerExpression(isTargetExpression); |
| } |
| } |
| |
| private boolean parsePowerExpression(boolean isTargetExpression) { |
| PsiBuilder.Marker expr = myBuilder.mark(); |
| if (!parseMemberExpression(isTargetExpression)) { |
| expr.drop(); |
| return false; |
| } |
| |
| if (myBuilder.getTokenType() == PyTokenTypes.EXP) { |
| myBuilder.advanceLexer(); |
| if (!parseUnaryExpression(isTargetExpression)) { |
| myBuilder.error(message("PARSE.expected.expression")); |
| } |
| expr.done(PyElementTypes.BINARY_EXPRESSION); |
| } |
| else { |
| expr.drop(); |
| } |
| |
| return true; |
| } |
| } |