| /* |
| * 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; |
| } |
| } |