All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition groovy-psi library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2014 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 org.jetbrains.plugins.groovy.lang.parser.parsing.util;

import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilder.Marker;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;

/**
 * Utility classdef, that contains various useful methods for
 * parser needs.
 *
 * @author ilyas
 */
public abstract class ParserUtils {

  /**
   * Auxiliary method for strict token appearance
   *
   * @param builder  current builder
   * @param elem     given element
   * @param errorMsg Message, that displays if element was not found; if errorMsg == null nothing displays
   * @return true if element parsed
   */
  public static boolean getToken(PsiBuilder builder, IElementType elem, String errorMsg) {
    if (elem.equals(builder.getTokenType())) {
      builder.advanceLexer();
      return true;
    } else {
      if (errorMsg != null)
        builder.error(errorMsg);
      return false;
    }
  }

  /**
   * Auxiliary method for construction like
   * 
   * token?
   * 
   * parsing
   *
   * @param builder current builder
   * @param elem    given element
   * @return true if element parsed
   */
  public static boolean getToken(PsiBuilder builder, IElementType elem) {
    if (elem.equals(builder.getTokenType())) {
      builder.advanceLexer();
      return true;
    }
    return false;
  }

  public static boolean getToken(PsiBuilder builder, IElementType elem1, IElementType elem2) {
    Marker marker = builder.mark();
    if (getToken(builder, elem1) && getToken(builder, elem2)) {
      marker.drop();
      return true;
    }
    else {
      marker.rollbackTo();
      return false;
    }
  }

  /**
   * Same as simple getToken() method but with TokenSet
   *
   * @param builder
   * @param tokenSet
   * @return
   */
  public static boolean getToken(PsiBuilder builder, TokenSet tokenSet) {
    return getToken(builder, tokenSet, null);
  }

  /**
   * Same as simple getToken() method but with TokenSet
   *
   * @param builder
   * @param tokenSet
   * @return
   */
  public static boolean getToken(PsiBuilder builder, TokenSet tokenSet, String msg) {
    if (tokenSet.contains(builder.getTokenType())) {
      builder.advanceLexer();
      return true;
    }
    else {
      if (msg != null) {
        builder.error(msg);
      }
      return false;
    }
  }

  /**
   * Checks, that following element sequence is like given
   *
   * @param builder Given PsiBuilder
   * @param elems   Array of need elements in order
   * @return true if following sequence is like a given
   *
   * Note don't change type of last parameter to "IElementType... elems"! Passed array should be stored in static variable to avoid creation
   * of new array.
   */
  public static boolean lookAhead(PsiBuilder builder, IElementType[] elems) {
    if (elems[0] != builder.getTokenType()) return false;

    if (elems.length == 1) return true;

    Marker rb = builder.mark();
    builder.advanceLexer();
    int i = 1;
    while (!builder.eof() && i < elems.length && elems[i] == builder.getTokenType()) {
      builder.advanceLexer();
      i++;
    }
    rb.rollbackTo();
    return i == elems.length;
  }

  public static boolean lookAhead(PsiBuilder builder, IElementType element1) {
    return element1 == builder.getTokenType();
  }

  public static boolean lookAhead(PsiBuilder builder, IElementType element1, IElementType element2) {
    if (element1 != builder.getTokenType()) return false;

    Marker rb = builder.mark();
    builder.advanceLexer();
    boolean res = (!builder.eof() && element2 == builder.getTokenType());
    rb.rollbackTo();
    return res;
  }

  public static boolean lookAhead(PsiBuilder builder, IElementType element1, IElementType element2, IElementType element3) {
    if (element1 != builder.getTokenType()) return false;

    Marker rb = builder.mark();

    boolean res = false;

    builder.advanceLexer();
    if (!builder.eof() && element2 == builder.getTokenType()) {
      builder.advanceLexer();
      res = (!builder.eof() && element3 == builder.getTokenType());
    }

    rb.rollbackTo();
    return res;
  }

  public static boolean lookAhead(PsiBuilder builder, IElementType element1, IElementType element2, IElementType element3, IElementType element4) {
    if (element1 != builder.getTokenType()) return false;

    Marker rb = builder.mark();

    boolean res = false;

    builder.advanceLexer();
    if (!builder.eof() && element2 == builder.getTokenType()) {
      builder.advanceLexer();
      if (!builder.eof() && element3 == builder.getTokenType()) {
        builder.advanceLexer();
        res = (!builder.eof() && element4 == builder.getTokenType());
      }
    }

    rb.rollbackTo();
    return res;
  }

  /**
   * Wraps current token to node with specified element type
   *
   * @param builder Given builder
   * @param elem    Node element
   * @return elem type
   */
  public static IElementType eatElement(PsiBuilder builder, IElementType elem) {
    Marker marker = builder.mark();
    builder.advanceLexer();
    marker.done(elem);
    return elem;
  }

  /**
   * Wraps current token with error message
   *
   * @param builder
   * @param msg     Error message
   */
  public static void wrapError(PsiBuilder builder, String msg) {
    Marker marker = builder.mark();
    builder.advanceLexer();
    marker.error(msg);
  }

  public static boolean skipCountingBraces(PsiBuilder builder, TokenSet until) {
    int braceLevel = 0;
    while (true) {
      if (builder.eof()) {
        return false;
      }
      final IElementType type = builder.getTokenType();
      if (braceLevel == 0 && until.contains(type)) {
        return true;
      }

      if (GroovyTokenTypes.mLCURLY == type) {
        braceLevel++;
      }
      else if (GroovyTokenTypes.mRCURLY == type) {
        braceLevel--;
      }
      builder.advanceLexer();
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy