blob: c4f44fe366e55358ed89bad437a519082f64a2a2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.netbeans.modules.php.latte.lexer;
import java.util.Objects;
import org.netbeans.spi.lexer.LexerInput;
import org.netbeans.spi.lexer.LexerRestartInfo;
import org.netbeans.modules.web.common.api.ByteStack;
@org.netbeans.api.annotations.common.SuppressWarnings({"SF_SWITCH_FALLTHROUGH", "URF_UNREAD_FIELD", "DLS_DEAD_LOCAL_STORE", "DM_DEFAULT_ENCODING"})
%%
%public
%class LatteMarkupColoringLexer
%type LatteMarkupTokenId
%function findNextToken
%unicode
%caseless
%char
%eofval{
if(input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return LatteMarkupTokenId.T_ERROR;
} else {
return null;
}
%eofval}
%{
private ByteStack stack = new ByteStack();
private LexerInput input;
public LatteMarkupColoringLexer(LexerRestartInfo info) {
this.input = info.input();
if(info.state() != null) {
//reset state
setState((LexerState) info.state());
} else {
zzState = zzLexicalState = YYINITIAL;
stack.clear();
}
}
private enum Syntax {
LATTE,
DOUBLE,
ASP,
PYTHON,
OFF;
}
public static final class LexerState {
final ByteStack stack;
/** the current state of the DFA */
final int zzState;
/** the current lexical state */
final int zzLexicalState;
LexerState(ByteStack stack, int zzState, int zzLexicalState) {
this.stack = stack;
this.zzState = zzState;
this.zzLexicalState = zzLexicalState;
}
@Override
public int hashCode() {
int hash = 5;
hash = 29 * hash + Objects.hashCode(this.stack);
hash = 29 * hash + this.zzState;
hash = 29 * hash + this.zzLexicalState;
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final LexerState other = (LexerState) obj;
if (!Objects.equals(this.stack, other.stack)) {
return false;
}
if (this.zzState != other.zzState) {
return false;
}
if (this.zzLexicalState != other.zzLexicalState) {
return false;
}
return true;
}
}
public LexerState getState() {
return new LexerState(stack.copyOf(), zzState, zzLexicalState);
}
public void setState(LexerState state) {
this.stack.copyFrom(state.stack);
this.zzState = state.zzState;
this.zzLexicalState = state.zzLexicalState;
}
protected int getZZLexicalState() {
return zzLexicalState;
}
protected void popState() {
yybegin(stack.pop());
}
protected void pushState(final int state) {
stack.push(getZZLexicalState());
yybegin(state);
}
// End user code
%}
WHITESPACE=[ \t\r\n]+
D_STRING_START="\""([^"\"""{"])*
D_STRING_END=([^"\"""$"] | "$}")*"\""
D_STRING="\""([^"\""])*"\""
S_STRING="'"([^'\\]|("\\"[^]))*"'"
KEYWORD="true"|"false"|"null"|"and"|"or"|"xor"|"clone"|"new"|"instanceof"|"return"|"continue"|"break"
CAST="(" ("expand"|"string"|"array"|"int"|"integer"|"float"|"bool"|"boolean"|"object") ")"
VARIABLE="$"[a-zA-Z0-9_]+
NUMBER=["+""-"]?[0-9]+(\.[0-9]+)?(e[0-9]+)?
STRICT_CHAR="::"|"=>"|"as"|"->"
GLOBAL_CHAR=[^\"']
SYMBOL=[a-zA-Z0-9_]+(\-[a-zA-Z0-9_]+)*
MACRO="if" | "elseif" | "else" | "ifset" | "elseifset" | "ifCurrent" | "for" | "foreach" | "while" | "first" | "last" | "sep" |
"capture" | "cache" | "syntax" | "_" | "block" | "form" | "label" | "snippet" | "continueIf" | "breakIf" | "var" | "default" |
"include" | "use" | "l" | "r" | "contentType" | "status" | "define" | "includeblock" | "layout" | "extends" | "link" | "plink" |
"control" | "input" | "dump" | "debugbreak" | "widget" | "translate"
END_MACRO="if" | "ifset" | "ifCurrent" | "for" | "foreach" | "while" | "first" | "last" | "sep" | "capture" | "cache" |
"syntax" | "_" | "block" | "form" | "label" | "snippet" | "define" | "translate"
%state ST_OTHER
%state ST_END_MACRO
%state ST_IN_D_STRING
%state ST_HIGHLIGHTING_ERROR
%%
<YYINITIAL, ST_OTHER, ST_END_MACRO>{WHITESPACE}+ {
return LatteMarkupTokenId.T_WHITESPACE;
}
<YYINITIAL> {
"/" {
yypushback(yylength());
pushState(ST_END_MACRO);
}
{MACRO} {
pushState(ST_OTHER);
return LatteMarkupTokenId.T_MACRO_START;
}
. {
yypushback(yylength());
pushState(ST_OTHER);
}
}
<ST_END_MACRO> {
"/" {END_MACRO}? {
pushState(ST_OTHER);
return LatteMarkupTokenId.T_MACRO_END;
}
. {
yypushback(yylength());
pushState(ST_OTHER);
}
}
<ST_OTHER> {
{NUMBER} {
return LatteMarkupTokenId.T_NUMBER;
}
{KEYWORD} {
return LatteMarkupTokenId.T_KEYWORD;
}
{CAST} {
return LatteMarkupTokenId.T_CAST;
}
{VARIABLE} {
return LatteMarkupTokenId.T_VARIABLE;
}
{D_STRING} {
yypushback(yylength());
pushState(ST_IN_D_STRING);
}
{S_STRING} {
return LatteMarkupTokenId.T_STRING;
}
{STRICT_CHAR} {
return LatteMarkupTokenId.T_CHAR;
}
{SYMBOL} {
return LatteMarkupTokenId.T_SYMBOL;
}
{GLOBAL_CHAR} {
return LatteMarkupTokenId.T_CHAR;
}
}
<ST_IN_D_STRING> {
([^"$""{"] | "$}" | "{"[^"$"])+ "{$" {
yypushback(1);
return LatteMarkupTokenId.T_STRING;
}
{VARIABLE} {
return LatteMarkupTokenId.T_VARIABLE;
}
{D_STRING_START} {
return LatteMarkupTokenId.T_STRING;
}
{D_STRING_END} {
popState();
return LatteMarkupTokenId.T_STRING;
}
}
/* ============================================
Stay in this state until we find a whitespace.
After we find a whitespace we go the the prev state and try again from the next token.
============================================ */
<ST_HIGHLIGHTING_ERROR> {
{WHITESPACE} {
popState();
}
. {
return LatteMarkupTokenId.T_ERROR;
}
}
/* ============================================
This rule must be the last in the section!!
it should contain all the states.
============================================ */
<YYINITIAL, ST_OTHER, ST_END_MACRO, ST_IN_D_STRING> {
. {
yypushback(1);
pushState(ST_HIGHLIGHTING_ERROR);
}
}