blob: c56938503546f923f9d14f3cfa2951a178155eea [file] [log] [blame]
/*
* Copyright 2000-2012 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.intellij.lang;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.UserDataHolderUnprotected;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.diff.FlyweightCapableTreeStructure;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
/**
* The IDEA side of a custom language parser. Provides lexical analysis results to the
* plugin and allows the plugin to build the AST tree.
*
* @see PsiParser
* @see ASTNode
*/
public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected {
/**
* Returns a project for which PSI builder was created (see {@link PsiBuilderFactory}).
* @return project.
*/
Project getProject();
/**
* Returns the complete text being parsed.
*
* @return the text being parsed
*/
CharSequence getOriginalText();
/**
* Advances the lexer to the next token, skipping whitespace and comment tokens.
*/
void advanceLexer();
/**
* Returns the type of current token from the lexer.
*
* @return the token type, or null when the token stream is over.
* @see #setTokenTypeRemapper(ITokenTypeRemapper).
*/
@Nullable
IElementType getTokenType();
/**
* Sets optional remapper that can change the type of tokens.
* Output of getTokenType() is affected by it.
*
* @param remapper the remapper object, or null.
*/
void setTokenTypeRemapper(@Nullable ITokenTypeRemapper remapper);
/**
* Slightly easier way to what {@link ITokenTypeRemapper} does (i.e. it just remaps current token to a given type).
* @param type new type for the current token.
*/
void remapCurrentToken(IElementType type);
/**
* Subscribe for notification on default whitespace and comments skipped events.
* @param callback an implementation for the callback
*/
void setWhitespaceSkippedCallback(@Nullable WhitespaceSkippedCallback callback);
/**
* See what token type is in <code>steps</code> ahead
* @param steps 0 is current token (i.e. the same {@link PsiBuilder#getTokenType()} returns)
* @return type element which getTokenType() will return if we call advance <code>steps</code> times in a row
*/
@Nullable
IElementType lookAhead(int steps);
/**
* See what token type is in <code>steps</code> ahead / behind
* @param steps 0 is current token (i.e. the same {@link PsiBuilder#getTokenType()} returns)
* @return type element ahead or behind, including whitespace / comment tokens
*/
@Nullable
IElementType rawLookup(int steps);
/**
* See what token type is in <code>steps</code> ahead / behind current position
* @param steps 0 is current token (i.e. the same {@link PsiBuilder#getTokenType()} returns)
* @return offset type element ahead or behind, including whitespace / comment tokens, -1 if first token,
* getOriginalText().getLength() at end
*/
int rawTokenTypeStart(int steps);
/**
* Returns the index of the current token in the original sequence.
*
* @return token index
*/
int rawTokenIndex();
/**
* Returns the text of the current token from the lexer.
*
* @return the token text, or null when the token stream is over.
*/
@NonNls
@Nullable
String getTokenText();
/**
* Returns the start offset of the current token, or the file length when the token stream is over.
*
* @return the token offset.
*/
int getCurrentOffset();
/**
* A marker defines a range in the document text which becomes a node in the AST
* tree. The ranges defined by markers within the text range of the current marker
* become child nodes of the node defined by the current marker.
*/
interface Marker {
/**
* Creates and returns a new marker starting immediately before the start of
* this marker and extending after its end. Can be called on a completed or
* a currently active marker.
*
* @return the new marker instance.
*/
Marker precede();
/**
* Drops this marker. Can be called after other markers have been added and completed
* after this marker. Does not affect lexer position or markers added after this marker.
*/
void drop();
/**
* Drops this marker and all markers added after it, and reverts the lexer position to the
* position of this marker.
*/
void rollbackTo();
/**
* Completes this marker and labels it with the specified AST node type. Before calling this method,
* all markers added after the beginning of this marker must be either dropped or completed.
*
* @param type the type of the node in the AST tree.
*/
void done(IElementType type);
/**
* Like {@linkplain #done(IElementType)}, but collapses all tokens between start and end markers
* into single leaf node of given type.
*
* @param type the type of the node in the AST tree.
*/
void collapse(IElementType type);
/**
* Like {@linkplain #done(IElementType)}, but the marker is completed (end marker inserted)
* before specified one. All markers added between start of this marker and the marker specified as end one
* must be either dropped or completed.
*
* @param type the type of the node in the AST tree.
* @param before marker to complete this one before.
*/
void doneBefore(IElementType type, Marker before);
/**
* Like {@linkplain #doneBefore(IElementType, Marker)}, but in addition an error element with given text
* is inserted right before this marker's end.
*
* @param type the type of the node in the AST tree.
* @param before marker to complete this one before.
* @param errorMessage for error element.
*/
void doneBefore(IElementType type, Marker before, String errorMessage);
/**
* Completes this marker and labels it as error element with specified message. Before calling this method,
* all markers added after the beginning of this marker must be either dropped or completed.
*
* @param message for error element.
*/
void error(String message);
/**
* Like {@linkplain #error(String)}, but the marker is completed before specified one.
*
* @param message for error element.
* @param before marker to complete this one before.
*/
void errorBefore(String message, Marker before);
/**
* Allows to define custom edge token binders instead of default ones. If any of parameters is null
* then corresponding token binder won't be changed (keeping previously set or default token binder).
* It is an error to set right token binder for not-done marker.
*
* @param left new left edge token binder.
* @param right new right edge token binder.
*/
void setCustomEdgeTokenBinders(@Nullable WhitespacesAndCommentsBinder left, @Nullable WhitespacesAndCommentsBinder right);
}
/**
* Creates a marker at the current parsing position.
*
* @return the new marker instance.
*/
Marker mark();
/**
* Adds an error marker with the specified message text at the current position in the tree.
* <br><b>Note</b>: from series of subsequent errors messages only first will be part of resulting tree.
*
* @param messageText the text of the error message displayed to the user.
*/
void error(String messageText);
/**
* Checks if the lexer has reached the end of file.
*
* @return true if the lexer is at end of file, false otherwise.
*/
boolean eof();
/**
* Returns the result of the parsing. All markers must be completed or dropped before this method is called.
*
* @return the built tree.
*/
ASTNode getTreeBuilt();
/**
* Same as {@link #getTreeBuilt()} but returns a light tree, which is build faster,
* produces less garbage but is incapable of creating a PSI over.
* <br><b>Note</b>: this method shouldn't be called if {@link #getTreeBuilt()} was called before.
*
* @return the light tree built.
*/
FlyweightCapableTreeStructure<LighterASTNode> getLightTree();
/**
* Enables or disables the builder debug mode. In debug mode, the builder will print stack trace
* to marker allocation position if one is not done when calling getTreeBuilt().
*
* @param dbgMode the debug mode value.
*/
void setDebugMode(boolean dbgMode);
void enforceCommentTokens(TokenSet tokens);
/**
* @return latest left done node for context dependent parsing.
*/
@Nullable
LighterASTNode getLatestDoneMarker();
}