| /* |
| * 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.editor.lexer; |
| |
| 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", "EI_EXPOSE_REP"}) |
| %% |
| |
| %public |
| %class PHP5ColoringLexer |
| %type PHPTokenId |
| %function nextToken |
| %unicode |
| %caseless |
| %char |
| |
| %state ST_PHP_IN_SCRIPTING |
| %state ST_PHP_DOUBLE_QUOTES |
| %state ST_PHP_BACKQUOTE |
| %state ST_PHP_QUOTES_AFTER_VARIABLE |
| %state ST_PHP_LOOKING_FOR_STATIC_PROPERTY |
| %state ST_PHP_HEREDOC |
| %state ST_PHP_START_HEREDOC |
| %state ST_PHP_END_HEREDOC |
| %state ST_PHP_NOWDOC |
| %state ST_PHP_START_NOWDOC |
| %state ST_PHP_END_NOWDOC |
| %state ST_PHP_LOOKING_FOR_PROPERTY |
| %state ST_PHP_LOOKING_FOR_FUNCTION_NAME |
| %state ST_PHP_LOOKING_FOR_CONSTANT_NAME |
| %state ST_PHP_VAR_OFFSET |
| %state ST_PHP_COMMENT |
| %state ST_PHP_DOC_COMMENT |
| %state ST_PHP_LINE_COMMENT |
| %state ST_PHP_HIGHLIGHTING_ERROR |
| %state ST_HALTED_COMPILER |
| |
| %eofval{ |
| if(input.readLength() > 0) { |
| // backup eof |
| input.backup(1); |
| //and return the text as error token |
| return PHPTokenId.UNKNOWN_TOKEN; |
| } else { |
| return null; |
| } |
| %eofval} |
| |
| %{ |
| |
| private final ByteStack stack = new ByteStack(); |
| private String heredoc = null; |
| private int hereocLength = 0; |
| private int parenBalanceInConst = 0; // for context sensitive lexer |
| private int bracketBalanceInConst = 0; // for context sensitive lexer |
| private boolean aspTagsAllowed; |
| private boolean shortTagsAllowed; |
| private boolean isInConst; |
| private LexerInput input; |
| |
| public PHP5ColoringLexer(LexerRestartInfo info, boolean shortTagsAllowed, boolean aspTagsAllowed, boolean inPHP) { |
| this.input = info.input(); |
| this.aspTagsAllowed = aspTagsAllowed; |
| this.shortTagsAllowed = shortTagsAllowed; |
| |
| if (info.state() != null) { |
| //reset state |
| setState((LexerState) info.state()); |
| } else { |
| //initial state |
| stack.push(YYINITIAL); |
| if (inPHP) { |
| stack.push(ST_PHP_IN_SCRIPTING); |
| zzState = ST_PHP_IN_SCRIPTING; |
| zzLexicalState = ST_PHP_IN_SCRIPTING; |
| } else { |
| zzState = YYINITIAL; |
| zzLexicalState = YYINITIAL; |
| } |
| } |
| |
| } |
| |
| public static final class LexerState { |
| final ByteStack stack; |
| /* the current state of the DFA */ |
| final int zzState; |
| /* the current lexical state */ |
| final int zzLexicalState; |
| /* remember the heredoc */ |
| final String heredoc; |
| /* and the lenght of */ |
| final int hereocLength; |
| |
| LexerState(ByteStack stack, int zzState, int zzLexicalState, String heredoc, int hereocLength) { |
| this.stack = stack; |
| this.zzState = zzState; |
| this.zzLexicalState = zzLexicalState; |
| this.heredoc = heredoc; |
| this.hereocLength = hereocLength; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| |
| if (obj == null || obj.getClass() != this.getClass()) { |
| return false; |
| } |
| |
| LexerState state = (LexerState) obj; |
| return (this.stack.equals(state.stack) |
| && (this.zzState == state.zzState) |
| && (this.zzLexicalState == state.zzLexicalState) |
| && (this.hereocLength == state.hereocLength) |
| && ((this.heredoc == null && state.heredoc == null) || (this.heredoc != null && state.heredoc != null && this.heredoc.equals(state.heredoc)))); |
| } |
| |
| @Override |
| public int hashCode() { |
| int hash = 11; |
| hash = 31 * hash + this.zzState; |
| hash = 31 * hash + this.zzLexicalState; |
| if (stack != null) { |
| hash = 31 * hash + this.stack.hashCode(); |
| } |
| hash = 31 * hash + this.hereocLength; |
| if (heredoc != null) { |
| hash = 31 * hash + this.heredoc.hashCode(); |
| } |
| return hash; |
| } |
| } |
| |
| public LexerState getState() { |
| return new LexerState(stack.copyOf(), zzState, zzLexicalState, heredoc, hereocLength); |
| } |
| |
| public void setState(LexerState state) { |
| this.stack.copyFrom(state.stack); |
| this.zzState = state.zzState; |
| this.zzLexicalState = state.zzLexicalState; |
| this.heredoc = state.heredoc; |
| this.hereocLength = state.hereocLength; |
| } |
| |
| protected boolean isHeredocState(int state) { |
| return state == ST_PHP_HEREDOC || state == ST_PHP_START_HEREDOC || state == ST_PHP_END_HEREDOC || state == ST_PHP_NOWDOC; |
| } |
| |
| public int[] getParamenters() { |
| return new int[]{zzMarkedPos, zzPushbackPos, zzCurrentPos, zzStartRead, zzEndRead, yyline, zzLexicalState}; |
| } |
| |
| protected int getZZLexicalState() { |
| return zzLexicalState; |
| } |
| |
| protected int getZZMarkedPos() { |
| return zzMarkedPos; |
| } |
| |
| protected int getZZEndRead() { |
| return zzEndRead; |
| } |
| |
| public char[] getZZBuffer() { |
| return zzBuffer; |
| } |
| |
| protected int getZZStartRead() { |
| return this.zzStartRead; |
| } |
| |
| protected int getZZPushBackPosition() { |
| return this.zzPushbackPos; |
| } |
| |
| protected void pushBack(int i) { |
| yypushback(i); |
| } |
| |
| protected void popState() { |
| yybegin(stack.pop()); |
| } |
| |
| protected void pushState(final int state) { |
| stack.push(getZZLexicalState()); |
| yybegin(state); |
| } |
| |
| private boolean isLabelChar(char c) { |
| return c == '_' |
| || (c >= 'a' && c <= 'z') |
| || (c >= 'A' && c <= 'Z') |
| || (c >= 0x7f && c <= 0xff); |
| } |
| |
| private boolean isEndNowdoc() { |
| String yytext = yytext().trim(); |
| int lastIndexOfNewline = yytext.lastIndexOf('\n'); |
| if (lastIndexOfNewline == -1) { |
| lastIndexOfNewline = yytext.lastIndexOf('\r'); |
| } |
| if (lastIndexOfNewline != -1) { |
| yytext = yytext.substring(lastIndexOfNewline); |
| } |
| return isEndHereOrNowdoc(yytext); |
| } |
| |
| private boolean isEndHeredoc() { |
| return isEndHereOrNowdoc(yytext()); |
| } |
| |
| private boolean isEndHereOrNowdoc(String text) { |
| // check whether ID exists |
| String trimedText = text.trim(); |
| boolean isEnd = false; |
| if (trimedText.startsWith(heredoc)) { |
| if (trimedText.length() == heredoc.length()) { |
| isEnd = true; |
| } else if (trimedText.length() > heredoc.length() |
| && !isLabelChar(trimedText.charAt(heredoc.length()))) { |
| // e.g. |
| // $test = <<< END |
| // ENDING |
| // END |
| isEnd = true; |
| } |
| } |
| return isEnd; |
| } |
| |
| // End user code |
| |
| %} |
| |
| LNUM=[0-9]+(_[0-9]+)* |
| DNUM=({LNUM}?[\.]{LNUM})|({LNUM}[\.]{LNUM}?) |
| EXPONENT_DNUM=(({LNUM}|{DNUM})[eE][+-]?{LNUM}) |
| HNUM="0x"[0-9a-fA-F]+(_[0-9a-fA-F]+)* |
| BNUM="0b"[01]+(_[01]+)* |
| //LABEL=[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* |
| LABEL=([[:letter:]_]|[\u007f-\u00ff])([[:letter:][:digit:]_]|[\u007f-\u00ff])* |
| WHITESPACE=[ \n\r\t]+ |
| TABS_AND_SPACES=[ \t]* |
| TOKENS=[:,.\[\]()$?//] |
| CLOSE_EXPRESSION=[;] |
| ANY_CHAR=[^] |
| NEWLINE=("\r"|"\n"|"\r\n") |
| DOUBLE_QUOTES_LITERAL_DOLLAR=("$"+([^a-zA-Z_\x7f-\xff$\"\\{]|("\\"{ANY_CHAR}))) |
| BACKQUOTE_LITERAL_DOLLAR=("$"+([^a-zA-Z_\x7f-\xff$`\\{]|("\\"{ANY_CHAR}))) |
| |
| HEREDOC_LITERAL_DOLLAR=("$"+([^a-zA-Z_\x7f-\xff$\n\r\\{]|("\\"[^\n\r]))) |
| HEREDOC_CURLY_OR_ESCAPE_OR_DOLLAR=(("{"+[^$\n\r\\{])|("{"*"\\"[^\n\r])|{HEREDOC_LITERAL_DOLLAR}) |
| HEREDOC_NON_LABEL=([^a-zA-Z_\x7f-\xff$\n\r\\{]|{HEREDOC_CURLY_OR_ESCAPE_OR_DOLLAR}) |
| HEREDOC_LABEL_NO_NEWLINE=({LABEL}([^a-zA-Z0-9_\x7f-\xff;$\n\r\\{]|(";"[^$\n\r\\{])|(";"?{HEREDOC_CURLY_OR_ESCAPE_OR_DOLLAR}))) |
| |
| DOUBLE_QUOTES_CHARS=("{"*([^$\"\\{]|("\\"{ANY_CHAR}))|{DOUBLE_QUOTES_LITERAL_DOLLAR}) |
| BACKQUOTE_CHARS=("{"*([^$`\\{]|("\\"{ANY_CHAR}))|{BACKQUOTE_LITERAL_DOLLAR}) |
| |
| HEREDOC_CHARS=([^$\\{]|("\\"{ANY_CHAR}))({HEREDOC_LABEL_NO_NEWLINE} | {HEREDOC_NON_LABEL} | {LABEL})* |
| NOWDOC_CHARS=({NEWLINE}*(([^a-zA-Z_\x7f-\xff\n\r][^\n\r]*)|({LABEL}[^a-zA-Z0-9_\x7f-\xff;\n\r][^\n\r]*)|({LABEL}[;][^\n\r]+))) |
| PHP_OPERATOR="=>"|"++"|"--"|"==="|"!=="|"=="|"!="|"<>"|"<="|">="|"+="|"-="|"*="|"/="|".="|"%="|"<<="|">>="|"&="|"|="|"^="|"||"|"&&"|"<<"|">>"|"**"|"**="|"..."|"="|"+"|"-"|"/"|"*"|"%"|"<"|">"|"!"|"@"|"^"|"&"|"|"|"~"|"<=>"|"??"|"??=" |
| PHP_TEXTUAL_OPERATOR="OR"|"AND"|"XOR" |
| // XXX how to define case sensitive patterns? |
| PHP_TYPE_INT=[i][n][t] |
| PHP_TYPE_FLOAT=[f][l][o][a][t] |
| PHP_TYPE_STRING=[s][t][r][i][n][g] |
| PHP_TYPE_BOOL=[b][o][o][l] |
| // PHP7.1: These may be used as type names in PHP7.0 or older |
| PHP_TYPE_VOID=[v][o][i][d] |
| PHP_ITERABLE=[i][t][e][r][a][b][l][e] |
| // PHP7.2 |
| PHP_TYPE_OBJECT=[o][b][j][e][c][t] |
| |
| |
| |
| |
| |
| %% |
| |
| <YYINITIAL>(([^<]|"<"[^?%(script)<])+)|"<script"|"<" { |
| return PHPTokenId.T_INLINE_HTML; |
| } |
| |
| <YYINITIAL>"<script"{WHITESPACE}+"language"{WHITESPACE}*"="{WHITESPACE}*("php"|"\"php\""|"\'php\'"){WHITESPACE}*">" { |
| pushState(ST_PHP_IN_SCRIPTING); |
| return PHPTokenId.T_INLINE_HTML; |
| } |
| |
| <YYINITIAL>"<?" { |
| if (shortTagsAllowed ) { |
| //yybegin(ST_PHP_IN_SCRIPTING); |
| pushState(ST_PHP_IN_SCRIPTING); |
| return PHPTokenId.PHP_OPENTAG; |
| //return createSymbol(ASTSymbol.T_OPEN_TAG); |
| } else { |
| //return createSymbol(ASTSymbol.T_INLINE_HTML); |
| return PHPTokenId.T_INLINE_HTML; |
| } |
| } |
| |
| <YYINITIAL>"<%="|"<?=" { |
| String text = yytext(); |
| if ((text.charAt(1)=='%' && aspTagsAllowed) |
| || (text.charAt(1)=='?')) { |
| //yybegin(ST_PHP_IN_SCRIPTING); |
| pushState(ST_PHP_IN_SCRIPTING); |
| return PHPTokenId.T_OPEN_TAG_WITH_ECHO; |
| //return createSymbol(ASTSymbol.T_OPEN_TAG); |
| } else { |
| //return createSymbol(ASTSymbol.T_INLINE_HTML); |
| return PHPTokenId.T_INLINE_HTML; |
| } |
| } |
| |
| <YYINITIAL>"<%" { |
| if (aspTagsAllowed) { |
| //yybegin(ST_PHP_IN_SCRIPTING); |
| pushState(ST_PHP_IN_SCRIPTING); |
| return PHPTokenId.PHP_OPENTAG; |
| //return createSymbol(ASTSymbol.T_OPEN_TAG); |
| } else { |
| //return createSymbol(ASTSymbol.T_INLINE_HTML); |
| return PHPTokenId.T_INLINE_HTML; |
| } |
| } |
| |
| <YYINITIAL>"<?php" { |
| pushState(ST_PHP_IN_SCRIPTING); |
| //yybegin(ST_PHP_IN_SCRIPTING); |
| return PHPTokenId.PHP_OPENTAG; |
| //return createSymbol(ASTSymbol.T_OPEN_TAG); |
| } |
| |
| |
| /*********************************************************************************************** |
| **************************************** P H P *********************************************** |
| ***********************************************************************************************/ |
| |
| <ST_PHP_IN_SCRIPTING> "exit" { |
| return PHPTokenId.PHP_EXIT; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"die" { |
| return PHPTokenId.PHP_DIE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"fn" { |
| // PHP 7.4 Arrow Functions 2.0 |
| // https://wiki.php.net/rfc/arrow_functions_v2 |
| return PHPTokenId.PHP_FN; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"function" { |
| pushState(ST_PHP_LOOKING_FOR_FUNCTION_NAME); |
| return PHPTokenId.PHP_FUNCTION; |
| } |
| |
| <ST_PHP_LOOKING_FOR_FUNCTION_NAME>{WHITESPACE}+ { |
| return PHPTokenId.WHITESPACE; |
| } |
| |
| <ST_PHP_LOOKING_FOR_FUNCTION_NAME>"(" { |
| popState(); |
| return PHPTokenId.PHP_TOKEN; |
| } |
| |
| <ST_PHP_LOOKING_FOR_FUNCTION_NAME>{LABEL} { |
| popState(); |
| return PHPTokenId.PHP_STRING; |
| } |
| |
| <ST_PHP_LOOKING_FOR_FUNCTION_NAME>{ANY_CHAR} { |
| yypushback(1); |
| popState(); |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"const" { |
| isInConst = true; |
| parenBalanceInConst = 0; |
| bracketBalanceInConst = 0; |
| pushState(ST_PHP_LOOKING_FOR_CONSTANT_NAME); |
| return PHPTokenId.PHP_CONST; |
| } |
| |
| <ST_PHP_LOOKING_FOR_CONSTANT_NAME>{WHITESPACE}+ { |
| return PHPTokenId.WHITESPACE; |
| } |
| |
| <ST_PHP_LOOKING_FOR_CONSTANT_NAME>{LABEL}{WHITESPACE}*"=" { |
| // const keyword is also used within group uses. so check "=", otherwise it matches the following: |
| // use A\{const CONSTANTA, function myFunction,...} |
| popState(); |
| String match = yytext(); |
| String[] segments = match.split("[ \n\r\t]+"); |
| int back = 1; |
| if(segments.length > 1) { |
| int wsLength = yylength() - 1 - segments[0].length(); // - "=" - {LABEL} |
| back += wsLength; |
| } |
| yypushback(back); |
| return PHPTokenId.PHP_STRING; |
| } |
| |
| <ST_PHP_LOOKING_FOR_CONSTANT_NAME>{ANY_CHAR} { |
| if(parenBalanceInConst == 0 && bracketBalanceInConst == 0) { |
| isInConst = false; |
| } |
| yypushback(1); |
| popState(); |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"," { |
| if (isInConst) { |
| pushState(ST_PHP_LOOKING_FOR_CONSTANT_NAME); |
| } |
| return PHPTokenId.PHP_TOKEN; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"return" { |
| return PHPTokenId.PHP_RETURN; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"yield"{WHITESPACE}+"from" { |
| return PHPTokenId.PHP_YIELD_FROM; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"yield" { |
| return PHPTokenId.PHP_YIELD; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"try" { |
| return PHPTokenId.PHP_TRY; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"catch" { |
| return PHPTokenId.PHP_CATCH; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"finally" { |
| return PHPTokenId.PHP_FINALLY; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"throw" { |
| return PHPTokenId.PHP_THROW; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"if" { |
| return PHPTokenId.PHP_IF; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"elseif" { |
| return PHPTokenId.PHP_ELSEIF; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"endif" { |
| return PHPTokenId.PHP_ENDIF; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"else" { |
| return PHPTokenId.PHP_ELSE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"while" { |
| return PHPTokenId.PHP_WHILE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"endwhile" { |
| return PHPTokenId.PHP_ENDWHILE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"do" { |
| return PHPTokenId.PHP_DO; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"for" { |
| return PHPTokenId.PHP_FOR; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"endfor" { |
| return PHPTokenId.PHP_ENDFOR; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"foreach" { |
| return PHPTokenId.PHP_FOREACH; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"endforeach" { |
| return PHPTokenId.PHP_ENDFOREACH; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"declare" { |
| return PHPTokenId.PHP_DECLARE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"enddeclare" { |
| return PHPTokenId.PHP_ENDDECLARE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"instanceof" { |
| return PHPTokenId.PHP_INSTANCEOF; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"insteadof" { |
| return PHPTokenId.PHP_INSTEADOF; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"as" { |
| return PHPTokenId.PHP_AS; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"switch" { |
| return PHPTokenId.PHP_SWITCH; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"endswitch" { |
| return PHPTokenId.PHP_ENDSWITCH; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"case" { |
| return PHPTokenId.PHP_CASE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"default" { |
| return PHPTokenId.PHP_DEFAULT; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"break" { |
| return PHPTokenId.PHP_BREAK; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"continue" { |
| return PHPTokenId.PHP_CONTINUE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"echo" { |
| return PHPTokenId.PHP_ECHO; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"goto" { |
| return PHPTokenId.PHP_GOTO; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"print" { |
| return PHPTokenId.PHP_PRINT; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"class" { |
| return PHPTokenId.PHP_CLASS; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"trait" { |
| return PHPTokenId.PHP_TRAIT; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"interface" { |
| return PHPTokenId.PHP_INTERFACE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"extends" { |
| return PHPTokenId.PHP_EXTENDS; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"implements" { |
| return PHPTokenId.PHP_IMPLEMENTS; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"self" { |
| return PHPTokenId.PHP_SELF; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{PHP_TYPE_INT} { |
| return PHPTokenId.PHP_TYPE_INT; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{PHP_TYPE_FLOAT} { |
| return PHPTokenId.PHP_TYPE_FLOAT; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{PHP_TYPE_STRING} { |
| return PHPTokenId.PHP_TYPE_STRING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{PHP_TYPE_BOOL} { |
| return PHPTokenId.PHP_TYPE_BOOL; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{PHP_TYPE_VOID} { |
| return PHPTokenId.PHP_TYPE_VOID; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{PHP_TYPE_OBJECT} { |
| return PHPTokenId.PHP_TYPE_OBJECT; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"->" { |
| pushState(ST_PHP_LOOKING_FOR_PROPERTY); |
| return PHPTokenId.PHP_OBJECT_OPERATOR; |
| } |
| |
| <ST_PHP_QUOTES_AFTER_VARIABLE> { |
| "->" { |
| popState(); |
| pushState(ST_PHP_LOOKING_FOR_PROPERTY); |
| return PHPTokenId.PHP_OBJECT_OPERATOR; |
| } |
| {ANY_CHAR} { |
| yypushback(1); |
| popState(); |
| } |
| } |
| |
| <ST_PHP_IN_SCRIPTING,ST_PHP_LOOKING_FOR_PROPERTY>{WHITESPACE}+ { |
| return PHPTokenId.WHITESPACE; |
| } |
| |
| <ST_PHP_LOOKING_FOR_PROPERTY>"->" { |
| return PHPTokenId.PHP_OBJECT_OPERATOR; |
| } |
| |
| <ST_PHP_LOOKING_FOR_PROPERTY>{LABEL} { |
| popState(); |
| return PHPTokenId.PHP_STRING; |
| } |
| |
| <ST_PHP_LOOKING_FOR_PROPERTY>{ANY_CHAR} { |
| yypushback(1); |
| popState(); |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"::" { |
| pushState(ST_PHP_LOOKING_FOR_STATIC_PROPERTY); |
| return PHPTokenId.PHP_PAAMAYIM_NEKUDOTAYIM; |
| } |
| |
| <ST_PHP_LOOKING_FOR_STATIC_PROPERTY>{WHITESPACE}+ { |
| return PHPTokenId.WHITESPACE; |
| } |
| |
| <ST_PHP_LOOKING_FOR_STATIC_PROPERTY>"::" { |
| return PHPTokenId.PHP_PAAMAYIM_NEKUDOTAYIM; |
| } |
| |
| <ST_PHP_LOOKING_FOR_STATIC_PROPERTY> { |
| {LABEL} { |
| popState(); |
| return PHPTokenId.PHP_STRING; |
| } |
| {ANY_CHAR} { |
| yypushback(1); |
| popState(); |
| } |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"\\" { |
| return PHPTokenId.PHP_NS_SEPARATOR; |
| } |
| <ST_PHP_IN_SCRIPTING>"new" { |
| return PHPTokenId.PHP_NEW; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"clone" { |
| return PHPTokenId.PHP_CLONE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"var" { |
| return PHPTokenId.PHP_VAR; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"("{TABS_AND_SPACES}({PHP_TYPE_INT}|{PHP_TYPE_FLOAT}|{PHP_TYPE_STRING}|{PHP_TYPE_BOOL}){TABS_AND_SPACES}")" { |
| return PHPTokenId.PHP_CASTING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"("{TABS_AND_SPACES}("int"|"integer"){TABS_AND_SPACES}")" { |
| return PHPTokenId.PHP_CASTING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"("{TABS_AND_SPACES}("real"|"double"|"float"){TABS_AND_SPACES}")" { |
| return PHPTokenId.PHP_CASTING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"("{TABS_AND_SPACES}"string"{TABS_AND_SPACES}")" { |
| return PHPTokenId.PHP_CASTING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"("{TABS_AND_SPACES}"binary"{TABS_AND_SPACES}")" { |
| return PHPTokenId.PHP_CASTING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" { |
| return PHPTokenId.PHP_CASTING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"("{TABS_AND_SPACES}"object"{TABS_AND_SPACES}")" { |
| return PHPTokenId.PHP_CASTING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"("{TABS_AND_SPACES}("bool"|"boolean"){TABS_AND_SPACES}")" { |
| return PHPTokenId.PHP_CASTING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"("{TABS_AND_SPACES}("unset"){TABS_AND_SPACES}")" { |
| return PHPTokenId.PHP_CASTING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"eval" { |
| return PHPTokenId.PHP_EVAL; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"include" { |
| return PHPTokenId.PHP_INCLUDE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"include_once" { |
| return PHPTokenId.PHP_INCLUDE_ONCE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"require" { |
| return PHPTokenId.PHP_REQUIRE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"require_once" { |
| return PHPTokenId.PHP_REQUIRE_ONCE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"namespace" { |
| return PHPTokenId.PHP_NAMESPACE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"use" { |
| return PHPTokenId.PHP_USE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"global" { |
| return PHPTokenId.PHP_GLOBAL; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"isset" { |
| return PHPTokenId.PHP_ISSET; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"empty" { |
| return PHPTokenId.PHP_EMPTY; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"__halt_compiler" { |
| pushState(ST_HALTED_COMPILER); |
| return PHPTokenId.PHP_HALT_COMPILER; |
| } |
| |
| <ST_HALTED_COMPILER> {ANY_CHAR}+ { |
| popState(); |
| return PHPTokenId.T_INLINE_HTML; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"static" { |
| return PHPTokenId.PHP_STATIC; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"abstract" { |
| return PHPTokenId.PHP_ABSTRACT; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"final" { |
| return PHPTokenId.PHP_FINAL; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"private" { |
| return PHPTokenId.PHP_PRIVATE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"protected" { |
| return PHPTokenId.PHP_PROTECTED; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"public" { |
| return PHPTokenId.PHP_PUBLIC; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"unset" { |
| return PHPTokenId.PHP_UNSET; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"list" { |
| return PHPTokenId.PHP_LIST; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"array" { |
| return PHPTokenId.PHP_ARRAY; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"callable" { |
| return PHPTokenId.PHP_CALLABLE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{PHP_ITERABLE} { |
| return PHPTokenId.PHP_ITERABLE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"parent" { |
| return PHPTokenId.PHP_PARENT; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"true" { |
| return PHPTokenId.PHP_TRUE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"null" { |
| return PHPTokenId.PHP_NULL; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"false" { |
| return PHPTokenId.PHP_FALSE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{PHP_OPERATOR} { |
| return PHPTokenId.PHP_OPERATOR; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{PHP_TEXTUAL_OPERATOR} { |
| return PHPTokenId.PHP_TEXTUAL_OPERATOR; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{TOKENS} { |
| if(isInConst) { |
| // for checking arrays |
| // e.g. const CONST = [1, 2], const GOTO = 1; |
| String text = yytext(); |
| switch (text) { |
| case "[": |
| bracketBalanceInConst++; |
| break; |
| case "]": |
| bracketBalanceInConst--; |
| break; |
| case "(": |
| parenBalanceInConst++; |
| break; |
| case ")": |
| parenBalanceInConst--; |
| break; |
| default: |
| break; |
| } |
| } |
| return PHPTokenId.PHP_TOKEN; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{CLOSE_EXPRESSION} { |
| if(isInConst) { |
| isInConst = false; |
| parenBalanceInConst = 0; |
| bracketBalanceInConst = 0; |
| } |
| return PHPTokenId.PHP_SEMICOLON; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"{" { |
| return PHPTokenId.PHP_CURLY_OPEN; |
| } |
| |
| <ST_PHP_DOUBLE_QUOTES,ST_PHP_BACKQUOTE,ST_PHP_HEREDOC>"${" { |
| pushState(ST_PHP_IN_SCRIPTING); |
| return PHPTokenId.PHP_TOKEN; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"}" { |
| int lastState = stack.peek(); |
| if (lastState != ST_PHP_IN_SCRIPTING && lastState != YYINITIAL) { |
| // probably in some sub state -> "{$" or "${" |
| popState(); |
| } |
| return PHPTokenId.PHP_CURLY_CLOSE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{BNUM} { |
| return PHPTokenId.PHP_NUMBER; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{LNUM} { |
| return PHPTokenId.PHP_NUMBER; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{HNUM} { |
| return PHPTokenId.PHP_NUMBER; |
| } |
| |
| <ST_PHP_VAR_OFFSET>0|([1-9][0-9]*) { |
| return PHPTokenId.PHP_NUMBER; |
| } |
| |
| <ST_PHP_VAR_OFFSET>{LNUM}|{HNUM} { |
| return PHPTokenId.PHP_NUMBER; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>{DNUM}|{EXPONENT_DNUM} { |
| return PHPTokenId.PHP_NUMBER; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"__CLASS__" { |
| return PHPTokenId.PHP__CLASS__; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"__TRAIT__" { |
| return PHPTokenId.PHP__TRAIT__; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"__FUNCTION__" { |
| return PHPTokenId.PHP__FUNCTION__; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"__METHOD__" { |
| return PHPTokenId.PHP__METHOD__; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"__LINE__" { |
| return PHPTokenId.PHP__LINE__; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"__FILE__" { |
| return PHPTokenId.PHP__FILE__; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"__DIR__" { |
| return PHPTokenId.PHP__DIR__; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"__NAMESPACE__" { |
| return PHPTokenId.PHP__NAMESPACE__; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"$"{LABEL} { |
| return PHPTokenId.PHP_VARIABLE; |
| } |
| |
| <ST_PHP_DOUBLE_QUOTES,ST_PHP_BACKQUOTE,ST_PHP_HEREDOC,ST_PHP_VAR_OFFSET>"$"{LABEL} { |
| pushState(ST_PHP_QUOTES_AFTER_VARIABLE); |
| return PHPTokenId.PHP_VARIABLE; |
| } |
| |
| <ST_PHP_DOUBLE_QUOTES,ST_PHP_HEREDOC,ST_PHP_BACKQUOTE>"$"{LABEL}"[" { |
| yypushback(1); |
| pushState(ST_PHP_VAR_OFFSET); |
| return PHPTokenId.PHP_VARIABLE; |
| } |
| |
| <ST_PHP_VAR_OFFSET>"]" { |
| popState(); |
| return PHPTokenId.PHP_TOKEN; |
| } |
| |
| <ST_PHP_VAR_OFFSET>"[" { |
| return PHPTokenId.PHP_TOKEN; |
| } |
| |
| <ST_PHP_VAR_OFFSET>{TOKENS}|[;{}\"`] {//the difference from the original rules comes from the fact that we took ';' out out of tokens |
| return PHPTokenId.UNKNOWN_TOKEN; |
| } |
| |
| <ST_PHP_VAR_OFFSET>[ \n\r\t\\'#] { |
| yypushback(1); |
| popState(); |
| if (yylength() > 0) |
| return PHPTokenId.PHP_ENCAPSED_AND_WHITESPACE; |
| } |
| |
| <ST_PHP_IN_SCRIPTING,ST_PHP_VAR_OFFSET>{LABEL} { |
| return PHPTokenId.PHP_STRING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>([#]|"//") { |
| pushState(ST_PHP_LINE_COMMENT); |
| return PHPTokenId.PHP_LINE_COMMENT; |
| } |
| |
| <ST_PHP_LINE_COMMENT>"?"|"%" { |
| return PHPTokenId.PHP_LINE_COMMENT; |
| } |
| |
| <ST_PHP_LINE_COMMENT>[^\n\r?%]*{ANY_CHAR} { |
| String yytext = yytext(); |
| switch (yytext.charAt(yytext.length() - 1)) { |
| case '?': |
| case '%': |
| yypushback(1); |
| break; |
| default: |
| popState(); |
| } |
| return PHPTokenId.PHP_LINE_COMMENT; |
| } |
| |
| <ST_PHP_LINE_COMMENT>{NEWLINE} { |
| popState(); |
| return PHPTokenId.PHP_LINE_COMMENT; |
| } |
| |
| |
| <ST_PHP_IN_SCRIPTING>"/**"{WHITESPACE} { |
| pushState(ST_PHP_DOC_COMMENT); |
| yypushback(yylength()-3); |
| return PHPTokenId.PHPDOC_COMMENT_START; |
| } |
| |
| <ST_PHP_DOC_COMMENT>"*/" { |
| popState(); |
| return PHPTokenId.PHPDOC_COMMENT_END; |
| } |
| |
| <ST_PHP_DOC_COMMENT>~"*/" { |
| yypushback(2); // go back to mark end of comment in the next token |
| return PHPTokenId.PHPDOC_COMMENT; |
| } |
| |
| <ST_PHP_DOC_COMMENT> <<EOF>> { |
| if (input.readLength() > 0) { |
| input.backup(1); // backup eof |
| return PHPTokenId.PHPDOC_COMMENT; |
| } |
| else { |
| return null; |
| } |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"/*" { |
| pushState(ST_PHP_COMMENT); |
| return PHPTokenId.PHP_COMMENT_START; |
| } |
| |
| <ST_PHP_COMMENT>"*/" { |
| popState(); |
| return PHPTokenId.PHP_COMMENT_END; |
| } |
| |
| <ST_PHP_COMMENT>~"*/" { |
| yypushback(2); |
| return PHPTokenId.PHP_COMMENT; |
| } |
| |
| <ST_PHP_COMMENT> <<EOF>> { |
| if (input.readLength() > 0) { |
| input.backup(1); // backup eof |
| return PHPTokenId.PHP_COMMENT; |
| } |
| else { |
| return null; |
| } |
| } |
| |
| <ST_PHP_IN_SCRIPTING,ST_PHP_LINE_COMMENT>"?>"{WHITESPACE}? { |
| //popState(); |
| yybegin(YYINITIAL); |
| if (yylength() > 2) { |
| yypushback(yylength()-2); |
| } |
| stack.clear(); |
| return PHPTokenId.PHP_CLOSETAG; |
| } |
| |
| <ST_PHP_IN_SCRIPTING,ST_PHP_LINE_COMMENT>"</script>"{WHITESPACE}? { |
| popState(); |
| return PHPTokenId.T_INLINE_HTML; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>"%>"{WHITESPACE}? { |
| if (aspTagsAllowed) { |
| yybegin(YYINITIAL); |
| stack.clear(); |
| return PHPTokenId.PHP_CLOSETAG; |
| } |
| return PHPTokenId.UNKNOWN_TOKEN; |
| } |
| |
| <ST_PHP_LINE_COMMENT>"%>"{WHITESPACE}? { |
| if (aspTagsAllowed) { |
| yybegin(YYINITIAL); |
| stack.clear(); |
| return PHPTokenId.PHP_CLOSETAG; |
| } |
| String text = yytext(); |
| if(text.indexOf('\r') != -1 || text.indexOf('\n') != -1 ){ |
| popState(); |
| } |
| return PHPTokenId.PHP_LINE_COMMENT; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>(b?[\"]{DOUBLE_QUOTES_CHARS}*("{"*|"$"*)[\"]) { |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>(b?[']([^'\\]|("\\"{ANY_CHAR}))*[']) { |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>b?[\"] { |
| pushState(ST_PHP_DOUBLE_QUOTES); |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}[']{LABEL}[']{NEWLINE} { |
| int bprefix = (yytext().charAt(0) != '<') ? 1 : 0; |
| int startString=3+bprefix; |
| /* 3 is <<<, 2 is quotes, 1 is newline */ |
| hereocLength = yylength()-bprefix-3-2-1-(yytext().charAt(yylength()-2)=='\r'?1:0); |
| while ((yytext().charAt(startString) == ' ') || (yytext().charAt(startString) == '\t')) { |
| startString++; |
| hereocLength--; |
| } |
| // first quate |
| startString++; |
| heredoc = yytext().substring(startString, hereocLength+startString); |
| yybegin(ST_PHP_START_NOWDOC); |
| return PHPTokenId.PHP_NOWDOC_TAG_START; |
| } |
| |
| <ST_PHP_START_NOWDOC>{ANY_CHAR} { |
| yypushback(1); |
| yybegin(ST_PHP_NOWDOC); |
| } |
| |
| <ST_PHP_START_NOWDOC>{TABS_AND_SPACES}{LABEL}";"?[^\n\r]*[\r\n]? { |
| /* <ST_START_NOWDOC>{TABS_AND_SPACES}{LABEL}";"?[^\n\r]*[\r\n]? */ |
| // there is no [\r\n] if it is the last line |
| // i.e. not [\r\n] but EOF, so check not [\r\n] but [\r\n]? |
| if (isEndNowdoc()) { |
| int indexOfNowdocId = yytext().indexOf(heredoc); |
| int back = yylength() - indexOfNowdocId - heredoc.length(); |
| yypushback(back); |
| heredoc=null; |
| hereocLength=0; |
| yybegin(ST_PHP_IN_SCRIPTING); |
| return PHPTokenId.PHP_NOWDOC_TAG_END; |
| } else { |
| yypushback(1); |
| yybegin(ST_PHP_NOWDOC); |
| } |
| } |
| |
| <ST_PHP_NOWDOC> { |
| {NEWLINE}{TABS_AND_SPACES}{LABEL}";"?[^\n\r]*[\r\n]? { |
| /* <ST_PHP_NOWDOC>{NEWLINE}{TABS_AND_SPACES}{LABEL}";"?[^\n\r]*[\r\n]? */ |
| if (isEndNowdoc()) { |
| String yytext = yytext(); |
| int trailingNewlineOffset = (yytext.endsWith("\n") || yytext.endsWith("\r")) ? 2 : 0; |
| int lastIndexOfNewline = yytext.lastIndexOf('\n', yylength() - trailingNewlineOffset); |
| if (lastIndexOfNewline == -1) { |
| lastIndexOfNewline = yytext.lastIndexOf('\r', yylength() - trailingNewlineOffset); |
| } |
| int back = yylength() - lastIndexOfNewline - 1; // -1 [\r\n] length |
| yypushback(back); |
| yybegin(ST_PHP_END_NOWDOC); |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } else { |
| yypushback(1); // [\r\n] length |
| } |
| } |
| |
| {NOWDOC_CHARS}|{NEWLINE} { |
| /* <ST_PHP_NOWDOC>{NOWDOC_CHARS}|{NEWLINE} */ |
| // retrun PHPTokenId when the closing marker is found |
| } |
| } |
| |
| <ST_PHP_END_NOWDOC>{NEWLINE}*{TABS_AND_SPACES}{LABEL}";"? { |
| heredoc=null; hereocLength=0; |
| yybegin(ST_PHP_IN_SCRIPTING); |
| int back = 0; |
| // mark just the label |
| if (yytext().charAt(yylength() - 1)==';') { |
| back++; |
| } |
| yypushback(back); |
| return PHPTokenId.PHP_NOWDOC_TAG_END; |
| } |
| |
| <ST_PHP_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}({LABEL}|"\""{LABEL}"\""){NEWLINE} { |
| int bprefix = (yytext().charAt(0) != '<') ? 1 : 0; |
| int startString=3+bprefix; |
| hereocLength = yylength()-bprefix-3-1-(yytext().charAt(yylength()-2)=='\r'?1:0); |
| while ((yytext().charAt(startString) == ' ') || (yytext().charAt(startString) == '\t')) { |
| startString++; |
| hereocLength--; |
| } |
| // HEREDOC PHP 5.3 |
| if (yytext().charAt(startString) == '"') { |
| hereocLength -= 2; |
| startString ++; |
| } |
| heredoc = yytext().substring(startString,hereocLength+startString); |
| yybegin(ST_PHP_START_HEREDOC); |
| return PHPTokenId.PHP_HEREDOC_TAG_START; |
| } |
| |
| <ST_PHP_START_HEREDOC> { |
| {TABS_AND_SPACES}{LABEL}";"?[^\n\r]*[\n\r]? { |
| int trailingNewLineLength = 1; |
| int label_len = yylength() - trailingNewLineLength; |
| int back = trailingNewLineLength; |
| |
| if (yytext().charAt(label_len - 1)==';') { |
| label_len--; |
| back++; |
| } |
| |
| if (isEndHeredoc()) { |
| int indexOfHeredocId = yytext().indexOf(heredoc); |
| back += label_len - indexOfHeredocId; |
| yypushback(back); |
| yybegin(ST_PHP_END_HEREDOC); |
| } else { |
| yypushback(yylength() - trailingNewLineLength); |
| yybegin(ST_PHP_HEREDOC); |
| } |
| } |
| {ANY_CHAR} { |
| yypushback(1); |
| yybegin(ST_PHP_HEREDOC); |
| } |
| } |
| |
| <ST_PHP_HEREDOC> { |
| {NEWLINE}{TABS_AND_SPACES}{LABEL}";"?[^\n\r]*[\n\r]? { |
| /* {NEWLINE}{TABS_AND_SPACES}{LABEL}";"?[^\n\r]*[\n\r]? */ |
| int trailingNewLineLength = 1; |
| if (isEndHeredoc()) { |
| String yytext = yytext(); |
| int newlineLength = yytext.startsWith("\r\n") ? 2 : 1; |
| int back = yylength() - newlineLength; |
| yypushback(back); |
| yybegin(ST_PHP_END_HEREDOC); |
| } else { |
| // handle variable |
| char previousChar = ' '; |
| int indexOfVariable = -1; |
| for (int i = 0; i < yylength(); i++) { |
| char currentChar = yytext().charAt(i); |
| if (currentChar == '$' && previousChar == '{') { |
| indexOfVariable = i - 1; |
| break; |
| } |
| if (currentChar == '$' && previousChar != '\\') { |
| indexOfVariable = i; |
| break; |
| } |
| previousChar = currentChar; |
| } |
| |
| if (indexOfVariable == -1) { |
| yypushback(trailingNewLineLength); |
| } else { |
| yypushback(yylength() - indexOfVariable); |
| return PHPTokenId.PHP_ENCAPSED_AND_WHITESPACE; |
| } |
| } |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } |
| |
| {HEREDOC_CHARS} { |
| int indexOfNewline = yytext().indexOf("\r"); |
| if (indexOfNewline == -1) { |
| indexOfNewline = yytext().indexOf("\n"); |
| } |
| if (indexOfNewline > 0) { |
| // if index equals 0, don't pushback (infinite loop) |
| yypushback(yylength() - indexOfNewline); |
| } |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } |
| |
| {HEREDOC_CHARS}("{$" | "${") { |
| yypushback(2); |
| return PHPTokenId.PHP_ENCAPSED_AND_WHITESPACE; |
| } |
| |
| {HEREDOC_CHARS}"$"{LABEL}"["? { |
| String text = yytext(); |
| int lastIndexOfDollar = text.lastIndexOf('$'); |
| yypushback(text.length() - lastIndexOfDollar); |
| return PHPTokenId.PHP_ENCAPSED_AND_WHITESPACE; |
| } |
| |
| "$" | "{" { |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } |
| } |
| |
| <ST_PHP_IN_SCRIPTING>[`] { |
| pushState(ST_PHP_BACKQUOTE); |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } |
| |
| <ST_PHP_END_HEREDOC>{TABS_AND_SPACES}{LABEL}";"? { |
| heredoc=null; |
| hereocLength=0; |
| yybegin(ST_PHP_IN_SCRIPTING); |
| int back = 0; |
| // mark just the label |
| if (yytext().charAt(yylength() - 1)==';') { |
| back++; |
| } |
| yypushback(back); |
| return PHPTokenId.PHP_HEREDOC_TAG_END; |
| } |
| |
| <ST_PHP_DOUBLE_QUOTES,ST_PHP_BACKQUOTE,ST_PHP_HEREDOC,ST_PHP_QUOTES_AFTER_VARIABLE>"{$" { |
| yypushback(1); |
| pushState(ST_PHP_IN_SCRIPTING); |
| return PHPTokenId.PHP_CURLY_OPEN; |
| } |
| |
| <ST_PHP_DOUBLE_QUOTES>{DOUBLE_QUOTES_CHARS}+ { |
| return PHPTokenId.PHP_ENCAPSED_AND_WHITESPACE; |
| } |
| |
| /* |
| The original parsing rule was {DOUBLE_QUOTES_CHARS}*("{"{2,}|"$"{2,}|(("{"+|"$"+)[\"])) |
| but jflex doesn't support a{n,} so we changed a{2,} to aa+ |
| */ |
| <ST_PHP_DOUBLE_QUOTES>{DOUBLE_QUOTES_CHARS}*("{""{"+|"$""$"+|(("{"+|"$"+)[\"])) { |
| yypushback(1); |
| return PHPTokenId.PHP_ENCAPSED_AND_WHITESPACE; |
| } |
| |
| <ST_PHP_BACKQUOTE>{BACKQUOTE_CHARS}+ { |
| return PHPTokenId.PHP_ENCAPSED_AND_WHITESPACE; |
| } |
| |
| /* |
| The original parsing rule was {BACKQUOTE_CHARS}*("{"{2,}|"$"{2,}|(("{"+|"$"+)[`])) |
| but jflex doesn't support a{n,} so we changed a{2,} to aa+ |
| */ |
| <ST_PHP_BACKQUOTE>{BACKQUOTE_CHARS}*("{""{"+|"$""$"+|(("{"+|"$"+)[`])) { |
| yypushback(1); |
| return PHPTokenId.PHP_ENCAPSED_AND_WHITESPACE; |
| } |
| |
| <ST_PHP_DOUBLE_QUOTES>[\"] { |
| popState(); |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } |
| |
| <ST_PHP_BACKQUOTE>[`] { |
| popState(); |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } |
| |
| <ST_PHP_DOUBLE_QUOTES>. { |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING; |
| } |
| |
| <ST_PHP_BACKQUOTE>. { |
| return PHPTokenId.PHP_CONSTANT_ENCAPSED_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_PHP_HIGHLIGHTING_ERROR> { |
| {WHITESPACE} {popState();return PHPTokenId.WHITESPACE;} |
| . {return PHPTokenId.UNKNOWN_TOKEN;} |
| } |
| |
| /* ============================================ |
| This rule must be the last in the section!! |
| it should contain all the states. |
| ============================================ */ |
| <ST_PHP_IN_SCRIPTING,ST_PHP_DOUBLE_QUOTES,ST_PHP_VAR_OFFSET,ST_PHP_BACKQUOTE,ST_PHP_HEREDOC,ST_PHP_START_HEREDOC,ST_PHP_END_HEREDOC,ST_PHP_NOWDOC,ST_PHP_START_NOWDOC,ST_PHP_END_NOWDOC>. { |
| yypushback(1); |
| pushState(ST_PHP_HIGHLIGHTING_ERROR); |
| } |