/*
* 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.intellij.coldFusion.model.lexer;
import com.intellij.coldFusion.model.parsers.CfmlElementTypes;
import com.intellij.lexer.FlexAdapter;
import com.intellij.lexer.Lexer;
import com.intellij.lexer.MergingLexerAdapter;
import com.intellij.openapi.project.Project;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
/**
* Created by Lera Nikolaenko
* Date: 06.10.2008
*/
public class CfmlLexer extends MergingLexerAdapter {
private static final int LEXER_STATE_LIMIT = 0xFFFF;
private Lexer myCfscriptLexer = null;
private int myStartPosition = 0;
private Project myProject;
private final _CfmlLexer.CfmlLexerConfiguration myConfiguration;
private static final TokenSet TOKENS_TO_MERGE =
TokenSet.create(CfmlTokenTypes.COMMENT,
CfmlTokenTypes.WHITE_SPACE,
CfmlTokenTypes.SCRIPT_EXPRESSION, CfmlElementTypes.TEMPLATE_TEXT);
public CfmlLexer(boolean highlightingMode, Project project) {
super(new FlexAdapter(new _CfmlLexer(project)), TOKENS_TO_MERGE);
myProject = project;
myConfiguration = ((_CfmlLexer)((FlexAdapter)getDelegate()).getFlex()).myCurrentConfiguration;
}
@Override
public void start(@NotNull CharSequence buffer, int startOffset, int endOffset, int initialState) {
myCfscriptLexer = null;
super.start(buffer, startOffset, endOffset, initialState);
}
@Override
public int getState() {
if (myCfscriptLexer != null) {
int modifiedState = (myCfscriptLexer.getState() << 16) + LEXER_STATE_LIMIT;
assert modifiedState != 0;
return modifiedState;
}
int state = doGetState();
assert state >= 0 && state < LEXER_STATE_LIMIT;
return state;
}
private int doGetState() {
return super.getState() + myConfiguration.getExtraState();
}
@Override
public void advance() {
if (myCfscriptLexer != null) {
myCfscriptLexer.advance();
if (myCfscriptLexer.getTokenType() == null) {
myCfscriptLexer = null;
}
}
else {
super.advance();
}
}
@Override
public IElementType getTokenType() {
if (myCfscriptLexer != null) {
return myCfscriptLexer.getTokenType();
}
if (super.getTokenType() == CfmlElementTypes.CF_SCRIPT ||
super.getTokenType() == CfmlTokenTypes.SCRIPT_EXPRESSION) {
final int startPosition = super.getTokenStart();
myStartPosition = startPosition;
int endPosition = super.getTokenEnd();
while (super.getTokenType() == CfmlTokenTypes.SCRIPT_EXPRESSION ||
super.getTokenType() == CfmlElementTypes.CF_SCRIPT) {
endPosition = super.getTokenEnd();
super.advance();
}
myCfscriptLexer = new CfscriptLexer(myProject);
myCfscriptLexer.start(super.getBufferSequence().subSequence(startPosition, endPosition),
0, endPosition - startPosition, myCfscriptLexer.getState());
return myCfscriptLexer.getTokenType();
}
return super.getTokenType();
}
@Override
public int getTokenStart() {
if (myCfscriptLexer != null) {
return myCfscriptLexer.getTokenStart() + myStartPosition;
}
return super.getTokenStart();
}
@Override
public int getTokenEnd() {
if (myCfscriptLexer != null) {
return myCfscriptLexer.getTokenEnd() + myStartPosition;
}
return super.getTokenEnd();
}
}