blob: 357cd35d10cbca84c98e2df4ed1c0cad77f8dca2 [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.javascript2.jade.editor.lexer;
import org.netbeans.spi.lexer.LexerInput;
import org.netbeans.spi.lexer.LexerRestartInfo;
%%
%public
%final
%class JadeColoringLexer
%type JadeTokenId
%unicode
%caseless
%char
%{
private LexerInput input;
private boolean canFollowTag = false;
int parenBalance = 1;
int braceBalance = 0;
int bracketBalance = 0;
int indent = 0;
int eolPosition = 0;
boolean dotAfterTag = false;
int blockIndent = -1;
boolean hasCssId = false;
int lastReaded = 0;
boolean continueJS = false;
boolean inString = false;
int whereToGo = 0;
private static enum TAG_TYPE { OTHER, SCRIPT, STYLE};
TAG_TYPE lastTag = TAG_TYPE.OTHER;
public JadeColoringLexer(LexerRestartInfo info) {
this.input = info.input();
if(info.state() != null) {
//reset state
setState((LexerState)info.state());
} else {
//initial state
zzState = zzLexicalState = YYINITIAL;
}
}
public LexerState getState() {
if (zzState == YYINITIAL && zzLexicalState == YYINITIAL) {
return null;
}
return new LexerState(zzState, zzLexicalState, canFollowTag, indent, hasCssId, lastTag, braceBalance, parenBalance, bracketBalance);
}
public void setState(LexerState state) {
this.zzState = state.zzState;
this.zzLexicalState = state.zzLexicalState;
this.canFollowTag = state.canFollowTag;
this.indent = state.indent;
this.hasCssId = state.hasCssId;
this.lastTag = state.lastTag;
this.braceBalance = state.braceBalance;
this.parenBalance = state.parenBalance;
this.bracketBalance = state.bracketBalance;
}
public JadeTokenId nextToken() throws java.io.IOException {
JadeTokenId token = yylex();
return token;
}
public static final class LexerState {
/** the current state of the DFA */
final int zzState;
/** the current lexical state */
final int zzLexicalState;
final boolean canFollowTag;
/** indent of the new line */
final int indent;
final boolean hasCssId;
/** last readed tag to switch embeding of js , css or html*/
final TAG_TYPE lastTag;
/** balance of brances */
final int braceBalance;
final int parenBalance;
final int bracketBalance;
LexerState (int zzState, int zzLexicalState, boolean canFollowTag, int indent, boolean hasCssId, TAG_TYPE lastTag, int braceBalance, int parenBalance, int bracketBalance) {
this.zzState = zzState;
this.zzLexicalState = zzLexicalState;
this.canFollowTag = canFollowTag;
this.indent = indent;
this.hasCssId = hasCssId;
this.lastTag = lastTag;
this.braceBalance = braceBalance;
this.parenBalance = parenBalance;
this.bracketBalance = bracketBalance;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final LexerState other = (LexerState) obj;
if (this.zzState != other.zzState) {
return false;
}
if (this.zzLexicalState != other.zzLexicalState) {
return false;
}
if (this.canFollowTag != other.canFollowTag) {
return false;
}
if (this.hasCssId != other.hasCssId) {
return false;
}
if (this.indent != other.indent) {
return false;
}
if (this.lastTag != other.lastTag) {
return false;
}
if ((this.braceBalance != other.braceBalance) || (this.parenBalance != other.parenBalance) || (this.bracketBalance != other.bracketBalance)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + this.zzState;
hash = 31 * hash + this.zzLexicalState;
hash = 31 * hash + (this.canFollowTag ? 0 : 1);
hash = 31 * hash + (this.hasCssId ? 0 : 1);
hash = 31 * hash + this.indent;
hash = 31 * hash + this.lastTag.hashCode();
hash = 31 * hash + this.braceBalance;
hash = 31 * hash + this.parenBalance;
hash = 31 * hash + this.bracketBalance;
return hash;
}
@Override
public String toString() {
return "LexerState{" + "zzState=" + zzState + ", zzLexicalState=" + zzLexicalState + '}';
}
}
JadeTokenId getTokenIdFromTagType (TAG_TYPE tagType, JadeTokenId defaultId) {
switch (tagType) {
case SCRIPT: return JadeTokenId.JAVASCRIPT;
case STYLE: return JadeTokenId.CSS;
default: return defaultId;
}
}
// End user code
boolean checkEndJS(int tokenLength, char ch) {
if (!continueJS
&& ((ch == ')' && parenBalance == 0)
|| (ch != ')' && parenBalance == 1))
&& braceBalance == 0 && bracketBalance == 0) {
if (lastReaded > 0 && ((tokenLength - lastReaded) > 0)) {
yypushback(tokenLength - lastReaded);
yybegin(HTML_ATTRIBUTE);
return true;
}
}
lastReaded = tokenLength;
continueJS = false;
return false;
}
%}
/* states */
%state AFTER_EOL
%state DOCTYPE
%state AFTER_DOCTYPE
%state DOCTYPE_STRING
%state DOCTYPE_STRING_END
%state AFTER_TAG
%state AFTER_CODE_DELIMITER
%state AFTER_CODE_DELIMITER_WITH_BLOCK_EXPANSION
%state IN_COMMENT
%state IN_COMMENT_AFTER_EOL
%state IN_UNBUFFERED_COMMENT
%state IN_UNBUFFERED_COMMENT_AFTER_EOL
%state TEXT_LINE
%state IN_PLAIN_TEXT_LINE
%state IN_PLAIN_TEXT_BLOCK
%state IN_PLAIN_TEXT_BLOCK_AFTER_EOL
%state AFTER_PLAIN_TEXT_BLOCK_DELIMITER
%state HTML_ATTRIBUTE
%state HTML_ATTRIBUTE_VALUE
%state JAVASCRIPT_VALUE
%state JAVASCRIPT
%state JAVASCRIPT_LINE
%state JAVASCRIPT_EXPRESSION
%state JAVASCRIPT_WITH_BLOCK_EXPANSION
%state JS_SSTRING
%state JS_STRING
%state FILEPATH
%state IN_FILTER_BLOCK
%state IN_FILTER_BLOCK_AFTER_EOL
%state AFTER_INCLUDE
%state AFTER_BLOCK
%state AFTER_COLON_IN_TAG
%state AFTER_EACH
%state JAVASCRIPT_AFTER_EACH
%state AFTER_MIXIN
%state MIXIN_ARGUMENTS
%state AFTER_PLUS_MIXIN
%state MIXIN_CALL_ARGUMENT
%state AFTER_ATTRIBUTES
/* base structural elements */
AnyChar = (.|[\n])
h = [0-9a-f]
nonascii = [\200-\377]
unicode = \\{h}{1,6}(\r\n|[ \t\r\n\f])?
escape = {unicode}|\\[ -~\200-\377]
nmstart = [_a-zA-Z]|{nonascii}|{escape}
nmchar = [_a-zA-Z0-9-]|{nonascii}|{escape}
HtmlString = [<] [^"\r"|"\n"|"\r\n"|">"|"*"]* [>]?
HtmlIdentifierPart = [[:letter:][:digit:]]+[[:letter:][:digit:]\-]*
HtmlIdentifier = {HtmlIdentifierPart}({HtmlIdentifierPart})*
CssIdentifier = -?{nmstart}{nmchar}*
LineTerminator = \r|\n|\r\n
StringCharacter = [^\r\n\"\\] | \\{LineTerminator}
WS = [ \t\f\u00A0\u000B]
WhiteSpace = [ \t\f\u00A0\u000B]+
Input = [^\r\n \t\f\u00A0\u000B]+
IdentifierPart = [:jletterdigit:]
Identifier = [:jletter:]{IdentifierPart}*
MixinName = {CssIdentifier}
Comment = "//"
UnbufferedComment = "//-"
%%
/*
TODO:
- TagInterPolation http://jade-lang.com/reference/interpolation/
- check interpolation in the text block
- mixin default atributes
- default attributes at all
*/
<YYINITIAL> {
{AnyChar} {
yypushback(1);
indent = 0;
yybegin(AFTER_EOL);
}
}
<AFTER_EOL> {
/* doctype */
"doctype" { yybegin(AFTER_DOCTYPE);
return JadeTokenId.DOCTYPE; }
"if" { yybegin(AFTER_CODE_DELIMITER);
return JadeTokenId.KEYWORD_IF;}
"else" { return JadeTokenId.KEYWORD_ELSE;}
"unless" { yybegin(AFTER_CODE_DELIMITER);
return JadeTokenId.KEYWORD_UNLESS;}
"each" { yybegin(AFTER_EACH);
return JadeTokenId.KEYWORD_EACH;}
"in" { yybegin(AFTER_CODE_DELIMITER);
return JadeTokenId.KEYWORD_IN;}
"for" { yybegin(AFTER_EACH);
return JadeTokenId.KEYWORD_FOR;}
"while" { yybegin(AFTER_CODE_DELIMITER);
return JadeTokenId.KEYWORD_WHILE;}
"case" { yybegin(AFTER_CODE_DELIMITER);
return JadeTokenId.KEYWORD_CASE;}
"when" { yybegin(AFTER_CODE_DELIMITER_WITH_BLOCK_EXPANSION);
return JadeTokenId.KEYWORD_WHEN;}
"default" { yybegin(AFTER_TAG); // handling : after the keyword
return JadeTokenId.KEYWORD_DEFAULT;}
"block" { yybegin(AFTER_BLOCK);
return JadeTokenId.KEYWORD_BLOCK;}
"extends" { yybegin(FILEPATH);
return JadeTokenId.KEYWORD_EXTENDS;}
"include" { yybegin(AFTER_INCLUDE);
return JadeTokenId.KEYWORD_INCLUDE;}
"mixin" { yybegin(AFTER_MIXIN);
return JadeTokenId.KEYWORD_MIXIN; }
"+" { yybegin(AFTER_PLUS_MIXIN);
return JadeTokenId.OPERATOR_PLUS; }
"-"|"="|"!=" { yybegin(AFTER_CODE_DELIMITER);
return JadeTokenId.CODE_DELIMITER; }
{WhiteSpace} { indent = tokenLength;
return JadeTokenId.WHITESPACE; }
"script" { yybegin(AFTER_TAG);
dotAfterTag = true;
hasCssId = false;
lastTag = TAG_TYPE.SCRIPT;
return JadeTokenId.TAG ;}
"style" { yybegin(AFTER_TAG);
dotAfterTag = true;
hasCssId = false;
lastTag = TAG_TYPE.STYLE;
return JadeTokenId.TAG ;}
{HtmlIdentifier} { yybegin(AFTER_TAG);
dotAfterTag = true;
hasCssId = false;
lastTag = TAG_TYPE.OTHER;
return JadeTokenId.TAG ;}
{LineTerminator} { indent = 0;
return JadeTokenId.EOL; }
{UnbufferedComment} { yybegin(IN_UNBUFFERED_COMMENT);
return JadeTokenId.UNBUFFERED_COMMENT_DELIMITER; }
{Comment} { yybegin(IN_COMMENT);
return JadeTokenId.COMMENT_DELIMITER; }
[#\.!] { hasCssId = false;
yypushback(1);
yybegin(AFTER_TAG); }
"|" { yybegin(IN_PLAIN_TEXT_LINE);
return JadeTokenId.PLAIN_TEXT_DELIMITER; }
":"{Input} { yybegin (IN_FILTER_BLOCK);
blockIndent = -1;
return JadeTokenId.FILTER; }
"<" { yybegin(IN_PLAIN_TEXT_LINE); }
"&" { yybegin(IN_PLAIN_TEXT_LINE); }
. { return JadeTokenId.UNKNOWN;}
}
/* TODO - this rure shold be rewrite. I don't like it. Mainly because the dot after tag handling*/
<AFTER_TAG> {
"#"{CssIdentifier} { if (!hasCssId) {
hasCssId = true;
return JadeTokenId.CSS_ID;
} else {
// only one css id is allowed in tag
return JadeTokenId.UNKNOWN;
}
}
"\."{CssIdentifier} { return JadeTokenId.CSS_CLASS; }
"(" { yybegin(HTML_ATTRIBUTE);
return JadeTokenId.BRACKET_LEFT_PAREN;
}
":" { yybegin(AFTER_COLON_IN_TAG);
return JadeTokenId.OPERATOR_COLON;
}
{WhiteSpace} { yybegin(TEXT_LINE);
return JadeTokenId.WHITESPACE;
}
{LineTerminator} { yybegin(AFTER_EOL);
indent = 0;
if (tokenLength > 0) {
return JadeTokenId.EOL;
}
}
"="|"!=" { yybegin(AFTER_CODE_DELIMITER);
return JadeTokenId.CODE_DELIMITER; }
"/" { return JadeTokenId.OPERATOR_DIVISION;}
"\." {
yybegin(AFTER_PLAIN_TEXT_BLOCK_DELIMITER);
return JadeTokenId.PLAIN_TEXT_DELIMITER;
}
"#{"|"!{" { yypushback(2);
yybegin(JAVASCRIPT_EXPRESSION);
whereToGo = TEXT_LINE;
}
"&attributes" { yybegin(AFTER_ATTRIBUTES);
return JadeTokenId.ATTRIBUTE; }
. { yybegin(TEXT_LINE); }
}
<AFTER_COLON_IN_TAG> {
{WhiteSpace} { return JadeTokenId.WHITESPACE;
}
{HtmlIdentifier} { yybegin(AFTER_TAG);
dotAfterTag = true;
hasCssId = false;
return JadeTokenId.TAG ;}
{LineTerminator} { yybegin(AFTER_EOL);
indent = 0;
return JadeTokenId.EOL;
}
. {
return JadeTokenId.UNKNOWN; }
}
<TEXT_LINE> {
[#!]"{" { yypushback(2);
yybegin(JAVASCRIPT_EXPRESSION);
whereToGo = TEXT_LINE;
if (tokenLength > 2) {
return JadeTokenId.TEXT;
}
}
{LineTerminator} {
yypushback(1);
yybegin(AFTER_EOL);
indent = 0;
if (tokenLength -1 > 0) {
return JadeTokenId.TEXT;
}
}
{AnyChar} { }
}
<HTML_ATTRIBUTE> {
{HtmlIdentifier} { return JadeTokenId.ATTRIBUTE; }
"=" { yybegin(HTML_ATTRIBUTE_VALUE);
return JadeTokenId.OPERATOR_ASSIGNMENT; }
"!=" { yybegin(HTML_ATTRIBUTE_VALUE);
return JadeTokenId.OPERATOR_NOT_EQUALS; }
"," { return JadeTokenId.OPERATOR_COMMA; }
{LineTerminator} { return JadeTokenId.EOL; }
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
")" { yybegin(AFTER_TAG);
return JadeTokenId.BRACKET_RIGHT_PAREN;}
. { return JadeTokenId.UNKNOWN;}
}
<HTML_ATTRIBUTE_VALUE> {
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
{LineTerminator} { return JadeTokenId.EOL; }
{AnyChar} {
parenBalance = 1;
lastReaded = bracketBalance = braceBalance = 0;
yypushback(1);
yybegin(JAVASCRIPT_VALUE);}
}
<AFTER_ATTRIBUTES> {
"(" { parenBalance = 1;
lastReaded = bracketBalance = braceBalance = 0;
yybegin(JAVASCRIPT_VALUE);
return JadeTokenId.BRACKET_LEFT_PAREN;
}
{LineTerminator} { yybegin(AFTER_EOL);
return JadeTokenId.EOL; }
. { yybegin(AFTER_TAG);
return JadeTokenId.UNKNOWN;}
}
<AFTER_EACH> {
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
{LineTerminator} { yybegin(AFTER_EOL);
return JadeTokenId.EOL; }
{AnyChar} { yypushback(1);
yybegin(JAVASCRIPT_AFTER_EACH); }
}
<JAVASCRIPT_AFTER_EACH> {
{LineTerminator} { yybegin(AFTER_EOL);
return JadeTokenId.EOL; }
{WS}*"in"({LineTerminator}|{WS}+) { int delta = tokenLength - lastReaded;
if (delta > 0) {
yypushback(delta);
yybegin(AFTER_EOL);
if (tokenLength > delta) {
return JadeTokenId.JAVASCRIPT;
}
}
yypushback(tokenLength);
yybegin(AFTER_EOL);
}
{AnyChar} { lastReaded = tokenLength; }
}
<JAVASCRIPT_VALUE> {
\' { yybegin(JS_SSTRING); }
\" { yybegin(JS_STRING); }
[\+\-\.&\*/%|=!]"="? { continueJS = true; lastReaded = tokenLength; }
"[" { braceBalance++; lastReaded = tokenLength; }
"]" { braceBalance--; lastReaded = tokenLength; }
"{" { bracketBalance++; lastReaded = tokenLength; }
"}" { bracketBalance--; lastReaded = tokenLength; }
"(" { parenBalance++; lastReaded = tokenLength;}
")" { parenBalance--;
if (checkEndJS(tokenLength, (char)zzInput)) {
return JadeTokenId.JAVASCRIPT;
}
}
{WS}+ { }
"," {
if (checkEndJS(tokenLength, (char)zzInput)) {
return JadeTokenId.JAVASCRIPT;
}
}
{HtmlIdentifier} {
if (zzInput == ')') parenBalance--;
if (checkEndJS(tokenLength, (char)zzInput)) {
return JadeTokenId.JAVASCRIPT;
}
if (zzInput == ')') parenBalance++; // ned to return back
}
{AnyChar} { lastReaded = tokenLength; /*continueJS = false;*/}
}
<JS_STRING> {
\" {
continueJS = false;
lastReaded = tokenLength;
yybegin(JAVASCRIPT_VALUE);
}
"\\\"" { }
{LineTerminator} {
yypushback(1);
yybegin(AFTER_EOL);
if (tokenLength -1 > 0) {
return JadeTokenId.UNKNOWN;
}
}
{AnyChar} { }
}
<JS_SSTRING> {
\' {
continueJS = false;
lastReaded = tokenLength;
yybegin(JAVASCRIPT_VALUE);
}
"\\'" { }
{LineTerminator} {
yypushback(1);
yybegin(AFTER_EOL);
if (tokenLength -1 > 0) {
return JadeTokenId.UNKNOWN;
}
}
{AnyChar} { }
}
<AFTER_INCLUDE> {
":"{Input} { return JadeTokenId.FILTER; }
{AnyChar} { yypushback(1); yybegin(FILEPATH); }
}
<AFTER_BLOCK> {
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
{Input} { yybegin(TEXT_LINE);
return JadeTokenId.BLOCK_NAME;}
{LineTerminator} { yybegin(AFTER_EOL);
return JadeTokenId.EOL; }
}
<JAVASCRIPT> {
[\"'{}(),\n\r] {
switch (zzInput) {
case '(': parenBalance++; break;
case '{': braceBalance++; break;
case '}': braceBalance--; break;
case ')':
parenBalance--;
break;
case ',':
case '\r':
case '\n':
if (parenBalance == 1 && braceBalance == 0) {
parenBalance = 0;
}
break;
}
if (parenBalance == 0 && braceBalance == 0) {
yypushback(1);
yybegin(HTML_ATTRIBUTE);
parenBalance = 1;
if (tokenLength > 1) {
return JadeTokenId.JAVASCRIPT;
}
}
}
{AnyChar} {}
}
<JAVASCRIPT_EXPRESSION> {
[#!]"{" { braceBalance = 1; return JadeTokenId.EXPRESSION_DELIMITER_OPEN; }
"{" { braceBalance++; }
"}" { braceBalance--;
if (braceBalance == 0) {
yypushback(1);
if (tokenLength > 1) {
return JadeTokenId.JAVASCRIPT;
}
} else if (braceBalance == -1) {
yybegin(whereToGo);
return JadeTokenId.EXPRESSION_DELIMITER_CLOSE;
}
}
{LineTerminator} { yypushback(1);
yybegin(AFTER_EOL);
if (tokenLength - 1 > 0) {
return JadeTokenId.JAVASCRIPT;
}
}
. { }
}
<JAVASCRIPT_WITH_BLOCK_EXPANSION> {
":" { yypushback(1);
yybegin(AFTER_TAG);
}
[^:\r\n]+ { return JadeTokenId.JAVASCRIPT; }
{LineTerminator} { yybegin(AFTER_EOL);
indent = 0;
return JadeTokenId.EOL; }
}
<JAVASCRIPT_LINE> {
.+ { return JadeTokenId.JAVASCRIPT; }
{LineTerminator} { yybegin(AFTER_EOL);
indent = 0;
return JadeTokenId.EOL; }
}
<AFTER_CODE_DELIMITER_WITH_BLOCK_EXPANSION> {
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
{AnyChar} { yypushback(1);
yybegin(JAVASCRIPT_WITH_BLOCK_EXPANSION);
}
}
<AFTER_CODE_DELIMITER> {
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
{AnyChar} { yypushback(1);
yybegin(JAVASCRIPT_LINE);
}
}
<IN_PLAIN_TEXT_LINE> {
[#!]"{" { yypushback(2);
yybegin(JAVASCRIPT_EXPRESSION);
whereToGo = IN_PLAIN_TEXT_LINE;
if (tokenLength > 2) {
return getTokenIdFromTagType(lastTag, JadeTokenId.PLAIN_TEXT);
}
}
{LineTerminator} { yypushback(1);
yybegin(AFTER_EOL);
if (tokenLength - 1 > 0 ) {
return getTokenIdFromTagType(lastTag, JadeTokenId.PLAIN_TEXT);
}
}
. { }
}
<AFTER_PLAIN_TEXT_BLOCK_DELIMITER> {
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
.* { // the text will not be renedered
return JadeTokenId.UNKNOWN;
}
{LineTerminator} { blockIndent = -1;
eolPosition = 0;
yybegin(IN_PLAIN_TEXT_BLOCK_AFTER_EOL);
return JadeTokenId.EOL;
}
}
<IN_PLAIN_TEXT_BLOCK> {
[#!]"{" { yypushback(2);
yybegin(JAVASCRIPT_EXPRESSION);
whereToGo = IN_PLAIN_TEXT_BLOCK;
if (tokenLength > 2) {
return JadeTokenId.TEXT;
}
}
{LineTerminator} { yybegin(IN_PLAIN_TEXT_BLOCK_AFTER_EOL);
eolPosition = tokenLength;
}
. { }
}
<IN_PLAIN_TEXT_BLOCK_AFTER_EOL> {
{WhiteSpace} {
int currentIndent = tokenLength - eolPosition;
if (currentIndent <= indent) {
// the block has to have one more space than the tag
yybegin(AFTER_EOL);
indent = currentIndent;
if (tokenLength > currentIndent) {
yypushback(currentIndent);
return getTokenIdFromTagType(lastTag, JadeTokenId.PLAIN_TEXT);
} else {
return JadeTokenId.WHITESPACE;
}
}
if (blockIndent < 0) {
blockIndent = currentIndent;
}
if (blockIndent > currentIndent) {
yypushback(currentIndent);
yybegin(AFTER_EOL);
if (tokenLength > currentIndent) {
return getTokenIdFromTagType(lastTag, JadeTokenId.PLAIN_TEXT);
}
}
yybegin(IN_PLAIN_TEXT_BLOCK);
}
{LineTerminator} {}
. { yypushback(1);
yybegin(AFTER_EOL);
indent = 0;
if (tokenLength > 1) {
return getTokenIdFromTagType(lastTag, JadeTokenId.PLAIN_TEXT);
}
}
}
<IN_FILTER_BLOCK> {
[#!]"{" { yypushback(2);
yybegin(JAVASCRIPT_EXPRESSION);
whereToGo = IN_FILTER_BLOCK;
if (tokenLength > 2) {
return JadeTokenId.FILTER_TEXT;
}
}
{LineTerminator} { yybegin(IN_FILTER_BLOCK_AFTER_EOL);
eolPosition = tokenLength;
}
. {}
}
<IN_FILTER_BLOCK_AFTER_EOL> {
{WhiteSpace} { int indentInBlock = tokenLength - eolPosition;
if (blockIndent < 0) {
blockIndent = indentInBlock;
}
if (blockIndent > indentInBlock) {
yypushback(indentInBlock);
yybegin(AFTER_EOL);
if (tokenLength > indentInBlock) {
return JadeTokenId.FILTER_TEXT;
}
}
yybegin(IN_FILTER_BLOCK);
}
{LineTerminator} {}
. { yypushback(1);
yybegin(AFTER_EOL);
if (tokenLength - 1 > 0) {
return JadeTokenId.FILTER_TEXT;
}
}
}
<AFTER_MIXIN> {
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
{LineTerminator} { yybegin(AFTER_EOL);
return JadeTokenId.EOL; }
{MixinName} { return JadeTokenId.MIXIN_NAME; }
"(" { yybegin(MIXIN_ARGUMENTS);
return JadeTokenId.BRACKET_LEFT_PAREN;}
. { return JadeTokenId.UNKNOWN; }
}
<MIXIN_ARGUMENTS> {
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
{Identifier} { return JadeTokenId.IDENTIFIER; }
"," { return JadeTokenId.OPERATOR_COMMA; }
"..." { return JadeTokenId.OPERATOR_REST_ARGUMENTS; }
")" { return JadeTokenId.BRACKET_RIGHT_PAREN;}
{LineTerminator} { yybegin(AFTER_EOL);
return JadeTokenId.EOL; }
{AnyChar} { // expect declaration of parameters
return JadeTokenId.UNKNOWN; }
}
<AFTER_PLUS_MIXIN> {
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
{MixinName} { return JadeTokenId.MIXIN_NAME; }
"(" { yybegin(MIXIN_CALL_ARGUMENT);
parenBalance = 1; braceBalance = 0;
return JadeTokenId.BRACKET_LEFT_PAREN;}
"," { yybegin(MIXIN_CALL_ARGUMENT);
parenBalance = 1; braceBalance = 0;
return JadeTokenId.OPERATOR_COMMA; }
")" { yybegin(AFTER_TAG);
return JadeTokenId.BRACKET_LEFT_PAREN;}
{LineTerminator} { yybegin(AFTER_EOL);
return JadeTokenId.EOL; }
. { return JadeTokenId.UNKNOWN; }
}
<MIXIN_CALL_ARGUMENT> {
[(){},] {
switch (zzInput) {
case '(': parenBalance++; break;
case '{': braceBalance++; break;
case '}': braceBalance--; break;
case ')':
parenBalance--;
break;
case ',':
if (parenBalance == 1 && braceBalance == 0) {
parenBalance = 0;
}
break;
}
if (parenBalance == 0 && braceBalance == 0) {
yypushback(1);
yybegin(AFTER_PLUS_MIXIN);
parenBalance = 1;
if (tokenLength > 1) {
return JadeTokenId.JAVASCRIPT;
}
}
}
{AnyChar} {}
}
/* This is help rule. Read all until end of line and remember the number of read chars. */
<IN_COMMENT> {
.* { }
{LineTerminator} { yybegin(IN_COMMENT_AFTER_EOL);
eolPosition = tokenLength;
}
}
/* Scan the begining of line in commnet.
If there is a whitespace, we need to find out, if the indentation says that the commment
continues or finished already. */
<IN_COMMENT_AFTER_EOL> {
{WhiteSpace} { int indentInComment = tokenLength - eolPosition;
if (indent >= indentInComment) {
yypushback(indentInComment + 1); // return back also the EOL
yybegin(AFTER_EOL);
if (tokenLength > (indentInComment + 1)) {
return JadeTokenId.COMMENT;
}
} else {
yybegin(IN_COMMENT);
}
}
{LineTerminator} {}
. { yypushback(1);
yybegin(AFTER_EOL);
if (tokenLength > 1) {
return JadeTokenId.COMMENT;
}
}
}
/* Copy of the normal comment. Just return the appropriate tokens */
<IN_UNBUFFERED_COMMENT> {
.* { }
{LineTerminator} { yybegin(IN_UNBUFFERED_COMMENT_AFTER_EOL);
eolPosition = tokenLength;
}
}
<IN_UNBUFFERED_COMMENT_AFTER_EOL> {
{WhiteSpace} { int indentInComment = tokenLength - eolPosition;
if (indent >= indentInComment) {
yypushback(indentInComment);
yybegin(AFTER_EOL);
if (tokenLength > indentInComment) {
return JadeTokenId.UNBUFFERED_COMMENT;
}
} else {
yybegin(IN_UNBUFFERED_COMMENT);
}
}
{LineTerminator} {}
. { yypushback(1);
yybegin(AFTER_EOL);
if (tokenLength > 1) {
return JadeTokenId.UNBUFFERED_COMMENT;
}
}
}
<AFTER_DOCTYPE> {
{LineTerminator} {
yybegin(AFTER_EOL);
indent = 0;
if (tokenLength > 0) {
return JadeTokenId.EOL;
}
}
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
{Input} { yybegin(DOCTYPE);
return JadeTokenId.DOCTYPE_TEMPLATE; }
}
<DOCTYPE> {
{LineTerminator} {
yybegin(AFTER_EOL);
indent = 0;
if (tokenLength > 0) {
return JadeTokenId.EOL;
}
}
['\"] { yybegin(DOCTYPE_STRING);
return JadeTokenId.DOCTYPE_STRING_START;}
{WhiteSpace} { return JadeTokenId.WHITESPACE; }
[^'\"\r\n \t\f\u00A0\u000B]+ { return JadeTokenId.DOCTYPE_ATTRIBUTE; }
}
<DOCTYPE_STRING> {
{LineTerminator} { yypushback(1);
yybegin(DOCTYPE);
if (tokenLength > 1) {
return JadeTokenId.UNKNOWN;
}
}
[\"'] { yypushback(1);
yybegin(DOCTYPE_STRING_END);
if (tokenLength > 1) {
return JadeTokenId.DOCTYPE_STRING_END;
}
}
[^\"'\r\n]+ { }
}
<DOCTYPE_STRING_END> {
[\"'] { yybegin(DOCTYPE);
return JadeTokenId.DOCTYPE_STRING_END;}
}
<FILEPATH> {
{LineTerminator} { yypushback(1);
yybegin(AFTER_EOL);
if (tokenLength - 1 > 0) {
return JadeTokenId.FILE_PATH;
}
}
[^\r\n] { }
}
<TEXT_LINE><<EOF>> {
{ if (input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return JadeTokenId.TEXT;
} else {
return null;
}}
}
<IN_UNBUFFERED_COMMENT_AFTER_EOL><<EOF>> { if (input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return JadeTokenId.UNBUFFERED_COMMENT;
} else {
return null;
}}
<IN_UNBUFFERED_COMMENT><<EOF>> { if (input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return JadeTokenId.UNBUFFERED_COMMENT;
} else {
return null;
}}
<IN_COMMENT_AFTER_EOL><<EOF>> { if (input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return JadeTokenId.COMMENT;
} else {
return null;
}}
<IN_COMMENT><<EOF>> { if (input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return JadeTokenId.COMMENT;
} else {
return null;
}}
<IN_FILTER_BLOCK_AFTER_EOL><<EOF>> { if (input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return JadeTokenId.FILTER_TEXT;
} else {
return null;
}}
<IN_FILTER_BLOCK><<EOF>> { if (input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return JadeTokenId.FILTER_TEXT;
} else {
return null;
}}
<IN_PLAIN_TEXT_LINE><<EOF>> {
if (input.readLength() > 0 ) {
input.backup(1);
return getTokenIdFromTagType(lastTag, JadeTokenId.PLAIN_TEXT);
} else {
return null;
}
}
<IN_PLAIN_TEXT_BLOCK_AFTER_EOL><<EOF>> { if (input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return getTokenIdFromTagType(lastTag, JadeTokenId.PLAIN_TEXT);
} else {
return null;
}}
<IN_PLAIN_TEXT_BLOCK><<EOF>> { if (input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return getTokenIdFromTagType(lastTag, JadeTokenId.PLAIN_TEXT);
} else {
return null;
}}
<<EOF>> {
if (input.readLength() > 0) {
// backup eof
input.backup(1);
//and return the text as error token
return JadeTokenId.UNKNOWN;
} else {
return null;
}
}