Stylus. Parsing of variables implemented
authorAndrey Vokin <andrey.vokin@jetbrains.com>
Mon, 15 Jul 2013 14:28:09 +0000 (18:28 +0400)
committerAndrey Vokin <andrey.vokin@jetbrains.com>
Wed, 17 Jul 2013 08:04:56 +0000 (12:04 +0400)
platform/lang-impl/src/com/intellij/indentation/OperationParserHelper.java [new file with mode: 0644]

diff --git a/platform/lang-impl/src/com/intellij/indentation/OperationParserHelper.java b/platform/lang-impl/src/com/intellij/indentation/OperationParserHelper.java
new file mode 100644 (file)
index 0000000..977cab0
--- /dev/null
@@ -0,0 +1,194 @@
+package com.intellij.indentation;
+
+import com.intellij.lang.PsiBuilder;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * User: Andrey.Vokin
+ * Date: 3/23/12
+ */
+public class OperationParserHelper {
+  private static boolean parsePostfixOperation(@NotNull final BinaryOperationParser parser) {
+    final PsiBuilder.Marker tempMarker = parser.mark();
+    PsiBuilder.Marker lastMarker = tempMarker;
+    boolean result = parsePrefixOperation(parser);
+    boolean tempMarkerDeleted = false;
+    while (parser.getPostfixOperators().contains(parser.getTokenType()) &&
+           !parser.getWhitespaceTokenSet().contains(parser.rawLookup(-1)) && !parser.isNewLine()) {
+      final PsiBuilder.Marker operationMarker = lastMarker.precede();
+      if (!tempMarkerDeleted) {
+        tempMarker.drop();
+        tempMarkerDeleted = true;
+      }
+      lastMarker = operationMarker;
+      parser.advance();
+      parser.done(operationMarker, parser.getPostfixExpressionElementType());
+      result = true;
+    }
+    if (!tempMarkerDeleted) {
+      tempMarker.drop();
+    }
+    return result;
+  }
+
+  private static boolean parsePrefixOperation(@NotNull final BinaryOperationParser parser) {
+    int prefixCount = 0;
+    while (parser.getPrefixOperators().contains(parser.lookAhead(prefixCount))) {
+      prefixCount++;
+    }
+    final PsiBuilder.Marker[] prefixMarkers = new PsiBuilder.Marker[prefixCount];
+    final IElementType[] elementTypes = new IElementType[prefixCount];
+    for (int i = 0; i < prefixCount; i++) {
+      prefixMarkers[i] = parser.mark();
+      elementTypes[i] = parser.getPrefixExpressionElementType();
+      parser.advance();
+    }
+    final boolean result = parser.parseSimpleExpression() || prefixCount > 0;
+    for (int i = prefixCount - 1; i >= 0; i--) {
+      parser.done(prefixMarkers[i], elementTypes[i]);
+    }
+    return result;
+  }
+
+  public static boolean callParsingBinaryOperation(@NotNull final BinaryOperationParser parser, int level) {
+    if (level < 0) {
+      return parsePostfixOperation(parser);
+    }
+    return parseBinaryOperation(parser, level);
+  }
+
+  private static boolean isBinaryOperator(@NotNull final BinaryOperationParser parser, int level) {
+    IElementType tokenType = parser.getTokenType();
+    return parser.getOperatorsByPriority()[level].contains(tokenType);
+  }
+
+  private static void parseBinaryOperator(@NotNull final BinaryOperationParser parser, int level) {
+    parser.advance();
+  }
+
+  /**
+   * Parses arithmetic mult, arithmetic sum, bit operation, relation operation
+   * @param level 0 for mult, 1, for sum, 2 for bit, 3 for relations
+   */
+  private static boolean parseBinaryOperation(@NotNull final BinaryOperationParser parser, int level) {
+    final PsiBuilder.Marker tempMarker = parser.mark();
+    PsiBuilder.Marker lastMarker = tempMarker;
+    boolean result = callParsingBinaryOperation(parser, level - 1);
+    boolean tempMarkerDeleted = false;
+    while (isBinaryOperator(parser, level) && !parser.isNewLine()) {
+      final PsiBuilder.Marker operationMarker = lastMarker.precede();
+      if (!tempMarkerDeleted) {
+        tempMarker.drop();
+        tempMarkerDeleted = true;
+      }
+      lastMarker = operationMarker;
+      parseBinaryOperator(parser, level);
+      callParsingBinaryOperation(parser, level - 1);
+      parser.done(operationMarker, parser.getOperationElementTypes()[level]);
+      result = true;
+    }
+    if (!tempMarkerDeleted) {
+      tempMarker.drop();
+    }
+    return result;
+  }
+
+  public interface BinaryOperationParser {
+    /**
+     * Gets the TokenType from PsiBuilder
+     * @return IElementType of current element
+     */
+    IElementType getTokenType();
+
+    /**
+     * Checks current token starts the line
+     * @return true if new line
+     */
+    boolean isNewLine();
+
+    /**
+     * Advance current position of PsiBuilder
+     */
+    void advance();
+
+    /**
+     * See what token type is in <code>step</code> ahead / benind (including whitespaces)
+     * @param step 0 is current token, -1 is previous, 1 is next and so on
+     * @return IElementType of the required element
+     */
+    IElementType rawLookup(int step);
+
+    /**
+     * See what token type is in <code>step</code> ahead (not including whitespaces)
+     * @param step 0 is current token, 1 is next and so on
+     * @return IElementType of the required element
+     */
+    IElementType lookAhead(int step);
+
+    /**
+     * Create new marker
+     * @return PsiBuilder.Marker of created marker
+     */
+    PsiBuilder.Marker mark();
+
+    /**
+     * Close marker with element type
+     * @param marker to close
+     * @param elementType to close marker as
+     */
+    void done(PsiBuilder.Marker marker, IElementType elementType);
+
+    /**
+     * Parses operand
+     * @return boolean if success
+     */
+    boolean parseSimpleExpression();
+
+    /**
+     * Provides all whitespace tokens
+     * @return TokenSet of whitespaces
+     */
+    TokenSet getWhitespaceTokenSet();
+
+    /**
+     * Provides prefix operators
+     * @return TokenSet of prefix operators
+     */
+    TokenSet getPrefixOperators();
+
+    /**
+     * Provides postfix operators
+     * @return TokenSet of prefix operators
+     */
+    TokenSet getPostfixOperators();
+
+    /**
+     * Provides operation priority and operands
+     * @return array of TokenSets
+     */
+    TokenSet[] getOperatorsByPriority();
+
+    /**
+     * Provides element types to finish postfix element marker
+     * @return IElementType
+     */
+    @Nullable
+    IElementType getPostfixExpressionElementType();
+
+    /**
+     * Provides element types to finish prefix element marker
+     * @return IElementType
+     */
+    @Nullable
+    IElementType getPrefixExpressionElementType();
+
+    /**
+     * Provides element types to finish binary operation element
+     * @return array of Element Types
+     */
+    IElementType[] getOperationElementTypes();
+  }
+}