/*
* The MIT License (MIT)
*
* Copyright (c) 2016 hsz Jakub Chrzanowski <jakub@hsz.mobi>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package mobi.hsz.idea.latex.lang;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.lang.ParserDefinition;
import com.intellij.lang.PsiParser;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.project.Project;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet;
import mobi.hsz.idea.latex.lexer.LatexLexerAdapter;
import mobi.hsz.idea.latex.parser.LatexParser;
import mobi.hsz.idea.latex.psi.LatexFile;
import mobi.hsz.idea.latex.psi.LatexTypes;
import org.jetbrains.annotations.NotNull;
/**
* Defines the implementation of a parser for a custom language.
*
* @author Jakub Chrzanowski <jakub@hsz.mobi>
* @since 0.1
*/
public class LatexParserDefinition implements ParserDefinition {
/** Whitespaces. */
public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE);
/** Regular comment started with # */
public static final TokenSet COMMENTS = TokenSet.create(LatexTypes.COMMENT);
/** Latex instruction started with \ */
public static final TokenSet INSTRUCTIONS = TokenSet.create(LatexTypes.IDENTIFIER, LatexTypes.IDENTIFIER_BEGIN, LatexTypes.IDENTIFIER_END);
/** Latex instruction's argument */
public static final TokenSet ARGUMENTS = TokenSet.create(LatexTypes.ARG);
/** All brackets: braces, brackets, parenthesis */
public static final TokenSet BRACKETS = TokenSet.create(
LatexTypes.LBRACE, LatexTypes.RBRACE,
LatexTypes.LBRACKET, LatexTypes.RBRACKET,
LatexTypes.LPAREN, LatexTypes.RPAREN
);
/** Element type of the node describing a file in the specified language. */
public static final IFileElementType FILE = new IFileElementType(Language.findInstance(LatexLanguage.class));
/**
* Returns the lexer for lexing files in the specified project. This lexer does not need to support incremental relexing - it is always
* called for the entire file.
*
* @param project the project to which the lexer is connected.
* @return the lexer instance.
*/
@NotNull
@Override
public Lexer createLexer(Project project) {
return new LatexLexerAdapter(project);
}
/**
* Returns the parser for parsing files in the specified project.
*
* @param project the project to which the parser is connected.
* @return the parser instance.
*/
@Override
public PsiParser createParser(Project project) {
return new LatexParser();
}
/**
* Returns the element type of the node describing a file in the specified language.
*
* @return the file node element type.
*/
@Override
public IFileElementType getFileNodeType() {
return FILE;
}
/**
* Returns the set of token types which are treated as whitespace by the PSI builder.
* Tokens of those types are automatically skipped by PsiBuilder. Whitespace elements
* on the bounds of nodes built by PsiBuilder are automatically excluded from the text
* range of the nodes.
* <p><strong>It is strongly advised you return TokenSet that only contains {@link com.intellij.psi.TokenType#WHITE_SPACE},
* which is suitable for all the languages unless you really need to use special whitespace token</strong>
*
* @return the set of whitespace token types.
*/
@NotNull
@Override
public TokenSet getWhitespaceTokens() {
return WHITE_SPACES;
}
/**
* Returns the set of token types which are treated as comments by the PSI builder.
* Tokens of those types are automatically skipped by PsiBuilder. Also, To Do patterns
* are searched in the text of tokens of those types.
*
* @return the set of comment token types.
*/
@NotNull
@Override
public TokenSet getCommentTokens() {
return COMMENTS;
}
/**
* Returns the set of token types which are treated as argument by the PSI builder.
*
* @return the set of argument token types.
*/
@NotNull
public TokenSet getArgumentTokens() {
return ARGUMENTS;
}
/**
* Returns the set of token types which are treated as instructions by the PSI builder.
*
* @return the set of instruction token types.
*/
@NotNull
public TokenSet getInstructionTokens() {
return INSTRUCTIONS;
}
/**
* Returns the set of token types which are treated as brackets by the PSI builder: [](){}
*
* @return the set of instruction token types.
*/
@NotNull
public TokenSet getBracketTokens() {
return BRACKETS;
}
/**
* Returns the set of element types which are treated as string literals. "Search in strings"
* option in refactorings is applied to the contents of such tokens.
*
* @return the set of string literal element types.
*/
@NotNull
@Override
public TokenSet getStringLiteralElements() {
return TokenSet.EMPTY;
}
/**
* Creates a PSI element for the specified AST node. The AST tree is a simple, semantic-free
* tree of AST nodes which is built during the PsiBuilder parsing pass. The PSI tree is built
* over the AST tree and includes elements of different types for different language constructs.
*
* @param node the node for which the PSI element should be returned.
* @return the PSI element matching the element type of the AST node.
*/
@NotNull
@Override
public PsiElement createElement(ASTNode node) {
return LatexTypes.Factory.createElement(node);
}
/**
* Creates a PSI element for the specified virtual file.
*
* @param viewProvider virtual file.
* @return the PSI file element.
*/
@Override
public PsiFile createFile(FileViewProvider viewProvider) {
return new LatexFile(viewProvider);
}
/**
* Checks if the specified two token types need to be separated by a space according to the language grammar.
* For example, in Java two keywords are always separated by a space; a keyword and an opening parenthesis may
* be separated or not separated. This is used for automatic whitespace insertion during AST modification operations.
*
* @param left the first token to check.
* @param right the second token to check.
* @return the spacing requirements.
*/
@Override
public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
return SpaceRequirements.MAY;
}
}