branch: externals/phps-mode
commit ed309d165beaa585d00cdd22704ef89cbb07f6e7
Author: Christian Johansson <christ...@cvj.se>
Commit: Christian Johansson <christ...@cvj.se>

    Moved lexer rules to separate file
---
 phps-mode-lex-analyzer.el    |    6 +-
 phps-mode-lexer-generator.el | 1532 ++++++++++++++++++++++++++++++++++++++++++
 phps-mode-lexer.el           | 1524 +----------------------------------------
 3 files changed, 1538 insertions(+), 1524 deletions(-)

diff --git a/phps-mode-lex-analyzer.el b/phps-mode-lex-analyzer.el
index f0d60c6dc3..f55d4df4d1 100644
--- a/phps-mode-lex-analyzer.el
+++ b/phps-mode-lex-analyzer.el
@@ -415,11 +415,11 @@ ALLOW-CACHE-READ and ALLOW-CACHE-WRITE."
                    (when error-start
                      (if error-end
                          (phps-mode-lex-analyzer--set-region-syntax-color
-                          error-start
-                          error-end
+                          (max error-start (point-min))
+                          (min error-end (point-max))
                           (list 'font-lock-face 'font-lock-warning-face))
                        (phps-mode-lex-analyzer--set-region-syntax-color
-                        error-start
+                        (max error-start (point-min))
                         (point-max)
                         (list 'font-lock-face 'font-lock-warning-face)))
 
diff --git a/phps-mode-lexer-generator.el b/phps-mode-lexer-generator.el
new file mode 100644
index 0000000000..b6e9122138
--- /dev/null
+++ b/phps-mode-lexer-generator.el
@@ -0,0 +1,1532 @@
+;;; phps-mode-lexer-generator.el -- Generate lexer rules for lexer -*- 
lexical-binding: t -*-
+
+;; Copyright (C) 2018-2023  Free Software Foundation, Inc.
+
+
+;;; Commentary:
+
+
+;;; Code:
+
+
+(defvar phps-mode-lexer-generator--table (make-hash-table :test 'equal))
+
+(defmacro phps-mode-lexer-generator--match-macro (states conditions &rest body)
+  "Place in STATES a check for CONDITIONS to execute BODY."
+  (unless (listp states)
+    (setq states (list states)))
+  (dolist (state states)
+    (let ((old-lambdas
+           (gethash
+            state
+            phps-mode-lexer-generator--table)))
+      (when old-lambdas
+        (setq
+         old-lambdas
+         (reverse old-lambdas)))
+      (push `((lambda() ,conditions) (lambda() ,@body)) old-lambdas)
+      (setq old-lambdas (reverse old-lambdas))
+      (puthash
+       state
+       old-lambdas
+       phps-mode-lexer-generator--table))))
+
+(defun phps-mode-lexer-generator--lambdas ()
+  (setq phps-mode-lexer-generator--table (make-hash-table :test 'equal))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "exit")
+     (phps-mode-lexer--return-token-with-indent 'T_EXIT))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "die")
+     (phps-mode-lexer--return-token-with-indent 'T_EXIT))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "fn")
+     (phps-mode-lexer--return-token-with-indent 'T_FN))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "function")
+     (phps-mode-lexer--return-token-with-indent 'T_FUNCTION))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "const")
+     (phps-mode-lexer--return-token-with-indent 'T_CONST))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "return")
+     (phps-mode-lexer--return-token-with-indent 'T_RETURN))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "#\\[")
+     (phps-mode-lexer--enter-nesting "[")
+     (phps-mode-lexer--return-token 'T_ATTRIBUTE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "yield"
+       phps-mode-lexer--whitespace
+       "from"
+       "[^a-zA-Z0-9_\x80-\xff]"))
+     (phps-mode-lexer--return-token-with-indent 'T_YIELD_FROM))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "yield")
+     (phps-mode-lexer--return-token-with-indent 'T_YIELD))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "try")
+     (phps-mode-lexer--return-token-with-indent 'T_TRY))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "catch")
+     (phps-mode-lexer--return-token-with-indent 'T_CATCH))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "finally")
+     (phps-mode-lexer--return-token-with-indent 'T_FINALLY))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "throw")
+     (phps-mode-lexer--return-token-with-indent 'T_THROW))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "if")
+     (phps-mode-lexer--return-token-with-indent 'T_IF))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "elseif")
+     (phps-mode-lexer--return-token-with-indent 'T_ELSEIF))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "endif")
+     (phps-mode-lexer--return-token-with-indent 'T_ENDIF))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "else")
+     (phps-mode-lexer--return-token-with-indent 'T_ELSE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "while")
+     (phps-mode-lexer--return-token-with-indent 'T_WHILE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "endwhile")
+     (phps-mode-lexer--return-token-with-indent 'T_ENDWHILE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "do")
+     (phps-mode-lexer--return-token-with-indent 'T_DO))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "for")
+     (phps-mode-lexer--return-token-with-indent 'T_FOR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "endfor")
+     (phps-mode-lexer--return-token-with-indent 'T_ENDFOR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "foreach")
+     (phps-mode-lexer--return-token-with-indent 'T_FOREACH))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "endforeach")
+     (phps-mode-lexer--return-token-with-indent 'T_ENDFOREACH))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "declare")
+     (phps-mode-lexer--return-token-with-indent 'T_DECLARE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "enddeclare")
+     (phps-mode-lexer--return-token-with-indent 'T_ENDDECLARE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "instanceof")
+     (phps-mode-lexer--return-token-with-indent 'T_INSTANCEOF))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "as")
+     (phps-mode-lexer--return-token-with-indent 'T_AS))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "switch")
+     (phps-mode-lexer--return-token-with-indent 'T_SWITCH))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "match")
+     (phps-mode-lexer--return-token-with-indent 'T_MATCH))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "endswitch")
+     (phps-mode-lexer--return-token-with-indent 'T_ENDSWITCH))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "case")
+     (phps-mode-lexer--return-token-with-indent 'T_CASE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "default")
+     (phps-mode-lexer--return-token-with-indent 'T_DEFAULT))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "break")
+     (phps-mode-lexer--return-token-with-indent 'T_BREAK))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "continue")
+     (phps-mode-lexer--return-token-with-indent 'T_CONTINUE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "goto")
+     (phps-mode-lexer--return-token-with-indent 'T_GOTO))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "echo")
+     (phps-mode-lexer--return-token-with-indent 'T_ECHO))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "print")
+     (phps-mode-lexer--return-token-with-indent 'T_PRINT))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "class")
+     (phps-mode-lexer--return-token-with-indent 'T_CLASS))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "interface")
+     (phps-mode-lexer--return-token-with-indent 'T_INTERFACE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "trait")
+     (phps-mode-lexer--return-token-with-indent 'T_TRAIT))
+
+    ;; The enum keyword must be followed by whitespace and another identifier.
+    ;; This avoids the BC break of using enum in classes, namespaces, 
functions and constants.
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at (concat "\\(enum\\)" phps-mode-lexer--whitespace 
"\\(extends\\|implements\\)"))
+     (phps-mode-lexer--yyless 4)
+     (phps-mode-lexer--return-token-with-str 'T_STRING))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at (concat "\\(enum\\)" phps-mode-lexer--whitespace 
"[a-zA-Z_\x80-\xff]"))
+     (phps-mode-lexer--yyless 4)
+     (phps-mode-lexer--return-token-with-indent 'T_ENUM (match-beginning 1) 
(match-end 1)))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "extends")
+     (phps-mode-lexer--return-token-with-indent 'T_EXTENDS))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "implements")
+     (phps-mode-lexer--return-token-with-indent 'T_IMPLEMENTS))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "->")
+     (phps-mode-lexer--yy-push-state 'ST_LOOKING_FOR_PROPERTY)
+     (phps-mode-lexer--return-token-with-indent 'T_OBJECT_OPERATOR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "?->")
+     (phps-mode-lexer--yy-push-state 'ST_LOOKING_FOR_PROPERTY)
+     (phps-mode-lexer--return-token-with-indent 'T_NULLSAFE_OBJECT_OPERATOR))
+
+    (phps-mode-lexer-generator--match-macro
+     (ST_IN_SCRIPTING ST_LOOKING_FOR_PROPERTY)
+     (looking-at phps-mode-lexer--whitespace)
+     (phps-mode-lexer--return-whitespace))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_LOOKING_FOR_PROPERTY
+     (looking-at "->")
+     (phps-mode-lexer--return-token 'T_OBJECT_OPERATOR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_LOOKING_FOR_PROPERTY
+     (looking-at "?->")
+     (phps-mode-lexer--return-token 'T_NULLSAFE_OBJECT_OPERATOR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_LOOKING_FOR_PROPERTY
+     (looking-at phps-mode-lexer--label)
+     (phps-mode-lexer--yy-pop-state)
+     (phps-mode-lexer--return-token-with-str 'T_STRING 0))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_LOOKING_FOR_PROPERTY
+     (looking-at phps-mode-lexer--any-char)
+     (phps-mode-lexer--yyless 0)
+     (phps-mode-lexer--yy-pop-state)
+     (phps-mode-lexer--restart))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "::")
+     (phps-mode-lexer--return-token 'T_PAAMAYIM_NEKUDOTAYIM))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\.\\.\\.")
+     (phps-mode-lexer--return-token 'T_ELLIPSIS))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\?\\?")
+     (phps-mode-lexer--return-token 'T_COALESCE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "new")
+     (phps-mode-lexer--return-token-with-indent 'T_NEW))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "clone")
+     (phps-mode-lexer--return-token-with-indent 'T_CLONE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "var")
+     (phps-mode-lexer--return-token-with-indent 'T_VAR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "("
+       phps-mode-lexer--tabs-and-spaces
+       "\\(int\\|integer\\)"
+       phps-mode-lexer--tabs-and-spaces
+       ")"))
+     (phps-mode-lexer--return-token 'T_INT_CAST))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "("
+       phps-mode-lexer--tabs-and-spaces
+       "\\(double\\|float\\)"
+       phps-mode-lexer--tabs-and-spaces
+       ")"))
+     (phps-mode-lexer--return-token 'T_DOUBLE_CAST))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "("
+       phps-mode-lexer--tabs-and-spaces
+       "\\(real\\)"
+       phps-mode-lexer--tabs-and-spaces
+       ")"))
+     (when (phps-mode-lexer--parser-mode)
+       (signal
+        'phps-lexer-error
+        (list
+         (format
+          "The (real) cast has been removed, use (float) instead at %d"
+          (match-beginning 0))
+         (match-beginning 0)
+         (match-end 0))))
+     (phps-mode-lexer--return-token 'T_DOUBLE_CAST))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "("
+       phps-mode-lexer--tabs-and-spaces
+       "\\(string\\|binary\\)"
+       phps-mode-lexer--tabs-and-spaces
+       ")"))
+     (phps-mode-lexer--return-token 'T_STRING_CAST))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "("
+       phps-mode-lexer--tabs-and-spaces
+       "array"
+       phps-mode-lexer--tabs-and-spaces
+       ")"))
+     (phps-mode-lexer--return-token 'T_ARRAY_CAST))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "("
+       phps-mode-lexer--tabs-and-spaces
+       "object"
+       phps-mode-lexer--tabs-and-spaces
+       ")"))
+     (phps-mode-lexer--return-token 'T_OBJECT_CAST))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "("
+       phps-mode-lexer--tabs-and-spaces
+       "\\(bool\\|boolean\\)"
+       phps-mode-lexer--tabs-and-spaces
+       ")"))
+     (phps-mode-lexer--return-token 'T_BOOL_CAST))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "("
+       phps-mode-lexer--tabs-and-spaces
+       "unset"
+       phps-mode-lexer--tabs-and-spaces ")"))
+     (phps-mode-lexer--return-token 'T_UNSET_CAST))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "eval")
+     (phps-mode-lexer--return-token-with-indent 'T_EVAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "include")
+     (phps-mode-lexer--return-token-with-indent 'T_INCLUDE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "include_once")
+     (phps-mode-lexer--return-token-with-indent 'T_INCLUDE_ONCE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "require")
+     (phps-mode-lexer--return-token-with-indent 'T_REQUIRE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "require_once")
+     (phps-mode-lexer--return-token-with-indent 'T_REQUIRE_ONCE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "namespace")
+     (phps-mode-lexer--return-token-with-indent 'T_NAMESPACE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "use")
+     (phps-mode-lexer--return-token-with-indent 'T_USE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "insteadof")
+     (phps-mode-lexer--return-token-with-indent 'T_INSTEADOF))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "global")
+     (phps-mode-lexer--return-token-with-indent 'T_GLOBAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "isset")
+     (phps-mode-lexer--return-token-with-indent 'T_ISSET))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "empty")
+     (phps-mode-lexer--return-token-with-indent 'T_EMPTY))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "__halt_compiler")
+     (phps-mode-lexer--return-token-with-indent 'T_HALT_COMPILER))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "static")
+     (phps-mode-lexer--return-token-with-indent 'T_STATIC))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "abstract")
+     (phps-mode-lexer--return-token-with-indent 'T_ABSTRACT))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "final")
+     (phps-mode-lexer--return-token-with-indent 'T_FINAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "private")
+     (phps-mode-lexer--return-token-with-indent 'T_PRIVATE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "protected")
+     (phps-mode-lexer--return-token-with-indent 'T_PROTECTED))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "public")
+     (phps-mode-lexer--return-token-with-indent 'T_PUBLIC))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "readonly")
+     (phps-mode-lexer--return-token-with-indent 'T_READONLY))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "unset")
+     (phps-mode-lexer--return-token-with-indent 'T_UNSET))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "=>")
+     (phps-mode-lexer--return-token 'T_DOUBLE_ARROW))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "list")
+     (phps-mode-lexer--return-token-with-indent 'T_LIST))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "array")
+     (phps-mode-lexer--return-token-with-indent 'T_ARRAY))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "callable")
+     (phps-mode-lexer--return-token-with-indent 'T_CALLABLE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\+\\+")
+     (phps-mode-lexer--return-token 'T_INC))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "--")
+     (phps-mode-lexer--return-token 'T_DEC))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "===")
+     (phps-mode-lexer--return-token 'T_IS_IDENTICAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "!==")
+     (phps-mode-lexer--return-token 'T_IS_NOT_IDENTICAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "==")
+     (phps-mode-lexer--return-token 'T_IS_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\(!=\\|<>\\)")
+     (phps-mode-lexer--return-token 'T_IS_NOT_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "<=>")
+     (phps-mode-lexer--return-token 'T_SPACESHIP))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "<=")
+     (phps-mode-lexer--return-token 'T_IS_SMALLER_OR_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at ">=")
+     (phps-mode-lexer--return-token 'T_IS_GREATER_OR_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\+=")
+     (phps-mode-lexer--return-token 'T_PLUS_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "-=")
+     (phps-mode-lexer--return-token 'T_MINUS_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\*=")
+     (phps-mode-lexer--return-token 'T_MUL_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\*\\\\\\*")
+     (phps-mode-lexer--return-token 'T_POW))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\*\\\\\\*=")
+     (phps-mode-lexer--return-token 'T_POW_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "/=")
+     (phps-mode-lexer--return-token 'T_DIV_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\.=")
+     (phps-mode-lexer--return-token 'T_CONCAT_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "%=")
+     (phps-mode-lexer--return-token 'T_MOD_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "<<=")
+     (phps-mode-lexer--return-token 'T_SL_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at ">>=")
+     (phps-mode-lexer--return-token 'T_SR_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "&=")
+     (phps-mode-lexer--return-token 'T_AND_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "|=")
+     (phps-mode-lexer--return-token 'T_OR_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\^=")
+     (phps-mode-lexer--return-token 'T_XOR_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\?\\?=")
+     (phps-mode-lexer--return-token 'T_COALESCE_EQUAL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "||")
+     (phps-mode-lexer--return-token 'T_BOOLEAN_OR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "&&")
+     (phps-mode-lexer--return-token 'T_BOOLEAN_AND))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "OR")
+     (phps-mode-lexer--return-token 'T_LOGICAL_OR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "AND")
+     (phps-mode-lexer--return-token 'T_LOGICAL_AND))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "XOR")
+     (phps-mode-lexer--return-token 'T_LOGICAL_XOR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "<<")
+     (phps-mode-lexer--return-token 'T_SL))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at ">>")
+     (phps-mode-lexer--return-token 'T_SR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at (concat "&" "[ \t\r\n]*" "\\(\\$\\|\\.\\.\\.\\)"))
+     (phps-mode-lexer--yyless 1)
+     (phps-mode-lexer--return-token
+      'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
+      (match-beginning 0)
+      (- (match-end 0) 1)))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "&")
+     (phps-mode-lexer--return-token 
'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat "\\(" "]" "\\|" ")" "\\)"))
+     (phps-mode-lexer--return-exit-nesting-token))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat "\\(" "\\[" "\\|" "(" "\\)"))
+     (phps-mode-lexer--enter-nesting)
+     (phps-mode-lexer--return-token))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at phps-mode-lexer--tokens)
+     (phps-mode-lexer--return-token))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "{")
+     (phps-mode-lexer--yy-push-state 'ST_IN_SCRIPTING)
+     (phps-mode-lexer--enter-nesting "{")
+     (phps-mode-lexer--return-token))
+
+    (phps-mode-lexer-generator--match-macro
+     (ST_DOUBLE_QUOTES ST_BACKQUOTE ST_HEREDOC)
+     (looking-at "\\${")
+     (phps-mode-lexer--yy-push-state 'ST_LOOKING_FOR_VARNAME)
+     (phps-mode-lexer--enter-nesting "{")
+     (phps-mode-lexer--return-token 'T_DOLLAR_OPEN_CURLY_BRACES))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "}")
+     (phps-mode-lexer--reset-doc-comment)
+     (when phps-mode-lexer--state-stack
+       (phps-mode-lexer--yy-pop-state))
+     (phps-mode-lexer--return-exit-nesting-token))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_LOOKING_FOR_VARNAME
+     (looking-at (concat phps-mode-lexer--label "[\\[}]"))
+     (let* ((start (match-beginning 0))
+            (end (1- (match-end 0)))
+            (_data (buffer-substring-no-properties start end)))
+       (phps-mode-lexer--yyless 1)
+       (phps-mode-lexer--yy-pop-state)
+       (phps-mode-lexer--yy-push-state 'ST_IN_SCRIPTING)
+       (phps-mode-lexer--return-token 'T_STRING_VARNAME start end)))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_LOOKING_FOR_VARNAME
+     (looking-at phps-mode-lexer--any-char)
+     (phps-mode-lexer--yyless 0)
+     (phps-mode-lexer--yy-pop-state)
+     (phps-mode-lexer--yy-push-state 'ST_IN_SCRIPTING)
+     (phps-mode-lexer--restart))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at phps-mode-lexer--bnum)
+     (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (data
+             (replace-regexp-in-string
+              "_"
+              ""
+              (buffer-substring-no-properties (+ start 2) end)))
+            (long-number (string-to-number data 2)))
+       ;; (message "Binary number %s from %s" long-number data)
+       (if (> long-number phps-mode-lexer--long-limit)
+           (phps-mode-lexer--return-token 'T_DNUMBER)
+         (phps-mode-lexer--return-token 'T_LNUMBER))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at phps-mode-lexer--onum)
+     (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (data (string-to-number
+                   (replace-regexp-in-string
+                    "_"
+                    ""
+                    (buffer-substring-no-properties start end))
+                   8)))
+       (if (> data phps-mode-lexer--long-limit)
+           (phps-mode-lexer--return-token 'T_DNUMBER)
+         (phps-mode-lexer--return-token 'T_LNUMBER))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at phps-mode-lexer--lnum)
+     (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (data (string-to-number
+                   (replace-regexp-in-string
+                    "_"
+                    ""
+                    (buffer-substring-no-properties start end)))))
+       ;; (message "Long number: %d" data)
+       (if (> data phps-mode-lexer--long-limit)
+           (phps-mode-lexer--return-token 'T_DNUMBER)
+         (phps-mode-lexer--return-token 'T_LNUMBER))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at phps-mode-lexer--hnum)
+     (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (data
+             (replace-regexp-in-string
+              "_"
+              ""
+              (buffer-substring-no-properties (+ start 2) end)))
+            (long-number (string-to-number data 16)))
+       ;; (message "Hexadecimal number %s from %s" long-number data)
+       (if (> long-number phps-mode-lexer--long-limit)
+           (phps-mode-lexer--return-token 'T_DNUMBER)
+         (phps-mode-lexer--return-token 'T_LNUMBER))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_VAR_OFFSET
+     (looking-at "\\([0]\\|[1-9][0-9]*\\)")
+     (phps-mode-lexer--return-token 'T_NUM_STRING))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_VAR_OFFSET
+     (looking-at
+      (concat "\\("
+              phps-mode-lexer--lnum "\\|"
+              phps-mode-lexer--hnum "\\|"
+              phps-mode-lexer--bnum "\\|"
+              phps-mode-lexer--onum "\\)"))
+     (phps-mode-lexer--return-token 'T_NUM_STRING))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (or (looking-at phps-mode-lexer--dnum)
+         (looking-at phps-mode-lexer--exponent-dnum))
+     (phps-mode-lexer--return-token 'T_DNUMBER))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "__CLASS__")
+     (phps-mode-lexer--return-token-with-indent 'T_CLASS_C))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "__TRAIT__")
+     (phps-mode-lexer--return-token-with-indent 'T_TRAIT_C))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "__FUNCTION__")
+     (phps-mode-lexer--return-token-with-indent 'T_FUNC_C))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "__METHOD__")
+     (phps-mode-lexer--return-token-with-indent 'T_METHOD_C))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "__LINE__")
+     (phps-mode-lexer--return-token-with-indent 'T_LINE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "__FILE__")
+     (phps-mode-lexer--return-token-with-indent 'T_FILE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "__DIR__")
+     (phps-mode-lexer--return-token-with-indent 'T_DIR))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "__NAMESPACE__")
+     (phps-mode-lexer--return-token-with-indent 'T_NS_C))
+
+    (phps-mode-lexer-generator--match-macro
+     'SHEBANG
+     (looking-at (concat "#!.*" phps-mode-lexer--newline))
+     (let ((lineno
+            (1+
+             (phps-mode-lexer--CG 'zend_lineno))))
+       (phps-mode-lexer--CG 'zend-lineno lineno))
+     (phps-mode-lexer--begin 'ST_INITIAL)
+     (phps-mode-lexer--restart))
+
+    (phps-mode-lexer-generator--match-macro
+     'SHEBANG
+     (looking-at phps-mode-lexer--any-char)
+     (phps-mode-lexer--yyless 0)
+     (phps-mode-lexer--begin 'ST_INITIAL)
+     (phps-mode-lexer--restart))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_INITIAL
+     (looking-at "<\\?=")
+     (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
+     (when (phps-mode-lexer--parser-mode)
+       (phps-mode-lexer--return-token-with-indent 'T_ECHO))
+     (phps-mode-lexer--return-token 'T_OPEN_TAG_WITH_ECHO))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_INITIAL
+     (looking-at
+      (concat
+       "<\\?php\\([ \t]\\|"
+       phps-mode-lexer--newline
+       "\\)"))
+     (phps-mode-lexer--handle-newline)
+     (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
+     (phps-mode-lexer--return-or-skip-token 'T_OPEN_TAG))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_INITIAL
+     (looking-at "<\\?php")
+     (let ((start (match-beginning 0))
+           (end (match-end 0)))
+
+       (cond
+
+        ;; Allow <?php followed by end of file.
+        ((equal end (point-max))
+         (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
+         (phps-mode-lexer--return-or-skip-token 'T_OPEN_TAG))
+
+        ;; Degenerate case: <?phpX is interpreted as <? phpX with short tags
+        ((phps-mode-lexer--CG 'short-tags)
+         (phps-mode-lexer--yyless 2)
+         (setq end (- end 2))
+         (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
+         (phps-mode-lexer--return-or-skip-token
+          'T_OPEN_TAG
+          start
+          end))
+
+        (t
+         (phps-mode-lexer--inline-char-handler)))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_INITIAL
+     (looking-at "<\\?")
+     (if (phps-mode-lexer--CG 'short-tags)
+         (progn
+           (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
+           (phps-mode-lexer--return-or-skip-token 'T_OPEN_TAG))
+       (phps-mode-lexer--inline-char-handler)))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_INITIAL
+     (looking-at phps-mode-lexer--any-char)
+     (if (= (point) (point-max))
+         (phps-mode-lexer--return-end-token)
+       (phps-mode-lexer--inline-char-handler)))
+
+    ;; Make sure a label character follows "->" or "?->", otherwise there is 
no property
+    ;; and "->"/"?->" will be taken literally
+    (phps-mode-lexer-generator--match-macro
+     (ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE)
+     (looking-at
+      (concat
+       "\\$"
+       phps-mode-lexer--label
+       "->"
+       "[a-zA-Z_\x80-\xff]"))
+     (phps-mode-lexer--yyless 3)
+     (phps-mode-lexer--yy-push-state 'ST_LOOKING_FOR_PROPERTY)
+     (phps-mode-lexer--return-token-with-str
+      'T_VARIABLE
+      1
+      (match-beginning 0)
+      (- (match-end 0) 3)))
+
+    (phps-mode-lexer-generator--match-macro
+     (ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE)
+     (looking-at
+      (concat
+       "\\$"
+       phps-mode-lexer--label
+       "\\?->"
+       "[a-zA-Z_\x80-\xff]"))
+     (phps-mode-lexer--yyless 4)
+     (phps-mode-lexer--yy-push-state 'ST_LOOKING_FOR_PROPERTY)
+     (phps-mode-lexer--return-token-with-str
+      'T_VARIABLE
+      1
+      (match-beginning 0)
+      (- (match-end 0) 4)))
+
+    ;; A [ always designates a variable offset, regardless of what follows
+    (phps-mode-lexer-generator--match-macro
+     (ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE)
+     (looking-at
+      (concat
+       "\\$"
+       phps-mode-lexer--label
+       "\\["))
+     (phps-mode-lexer--yyless 1)
+     (phps-mode-lexer--yy-push-state 'ST_VAR_OFFSET)
+     (phps-mode-lexer--return-token-with-str
+      'T_VARIABLE
+      1
+      (match-beginning 0)
+      (- (match-end 0) 1)))
+
+    (phps-mode-lexer-generator--match-macro
+     (
+      ST_IN_SCRIPTING
+      ST_DOUBLE_QUOTES
+      ST_HEREDOC
+      ST_BACKQUOTE
+      ST_VAR_OFFSET)
+     (looking-at
+      (concat
+       "\\$"
+       phps-mode-lexer--label))
+     (phps-mode-lexer--return-token-with-str 'T_VARIABLE 1))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_VAR_OFFSET
+     (looking-at "\\]")
+     (phps-mode-lexer--yy-pop-state)
+     (phps-mode-lexer--return-token-with-str "]" 1))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_VAR_OFFSET
+     (looking-at
+      (concat "\\(" phps-mode-lexer--tokens
+              "\\|[{}\"`]\\)"))
+     (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (data (buffer-substring-no-properties start end)))
+       ;; Only '[' or '-' can be valid, but returning other tokens will allow 
a more explicit parse error
+       (phps-mode-lexer--return-token data)))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_VAR_OFFSET
+     (looking-at (concat "[ \n\r\t'#]"))
+     ;; Invalid rule to return a more explicit parse error with proper line 
number
+     (phps-mode-lexer--yyless 0)
+     (phps-mode-lexer--yy-pop-state)
+     (phps-mode-lexer--return-token-with-val 'T_ENCAPSED_AND_WHITESPACE))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "namespace"
+       "\\("
+       "\\\\"
+       phps-mode-lexer--label
+       "\\)+"))
+     (phps-mode-lexer--return-token-with-str
+      'T_NAME_RELATIVE
+      (1- (length "namespace\\"))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at (concat
+                  phps-mode-lexer--label
+                  "\\("
+                  "\\\\"
+                  phps-mode-lexer--label
+                  "\\)+"))
+     (phps-mode-lexer--return-token-with-str
+      'T_NAME_QUALIFIED
+      0))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at (concat
+                  "\\\\"
+                  phps-mode-lexer--label
+                  "\\("
+                  "\\\\"
+                  phps-mode-lexer--label
+                  "\\)*"))
+     (phps-mode-lexer--return-token-with-str
+      'T_NAME_FULLY_QUALIFIED
+      1))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\\\")
+     (phps-mode-lexer--return-token 'T_NS_SEPARATOR))
+
+    (phps-mode-lexer-generator--match-macro
+     (ST_IN_SCRIPTING ST_VAR_OFFSET)
+     (looking-at phps-mode-lexer--label)
+     (phps-mode-lexer--return-token-with-str 'T_STRING 0))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\\(#\\|//\\)")
+     (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (_data (buffer-substring-no-properties start end))
+            (line (buffer-substring-no-properties end (line-end-position))))
+       (if (string-match "\\?>" line)
+           (phps-mode-lexer--return-or-skip-token
+            'T_COMMENT
+            start
+            (+ end (match-beginning 0)))
+         (phps-mode-lexer--return-or-skip-token
+          'T_COMMENT
+          start
+          (line-end-position)))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "\\(/\\*\\|/\\*\\*"
+       phps-mode-lexer--whitespace
+       "\\)"))
+     (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (_data (buffer-substring-no-properties start end))
+            (doc-com (looking-at-p (concat "/\\*\\*" 
phps-mode-lexer--whitespace))))
+       (let ((string-start (search-forward "*/" nil t)))
+         (if string-start
+             (if doc-com
+                 (progn
+                   (phps-mode-lexer--reset-doc-comment)
+                   (phps-mode-lexer--return-token
+                    'T_DOC_COMMENT
+                    start)
+                   (phps-mode-lexer--CG 'doc_comment t))
+               (phps-mode-lexer--return-token
+                'T_COMMENT start))
+           (progn
+             (signal
+              'phps-lexer-error
+              (list
+               (format
+                "Unterminated comment starting at %d"
+                start)
+               start)))))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "\\?>"
+       phps-mode-lexer--newline
+       "?"))
+     (let ((start (match-beginning 0))
+           (end (match-end 0)))
+       (when (= (- end start) 3)
+         (setq end (1- end)))
+       (phps-mode-lexer--begin 'ST_INITIAL)
+       (when (phps-mode-lexer--parser-mode)
+         (phps-mode-lexer--return-token
+          ";"
+          start
+          end))
+       (phps-mode-lexer--return-token
+        'T_CLOSE_TAG
+        start
+        end)))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "'")
+     (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (_data (buffer-substring-no-properties start end))
+            (un-escaped-end (phps-mode-lexer--get-next-unescaped "'")))
+       (if un-escaped-end
+           (phps-mode-lexer--return-token
+            'T_CONSTANT_ENCAPSED_STRING
+            start
+            un-escaped-end)
+         ;; Unclosed single quotes
+         (phps-mode-lexer--return-token-with-val
+          'T_ENCAPSED_AND_WHITESPACE
+          start
+          (point-max))
+         (phps-mode-lexer--move-forward
+          (point-max)))))
+
+    ;; Double quoted string
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "\"")
+     (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (_data (buffer-substring-no-properties start end))
+            (open-quote t))
+
+       ;; Move forward from the double-quote one character
+       (forward-char)
+
+       (while open-quote
+         (let ((string-start
+                (search-forward-regexp
+                 (concat
+                  "\\(\""
+                  "\\|\\$" phps-mode-lexer--label
+                  "\\|\\${" phps-mode-lexer--label
+                  "\\|{\\$" phps-mode-lexer--label "\\)")
+                 nil t)))
+
+           ;; Do we find a ending double quote or starting variable?
+           (if string-start
+               (let ((string-start (match-beginning 0))
+                     (last-character-is-escape-character t)
+                     (is-escaped nil))
+
+                 ;; Do we find variable inside quote?
+                 (goto-char string-start)
+
+                 ;; Backtrack until we find a character that is not a escape 
character
+                 (while last-character-is-escape-character
+                   (forward-char -1)
+                   (if (looking-at-p "\\\\")
+                       (setq is-escaped (not is-escaped))
+                     (setq last-character-is-escape-character nil)))
+
+                 ;; Do we find variable inside quote?
+                 (goto-char string-start)
+
+                 ;; Process character but only if it's not escaped
+                 (if is-escaped
+                     (forward-char 1)
+                   (setq open-quote nil)
+                   (if (looking-at-p "\"")
+                       (let ((_double-quoted-string
+                              (buffer-substring-no-properties start (+ 
string-start 1))))
+                         ;; (message "Double quoted string: %s" 
_double-quoted-string)
+                         (phps-mode-lexer--return-token-with-val
+                          'T_CONSTANT_ENCAPSED_STRING
+                          start
+                          (+ string-start 1)))
+                     ;; (message "Found variable after '%s' at %s-%s" 
(buffer-substring-no-properties start string-start) start string-start)
+                     (phps-mode-lexer--begin 'ST_DOUBLE_QUOTES)
+                     (phps-mode-lexer--return-token "\"" start (1+ start)))))
+             (progn
+               (setq open-quote nil)
+               (signal
+                'phps-lexer-error
+                (list
+                 (format "Found no ending of quote at %s" start)
+                 start))))))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at
+      (concat
+       "<<<"
+       phps-mode-lexer--tabs-and-spaces
+       "\\("
+       phps-mode-lexer--label
+       "\\|'"
+       phps-mode-lexer--label
+       "'\\|\""
+       phps-mode-lexer--label
+       "\"\\)"
+       phps-mode-lexer--newline))
+     (let* ((start (match-beginning 0))
+            (end (match-end 0))
+            (data
+             (buffer-substring-no-properties
+              (match-beginning 1)
+              (match-end 1))))
+
+       ;; Determine if it's HEREDOC or NOWDOC and extract label here
+       (if (string= (substring data 0 1) "'")
+           (progn
+             (setq
+              phps-mode-lexer--heredoc-label
+              (substring data 1 (- (length data) 1)))
+             (phps-mode-lexer--begin 'ST_NOWDOC))
+         (progn
+           (if (string= (substring data 0 1) "\"")
+               (setq
+                phps-mode-lexer--heredoc-label
+                (substring data 1 (- (length data) 1)))
+             (setq
+              phps-mode-lexer--heredoc-label
+              data))
+           (phps-mode-lexer--begin 'ST_HEREDOC)))
+
+       ;; Check for ending label on the next line
+       (when (string=
+              (buffer-substring-no-properties
+               end
+               (+ end
+                  (length
+                   phps-mode-lexer--heredoc-label)))
+              phps-mode-lexer--heredoc-label)
+         (phps-mode-lexer--begin 'ST_END_HEREDOC))
+
+       (push
+        `(,phps-mode-lexer--heredoc-label ,start ,end)
+        phps-mode-lexer--heredoc-label-stack)
+       ;; (message "Found heredoc or nowdoc at %s with label %s" data 
phps-mode-lexer--heredoc-label)
+
+       (phps-mode-lexer--CG
+        'doc_comment
+        t)
+       (phps-mode-lexer--return-token
+        'T_START_HEREDOC
+        start
+        end)))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_IN_SCRIPTING
+     (looking-at "[`]")
+     ;; (message "Begun backquote at %s-%s" (match-beginning 0) (match-end 0))
+     (phps-mode-lexer--begin 'ST_BACKQUOTE)
+     (phps-mode-lexer--return-token "`"))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_END_HEREDOC
+     (looking-at
+      (concat phps-mode-lexer--any-char))
+     (let* ((start (match-beginning 0))
+            (end (+ start
+                    (length
+                     phps-mode-lexer--heredoc-label)))
+            (_data (buffer-substring-no-properties start end)))
+       ;; (message "Found ending heredoc at %s, %s of %s" _data 
(thing-at-point 'line) phps-mode-lexer--heredoc-label)
+       (pop phps-mode-lexer--heredoc-label-stack)
+       (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
+       (phps-mode-lexer--return-token 'T_END_HEREDOC start end)))
+
+    (phps-mode-lexer-generator--match-macro
+     (ST_DOUBLE_QUOTES ST_BACKQUOTE ST_HEREDOC)
+     (looking-at "{\\$")
+     (phps-mode-lexer--yy-push-state 'ST_IN_SCRIPTING)
+     (phps-mode-lexer--yyless 1)
+     (phps-mode-lexer--enter-nesting "{")
+     (phps-mode-lexer--return-token
+      'T_CURLY_OPEN
+      (match-beginning 0)
+      (- (match-end 0) 1)))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_DOUBLE_QUOTES
+     (looking-at "[\"]")
+     (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
+     (phps-mode-lexer--return-token "\""))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_BACKQUOTE
+     (looking-at "[`]")
+     (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
+     (phps-mode-lexer--return-token "`"))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_DOUBLE_QUOTES
+     (looking-at phps-mode-lexer--any-char)
+     (let ((start (point))
+           (start-error (car (cdr (nth 2 phps-mode-lexer--generated-tokens)))))
+       (let ((string-start (search-forward-regexp "[^\\\\]\"" nil t)))
+         (if string-start
+             (let* ((end (- (match-end 0) 1))
+                    (double-quoted-string (buffer-substring-no-properties 
start end)))
+               ;; Do we find variable inside quote?
+               (if (or (string-match (concat "\\${" phps-mode-lexer--label) 
double-quoted-string)
+                       (string-match (concat "{\\$" phps-mode-lexer--label) 
double-quoted-string)
+                       (string-match (concat "\\$" phps-mode-lexer--label) 
double-quoted-string))
+                   (progn
+                     (let ((variable-start (+ start (match-beginning 0))))
+
+                       ;; (message "Found starting expression inside 
double-quoted string at: %s %s" start variable-start)
+                       (phps-mode-lexer--return-token-with-val
+                        'T_ENCAPSED_AND_WHITESPACE
+                        start
+                        variable-start)))
+                 (progn
+                   (phps-mode-lexer--return-token-with-val
+                    'T_ENCAPSED_AND_WHITESPACE
+                    start
+                    end)
+                   ;; (message "Found end of quote at %s-%s, moving ahead 
after '%s'" start end (buffer-substring-no-properties start end))
+                   )))
+           (progn
+             (signal
+              'phps-lexer-error
+              (list
+               (format "Found no ending of double quoted region starting at 
%d" start-error)
+               start-error)))))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_BACKQUOTE
+     (looking-at phps-mode-lexer--any-char)
+     (let ((start (car (cdr (car phps-mode-lexer--generated-tokens)))))
+       (let ((string-start (search-forward-regexp "\\([^\\\\]`\\|\\$\\|{\\)" 
nil t)))
+         (if string-start
+             (let ((start (- (match-end 0) 1)))
+               ;; (message "Skipping backquote forward over %s" 
(buffer-substring-no-properties phps-mode-lexer--generated-new-tokens-index 
start))
+               (phps-mode-lexer--return-token-with-val
+                'T_ENCAPSED_AND_WHITESPACE
+                phps-mode-lexer--generated-new-tokens-index
+                start))
+           (progn
+             (signal
+              'phps-lexer-error
+              (list
+               (format "Found no ending of back-quoted string starting at %d" 
start)
+               start)))))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_HEREDOC
+     (looking-at phps-mode-lexer--any-char)
+     ;; Check for $, ${ and {$ forward
+     (let ((old-start (car (cdr (car phps-mode-lexer--heredoc-label-stack))))
+           (old-end (point)))
+       (let ((string-start
+              (search-forward-regexp
+               (concat
+                "\\(\n[\t ]*\\("
+                phps-mode-lexer--heredoc-label
+                "\\)\\|\\$"
+                phps-mode-lexer--label
+                "\\|{\\$"
+                phps-mode-lexer--label
+                "\\|\\${"
+                phps-mode-lexer--label
+                "\\)"
+                )
+               nil
+               t)))
+         (if string-start
+             (let* ((start (match-beginning 0))
+                    (end (match-end 0))
+                    (data (match-string 0)))
+
+               (cond
+
+                ((string-match-p
+                  (concat
+                   "\n[\t ]*"
+                   phps-mode-lexer--heredoc-label
+                   )
+                  data)
+                 ;; Skip possible white-spaces before label
+                 (setq start (match-beginning 2))
+                 (setq end (match-beginning 2))
+                 ;; (message "Found heredoc end at %s-%s" start end)
+                 (phps-mode-lexer--return-token-with-val
+                  'T_ENCAPSED_AND_WHITESPACE
+                  old-end
+                  start)
+                 (phps-mode-lexer--begin 'ST_END_HEREDOC))
+
+                (t
+                 ;; (message "Found variable at '%s'.. Skipping forward to %s" 
data start)
+                 (phps-mode-lexer--return-token-with-val
+                  'T_ENCAPSED_AND_WHITESPACE
+                  old-end
+                  start))
+
+                ))
+           (progn
+             (signal
+              'phps-lexer-error
+              (list
+               (format "Found no ending of heredoc starting at %d" old-start)
+               old-start)))))))
+
+    (phps-mode-lexer-generator--match-macro
+     ST_NOWDOC
+     (looking-at phps-mode-lexer--any-char)
+     (let ((start (car (cdr (car phps-mode-lexer--generated-tokens)))))
+       (let ((string-start
+              (search-forward-regexp
+               (concat
+                "\n[\t ]*\\("
+                phps-mode-lexer--heredoc-label
+                "\\)")
+               nil
+               t)))
+         (if string-start
+             (let* ((start (match-beginning 1))
+                    (end (match-end 1))
+                    (_data (buffer-substring-no-properties start end)))
+               ;; (message "Found something ending at %s" _data)
+               ;; (message "Found nowdoc end at %s-%s" start end)
+               (phps-mode-lexer--return-token-with-val
+                'T_ENCAPSED_AND_WHITESPACE
+                phps-mode-lexer--generated-new-tokens-index
+                start)
+               (phps-mode-lexer--begin 'ST_END_HEREDOC))
+           (progn
+             (signal
+              'phps-lexer-error
+              (list
+               (format "Found no ending of nowdoc starting at %d" start)
+               start)))))))
+
+    (phps-mode-lexer-generator--match-macro
+     (ST_IN_SCRIPTING ST_VAR_OFFSET)
+     (looking-at phps-mode-lexer--any-char)
+     (signal
+      'phps-lexer-error
+      (list
+       (format "Unexpected character at %d" (match-beginning 0))
+       (match-beginning 0))))
+
+    phps-mode-lexer-generator--table)
+
+
+(provide 'phps-mode-lexer-generator)
diff --git a/phps-mode-lexer.el b/phps-mode-lexer.el
index a1ff3ce78b..a795087ed4 100644
--- a/phps-mode-lexer.el
+++ b/phps-mode-lexer.el
@@ -17,6 +17,7 @@
 
 
 (require 'phps-mode-macros)
+(require 'phps-mode-lexer-generator)
 
 (require 'subr-x)
 
@@ -116,7 +117,8 @@
 ;; VARIABLES
 
 
-(defvar phps-mode-lexer--lambdas-by-state nil
+(defvar phps-mode-lexer--lambdas-by-state
+  (eval-when-compile (phps-mode-lexer-generator--lambdas))
   "Hash-table of lex-analyzer rules organized by state.")
 
 (defvar-local phps-mode-lexer--generated-tokens nil
@@ -346,26 +348,6 @@
      phps-mode-lex-analyzer--lexer-index
      end)))
 
-(defmacro phps-mode-lexer--match-macro (states conditions &rest body)
-  "Place in STATES a check for CONDITIONS to execute BODY."
-  (unless (listp states)
-    (setq states (list states)))
-  (dolist (state states)
-    (let ((old-lambdas
-           (gethash
-            state
-            phps-mode-lexer--lambdas-by-state)))
-      (when old-lambdas
-        (setq
-         old-lambdas
-         (reverse old-lambdas)))
-      (push `((lambda() ,conditions) (lambda() ,@body)) old-lambdas)
-      (setq old-lambdas (reverse old-lambdas))
-      (puthash
-       state
-       old-lambdas
-       phps-mode-lexer--lambdas-by-state))))
-
 (defun phps-mode-lexer--return-token (&optional token start end)
   "Return TOKEN with START and END."
   (unless start
@@ -465,1506 +447,6 @@
 ;; LEXER FUNCTIONS BELOW
 
 
-;; Setup lexer rules
-
-
-(eval-when-compile
-  (setq phps-mode-lexer--lambdas-by-state (make-hash-table :test 'equal))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "exit")
-   (phps-mode-lexer--return-token-with-indent 'T_EXIT))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "die")
-   (phps-mode-lexer--return-token-with-indent 'T_EXIT))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "fn")
-   (phps-mode-lexer--return-token-with-indent 'T_FN))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "function")
-   (phps-mode-lexer--return-token-with-indent 'T_FUNCTION))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "const")
-   (phps-mode-lexer--return-token-with-indent 'T_CONST))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "return")
-   (phps-mode-lexer--return-token-with-indent 'T_RETURN))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "#\\[")
-   (phps-mode-lexer--enter-nesting "[")
-   (phps-mode-lexer--return-token 'T_ATTRIBUTE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "yield"
-     phps-mode-lexer--whitespace
-     "from"
-     "[^a-zA-Z0-9_\x80-\xff]"))
-   (phps-mode-lexer--return-token-with-indent 'T_YIELD_FROM))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "yield")
-   (phps-mode-lexer--return-token-with-indent 'T_YIELD))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "try")
-   (phps-mode-lexer--return-token-with-indent 'T_TRY))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "catch")
-   (phps-mode-lexer--return-token-with-indent 'T_CATCH))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "finally")
-   (phps-mode-lexer--return-token-with-indent 'T_FINALLY))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "throw")
-   (phps-mode-lexer--return-token-with-indent 'T_THROW))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "if")
-   (phps-mode-lexer--return-token-with-indent 'T_IF))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "elseif")
-   (phps-mode-lexer--return-token-with-indent 'T_ELSEIF))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "endif")
-   (phps-mode-lexer--return-token-with-indent 'T_ENDIF))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "else")
-   (phps-mode-lexer--return-token-with-indent 'T_ELSE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "while")
-   (phps-mode-lexer--return-token-with-indent 'T_WHILE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "endwhile")
-   (phps-mode-lexer--return-token-with-indent 'T_ENDWHILE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "do")
-   (phps-mode-lexer--return-token-with-indent 'T_DO))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "for")
-   (phps-mode-lexer--return-token-with-indent 'T_FOR))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "endfor")
-   (phps-mode-lexer--return-token-with-indent 'T_ENDFOR))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "foreach")
-   (phps-mode-lexer--return-token-with-indent 'T_FOREACH))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "endforeach")
-   (phps-mode-lexer--return-token-with-indent 'T_ENDFOREACH))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "declare")
-   (phps-mode-lexer--return-token-with-indent 'T_DECLARE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "enddeclare")
-   (phps-mode-lexer--return-token-with-indent 'T_ENDDECLARE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "instanceof")
-   (phps-mode-lexer--return-token-with-indent 'T_INSTANCEOF))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "as")
-   (phps-mode-lexer--return-token-with-indent 'T_AS))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "switch")
-   (phps-mode-lexer--return-token-with-indent 'T_SWITCH))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "match")
-   (phps-mode-lexer--return-token-with-indent 'T_MATCH))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "endswitch")
-   (phps-mode-lexer--return-token-with-indent 'T_ENDSWITCH))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "case")
-   (phps-mode-lexer--return-token-with-indent 'T_CASE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "default")
-   (phps-mode-lexer--return-token-with-indent 'T_DEFAULT))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "break")
-   (phps-mode-lexer--return-token-with-indent 'T_BREAK))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "continue")
-   (phps-mode-lexer--return-token-with-indent 'T_CONTINUE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "goto")
-   (phps-mode-lexer--return-token-with-indent 'T_GOTO))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "echo")
-   (phps-mode-lexer--return-token-with-indent 'T_ECHO))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "print")
-   (phps-mode-lexer--return-token-with-indent 'T_PRINT))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "class")
-   (phps-mode-lexer--return-token-with-indent 'T_CLASS))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "interface")
-   (phps-mode-lexer--return-token-with-indent 'T_INTERFACE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "trait")
-   (phps-mode-lexer--return-token-with-indent 'T_TRAIT))
-
-  ;; The enum keyword must be followed by whitespace and another identifier.
-  ;; This avoids the BC break of using enum in classes, namespaces, functions 
and constants.
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at (concat "\\(enum\\)" phps-mode-lexer--whitespace 
"\\(extends\\|implements\\)"))
-   (phps-mode-lexer--yyless 4)
-   (phps-mode-lexer--return-token-with-str 'T_STRING))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at (concat "\\(enum\\)" phps-mode-lexer--whitespace 
"[a-zA-Z_\x80-\xff]"))
-   (phps-mode-lexer--yyless 4)
-   (phps-mode-lexer--return-token-with-indent 'T_ENUM (match-beginning 1) 
(match-end 1)))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "extends")
-   (phps-mode-lexer--return-token-with-indent 'T_EXTENDS))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "implements")
-   (phps-mode-lexer--return-token-with-indent 'T_IMPLEMENTS))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "->")
-   (phps-mode-lexer--yy-push-state 'ST_LOOKING_FOR_PROPERTY)
-   (phps-mode-lexer--return-token-with-indent 'T_OBJECT_OPERATOR))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "?->")
-   (phps-mode-lexer--yy-push-state 'ST_LOOKING_FOR_PROPERTY)
-   (phps-mode-lexer--return-token-with-indent 'T_NULLSAFE_OBJECT_OPERATOR))
-
-  (phps-mode-lexer--match-macro
-   (ST_IN_SCRIPTING ST_LOOKING_FOR_PROPERTY)
-   (looking-at phps-mode-lexer--whitespace)
-   (phps-mode-lexer--return-whitespace))
-
-  (phps-mode-lexer--match-macro
-   ST_LOOKING_FOR_PROPERTY
-   (looking-at "->")
-   (phps-mode-lexer--return-token 'T_OBJECT_OPERATOR))
-
-  (phps-mode-lexer--match-macro
-   ST_LOOKING_FOR_PROPERTY
-   (looking-at "?->")
-   (phps-mode-lexer--return-token 'T_NULLSAFE_OBJECT_OPERATOR))
-
-  (phps-mode-lexer--match-macro
-   ST_LOOKING_FOR_PROPERTY
-   (looking-at phps-mode-lexer--label)
-   (phps-mode-lexer--yy-pop-state)
-   (phps-mode-lexer--return-token-with-str 'T_STRING 0))
-
-  (phps-mode-lexer--match-macro
-   ST_LOOKING_FOR_PROPERTY
-   (looking-at phps-mode-lexer--any-char)
-   (phps-mode-lexer--yyless 0)
-   (phps-mode-lexer--yy-pop-state)
-   (phps-mode-lexer--restart))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "::")
-   (phps-mode-lexer--return-token 'T_PAAMAYIM_NEKUDOTAYIM))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\.\\.\\.")
-   (phps-mode-lexer--return-token 'T_ELLIPSIS))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\?\\?")
-   (phps-mode-lexer--return-token 'T_COALESCE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "new")
-   (phps-mode-lexer--return-token-with-indent 'T_NEW))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "clone")
-   (phps-mode-lexer--return-token-with-indent 'T_CLONE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "var")
-   (phps-mode-lexer--return-token-with-indent 'T_VAR))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "("
-     phps-mode-lexer--tabs-and-spaces
-     "\\(int\\|integer\\)"
-     phps-mode-lexer--tabs-and-spaces
-     ")"))
-   (phps-mode-lexer--return-token 'T_INT_CAST))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "("
-     phps-mode-lexer--tabs-and-spaces
-     "\\(double\\|float\\)"
-     phps-mode-lexer--tabs-and-spaces
-     ")"))
-   (phps-mode-lexer--return-token 'T_DOUBLE_CAST))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "("
-     phps-mode-lexer--tabs-and-spaces
-     "\\(real\\)"
-     phps-mode-lexer--tabs-and-spaces
-     ")"))
-   (when (phps-mode-lexer--parser-mode)
-     (signal
-      'phps-lexer-error
-      (list
-       (format
-        "The (real) cast has been removed, use (float) instead at %d"
-        (match-beginning 0))
-       (match-beginning 0)
-       (match-end 0))))
-   (phps-mode-lexer--return-token 'T_DOUBLE_CAST))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "("
-     phps-mode-lexer--tabs-and-spaces
-     "\\(string\\|binary\\)"
-     phps-mode-lexer--tabs-and-spaces
-     ")"))
-   (phps-mode-lexer--return-token 'T_STRING_CAST))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "("
-     phps-mode-lexer--tabs-and-spaces
-     "array"
-     phps-mode-lexer--tabs-and-spaces
-     ")"))
-   (phps-mode-lexer--return-token 'T_ARRAY_CAST))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "("
-     phps-mode-lexer--tabs-and-spaces
-     "object"
-     phps-mode-lexer--tabs-and-spaces
-     ")"))
-   (phps-mode-lexer--return-token 'T_OBJECT_CAST))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "("
-     phps-mode-lexer--tabs-and-spaces
-     "\\(bool\\|boolean\\)"
-     phps-mode-lexer--tabs-and-spaces
-     ")"))
-   (phps-mode-lexer--return-token 'T_BOOL_CAST))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "("
-     phps-mode-lexer--tabs-and-spaces
-     "unset"
-     phps-mode-lexer--tabs-and-spaces ")"))
-   (phps-mode-lexer--return-token 'T_UNSET_CAST))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "eval")
-   (phps-mode-lexer--return-token-with-indent 'T_EVAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "include")
-   (phps-mode-lexer--return-token-with-indent 'T_INCLUDE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "include_once")
-   (phps-mode-lexer--return-token-with-indent 'T_INCLUDE_ONCE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "require")
-   (phps-mode-lexer--return-token-with-indent 'T_REQUIRE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "require_once")
-   (phps-mode-lexer--return-token-with-indent 'T_REQUIRE_ONCE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "namespace")
-   (phps-mode-lexer--return-token-with-indent 'T_NAMESPACE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "use")
-   (phps-mode-lexer--return-token-with-indent 'T_USE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "insteadof")
-   (phps-mode-lexer--return-token-with-indent 'T_INSTEADOF))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "global")
-   (phps-mode-lexer--return-token-with-indent 'T_GLOBAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "isset")
-   (phps-mode-lexer--return-token-with-indent 'T_ISSET))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "empty")
-   (phps-mode-lexer--return-token-with-indent 'T_EMPTY))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "__halt_compiler")
-   (phps-mode-lexer--return-token-with-indent 'T_HALT_COMPILER))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "static")
-   (phps-mode-lexer--return-token-with-indent 'T_STATIC))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "abstract")
-   (phps-mode-lexer--return-token-with-indent 'T_ABSTRACT))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "final")
-   (phps-mode-lexer--return-token-with-indent 'T_FINAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "private")
-   (phps-mode-lexer--return-token-with-indent 'T_PRIVATE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "protected")
-   (phps-mode-lexer--return-token-with-indent 'T_PROTECTED))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "public")
-   (phps-mode-lexer--return-token-with-indent 'T_PUBLIC))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "readonly")
-   (phps-mode-lexer--return-token-with-indent 'T_READONLY))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "unset")
-   (phps-mode-lexer--return-token-with-indent 'T_UNSET))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "=>")
-   (phps-mode-lexer--return-token 'T_DOUBLE_ARROW))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "list")
-   (phps-mode-lexer--return-token-with-indent 'T_LIST))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "array")
-   (phps-mode-lexer--return-token-with-indent 'T_ARRAY))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "callable")
-   (phps-mode-lexer--return-token-with-indent 'T_CALLABLE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\+\\+")
-   (phps-mode-lexer--return-token 'T_INC))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "--")
-   (phps-mode-lexer--return-token 'T_DEC))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "===")
-   (phps-mode-lexer--return-token 'T_IS_IDENTICAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "!==")
-   (phps-mode-lexer--return-token 'T_IS_NOT_IDENTICAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "==")
-   (phps-mode-lexer--return-token 'T_IS_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\(!=\\|<>\\)")
-   (phps-mode-lexer--return-token 'T_IS_NOT_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "<=>")
-   (phps-mode-lexer--return-token 'T_SPACESHIP))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "<=")
-   (phps-mode-lexer--return-token 'T_IS_SMALLER_OR_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at ">=")
-   (phps-mode-lexer--return-token 'T_IS_GREATER_OR_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\+=")
-   (phps-mode-lexer--return-token 'T_PLUS_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "-=")
-   (phps-mode-lexer--return-token 'T_MINUS_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\*=")
-   (phps-mode-lexer--return-token 'T_MUL_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\*\\\\\\*")
-   (phps-mode-lexer--return-token 'T_POW))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\*\\\\\\*=")
-   (phps-mode-lexer--return-token 'T_POW_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "/=")
-   (phps-mode-lexer--return-token 'T_DIV_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\.=")
-   (phps-mode-lexer--return-token 'T_CONCAT_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "%=")
-   (phps-mode-lexer--return-token 'T_MOD_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "<<=")
-   (phps-mode-lexer--return-token 'T_SL_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at ">>=")
-   (phps-mode-lexer--return-token 'T_SR_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "&=")
-   (phps-mode-lexer--return-token 'T_AND_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "|=")
-   (phps-mode-lexer--return-token 'T_OR_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\^=")
-   (phps-mode-lexer--return-token 'T_XOR_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\?\\?=")
-   (phps-mode-lexer--return-token 'T_COALESCE_EQUAL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "||")
-   (phps-mode-lexer--return-token 'T_BOOLEAN_OR))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "&&")
-   (phps-mode-lexer--return-token 'T_BOOLEAN_AND))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "OR")
-   (phps-mode-lexer--return-token 'T_LOGICAL_OR))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "AND")
-   (phps-mode-lexer--return-token 'T_LOGICAL_AND))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "XOR")
-   (phps-mode-lexer--return-token 'T_LOGICAL_XOR))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "<<")
-   (phps-mode-lexer--return-token 'T_SL))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at ">>")
-   (phps-mode-lexer--return-token 'T_SR))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at (concat "&" "[ \t\r\n]*" "\\(\\$\\|\\.\\.\\.\\)"))
-   (phps-mode-lexer--yyless 1)
-   (phps-mode-lexer--return-token
-    'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
-    (match-beginning 0)
-    (- (match-end 0) 1)))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "&")
-   (phps-mode-lexer--return-token 'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat "\\(" "]" "\\|" ")" "\\)"))
-   (phps-mode-lexer--return-exit-nesting-token))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat "\\(" "\\[" "\\|" "(" "\\)"))
-   (phps-mode-lexer--enter-nesting)
-   (phps-mode-lexer--return-token))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at phps-mode-lexer--tokens)
-   (phps-mode-lexer--return-token))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "{")
-   (phps-mode-lexer--yy-push-state 'ST_IN_SCRIPTING)
-   (phps-mode-lexer--enter-nesting "{")
-   (phps-mode-lexer--return-token))
-
-  (phps-mode-lexer--match-macro
-   (ST_DOUBLE_QUOTES ST_BACKQUOTE ST_HEREDOC)
-   (looking-at "\\${")
-   (phps-mode-lexer--yy-push-state 'ST_LOOKING_FOR_VARNAME)
-   (phps-mode-lexer--enter-nesting "{")
-   (phps-mode-lexer--return-token 'T_DOLLAR_OPEN_CURLY_BRACES))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "}")
-   (phps-mode-lexer--reset-doc-comment)
-   (when phps-mode-lexer--state-stack
-     (phps-mode-lexer--yy-pop-state))
-   (phps-mode-lexer--return-exit-nesting-token))
-
-  (phps-mode-lexer--match-macro
-   ST_LOOKING_FOR_VARNAME
-   (looking-at (concat phps-mode-lexer--label "[\\[}]"))
-   (let* ((start (match-beginning 0))
-          (end (1- (match-end 0)))
-          (_data (buffer-substring-no-properties start end)))
-     (phps-mode-lexer--yyless 1)
-     (phps-mode-lexer--yy-pop-state)
-     (phps-mode-lexer--yy-push-state 'ST_IN_SCRIPTING)
-     (phps-mode-lexer--return-token 'T_STRING_VARNAME start end)))
-
-  (phps-mode-lexer--match-macro
-   ST_LOOKING_FOR_VARNAME
-   (looking-at phps-mode-lexer--any-char)
-   (phps-mode-lexer--yyless 0)
-   (phps-mode-lexer--yy-pop-state)
-   (phps-mode-lexer--yy-push-state 'ST_IN_SCRIPTING)
-   (phps-mode-lexer--restart))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at phps-mode-lexer--bnum)
-   (let* ((start (match-beginning 0))
-          (end (match-end 0))
-          (data
-           (replace-regexp-in-string
-            "_"
-            ""
-            (buffer-substring-no-properties (+ start 2) end)))
-          (long-number (string-to-number data 2)))
-     ;; (message "Binary number %s from %s" long-number data)
-     (if (> long-number phps-mode-lexer--long-limit)
-         (phps-mode-lexer--return-token 'T_DNUMBER)
-       (phps-mode-lexer--return-token 'T_LNUMBER))))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at phps-mode-lexer--onum)
-   (let* ((start (match-beginning 0))
-          (end (match-end 0))
-          (data (string-to-number
-                 (replace-regexp-in-string
-                  "_"
-                  ""
-                  (buffer-substring-no-properties start end))
-                 8)))
-     (if (> data phps-mode-lexer--long-limit)
-         (phps-mode-lexer--return-token 'T_DNUMBER)
-       (phps-mode-lexer--return-token 'T_LNUMBER))))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at phps-mode-lexer--lnum)
-   (let* ((start (match-beginning 0))
-          (end (match-end 0))
-          (data (string-to-number
-                 (replace-regexp-in-string
-                  "_"
-                  ""
-                  (buffer-substring-no-properties start end)))))
-     ;; (message "Long number: %d" data)
-     (if (> data phps-mode-lexer--long-limit)
-         (phps-mode-lexer--return-token 'T_DNUMBER)
-       (phps-mode-lexer--return-token 'T_LNUMBER))))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at phps-mode-lexer--hnum)
-   (let* ((start (match-beginning 0))
-          (end (match-end 0))
-          (data
-           (replace-regexp-in-string
-            "_"
-            ""
-            (buffer-substring-no-properties (+ start 2) end)))
-          (long-number (string-to-number data 16)))
-     ;; (message "Hexadecimal number %s from %s" long-number data)
-     (if (> long-number phps-mode-lexer--long-limit)
-         (phps-mode-lexer--return-token 'T_DNUMBER)
-       (phps-mode-lexer--return-token 'T_LNUMBER))))
-
-  (phps-mode-lexer--match-macro
-   ST_VAR_OFFSET
-   (looking-at "\\([0]\\|[1-9][0-9]*\\)")
-   (phps-mode-lexer--return-token 'T_NUM_STRING))
-
-  (phps-mode-lexer--match-macro
-   ST_VAR_OFFSET
-   (looking-at
-    (concat "\\("
-            phps-mode-lexer--lnum "\\|"
-            phps-mode-lexer--hnum "\\|"
-            phps-mode-lexer--bnum "\\|"
-            phps-mode-lexer--onum "\\)"))
-   (phps-mode-lexer--return-token 'T_NUM_STRING))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (or (looking-at phps-mode-lexer--dnum)
-       (looking-at phps-mode-lexer--exponent-dnum))
-   (phps-mode-lexer--return-token 'T_DNUMBER))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "__CLASS__")
-   (phps-mode-lexer--return-token-with-indent 'T_CLASS_C))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "__TRAIT__")
-   (phps-mode-lexer--return-token-with-indent 'T_TRAIT_C))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "__FUNCTION__")
-   (phps-mode-lexer--return-token-with-indent 'T_FUNC_C))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "__METHOD__")
-   (phps-mode-lexer--return-token-with-indent 'T_METHOD_C))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "__LINE__")
-   (phps-mode-lexer--return-token-with-indent 'T_LINE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "__FILE__")
-   (phps-mode-lexer--return-token-with-indent 'T_FILE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "__DIR__")
-   (phps-mode-lexer--return-token-with-indent 'T_DIR))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "__NAMESPACE__")
-   (phps-mode-lexer--return-token-with-indent 'T_NS_C))
-
-  (phps-mode-lexer--match-macro
-   'SHEBANG
-   (looking-at (concat "#!.*" phps-mode-lexer--newline))
-   (let ((lineno
-          (1+
-           (phps-mode-lexer--CG 'zend_lineno))))
-     (phps-mode-lexer--CG 'zend-lineno lineno))
-   (phps-mode-lexer--begin 'ST_INITIAL)
-   (phps-mode-lexer--restart))
-
-  (phps-mode-lexer--match-macro
-   'SHEBANG
-   (looking-at phps-mode-lexer--any-char)
-   (phps-mode-lexer--yyless 0)
-   (phps-mode-lexer--begin 'ST_INITIAL)
-   (phps-mode-lexer--restart))
-
-  (phps-mode-lexer--match-macro
-   ST_INITIAL
-   (looking-at "<\\?=")
-   (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
-   (when (phps-mode-lexer--parser-mode)
-     (phps-mode-lexer--return-token-with-indent 'T_ECHO))
-   (phps-mode-lexer--return-token 'T_OPEN_TAG_WITH_ECHO))
-
-  (phps-mode-lexer--match-macro
-   ST_INITIAL
-   (looking-at
-    (concat
-     "<\\?php\\([ \t]\\|"
-     phps-mode-lexer--newline
-     "\\)"))
-   (phps-mode-lexer--handle-newline)
-   (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
-   (phps-mode-lexer--return-or-skip-token 'T_OPEN_TAG))
-
-  (phps-mode-lexer--match-macro
-   ST_INITIAL
-   (looking-at "<\\?php")
-   (let ((start (match-beginning 0))
-         (end (match-end 0)))
-
-     (cond
-
-      ;; Allow <?php followed by end of file.
-      ((equal end (point-max))
-       (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
-       (phps-mode-lexer--return-or-skip-token 'T_OPEN_TAG))
-
-      ;; Degenerate case: <?phpX is interpreted as <? phpX with short tags
-      ((phps-mode-lexer--CG 'short-tags)
-       (phps-mode-lexer--yyless 2)
-       (setq end (- end 2))
-       (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
-       (phps-mode-lexer--return-or-skip-token
-        'T_OPEN_TAG
-        start
-        end))
-
-      (t
-       (phps-mode-lexer--inline-char-handler)))))
-
-  (phps-mode-lexer--match-macro
-   ST_INITIAL
-   (looking-at "<\\?")
-   (if (phps-mode-lexer--CG 'short-tags)
-       (progn
-         (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
-         (phps-mode-lexer--return-or-skip-token 'T_OPEN_TAG))
-     (phps-mode-lexer--inline-char-handler)))
-
-  (phps-mode-lexer--match-macro
-   ST_INITIAL
-   (looking-at phps-mode-lexer--any-char)
-   (if (= (point) (point-max))
-       (phps-mode-lexer--return-end-token)
-     (phps-mode-lexer--inline-char-handler)))
-
-  ;; Make sure a label character follows "->" or "?->", otherwise there is no 
property
-  ;; and "->"/"?->" will be taken literally
-  (phps-mode-lexer--match-macro
-   (ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE)
-   (looking-at
-    (concat
-     "\\$"
-     phps-mode-lexer--label
-     "->"
-     "[a-zA-Z_\x80-\xff]"))
-   (phps-mode-lexer--yyless 3)
-   (phps-mode-lexer--yy-push-state 'ST_LOOKING_FOR_PROPERTY)
-   (phps-mode-lexer--return-token-with-str
-    'T_VARIABLE
-    1
-    (match-beginning 0)
-    (- (match-end 0) 3)))
-
-  (phps-mode-lexer--match-macro
-   (ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE)
-   (looking-at
-    (concat
-     "\\$"
-     phps-mode-lexer--label
-     "\\?->"
-     "[a-zA-Z_\x80-\xff]"))
-   (phps-mode-lexer--yyless 4)
-   (phps-mode-lexer--yy-push-state 'ST_LOOKING_FOR_PROPERTY)
-   (phps-mode-lexer--return-token-with-str
-    'T_VARIABLE
-    1
-    (match-beginning 0)
-    (- (match-end 0) 4)))
-
-  ;; A [ always designates a variable offset, regardless of what follows
-  (phps-mode-lexer--match-macro
-   (ST_DOUBLE_QUOTES ST_HEREDOC ST_BACKQUOTE)
-   (looking-at
-    (concat
-     "\\$"
-     phps-mode-lexer--label
-     "\\["))
-   (phps-mode-lexer--yyless 1)
-   (phps-mode-lexer--yy-push-state 'ST_VAR_OFFSET)
-   (phps-mode-lexer--return-token-with-str
-    'T_VARIABLE
-    1
-    (match-beginning 0)
-    (- (match-end 0) 1)))
-
-  (phps-mode-lexer--match-macro
-   (
-    ST_IN_SCRIPTING
-    ST_DOUBLE_QUOTES
-    ST_HEREDOC
-    ST_BACKQUOTE
-    ST_VAR_OFFSET)
-   (looking-at
-    (concat
-     "\\$"
-     phps-mode-lexer--label))
-   (phps-mode-lexer--return-token-with-str 'T_VARIABLE 1))
-
-  (phps-mode-lexer--match-macro
-   ST_VAR_OFFSET
-   (looking-at "\\]")
-   (phps-mode-lexer--yy-pop-state)
-   (phps-mode-lexer--return-token-with-str "]" 1))
-
-  (phps-mode-lexer--match-macro
-   ST_VAR_OFFSET
-   (looking-at
-    (concat "\\(" phps-mode-lexer--tokens
-            "\\|[{}\"`]\\)"))
-   (let* ((start (match-beginning 0))
-          (end (match-end 0))
-          (data (buffer-substring-no-properties start end)))
-     ;; Only '[' or '-' can be valid, but returning other tokens will allow a 
more explicit parse error
-     (phps-mode-lexer--return-token data)))
-
-  (phps-mode-lexer--match-macro
-   ST_VAR_OFFSET
-   (looking-at (concat "[ \n\r\t'#]"))
-   ;; Invalid rule to return a more explicit parse error with proper line 
number
-   (phps-mode-lexer--yyless 0)
-   (phps-mode-lexer--yy-pop-state)
-   (phps-mode-lexer--return-token-with-val 'T_ENCAPSED_AND_WHITESPACE))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "namespace"
-     "\\("
-     "\\\\"
-     phps-mode-lexer--label
-     "\\)+"))
-   (phps-mode-lexer--return-token-with-str
-    'T_NAME_RELATIVE
-    (1- (length "namespace\\"))))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at (concat
-                phps-mode-lexer--label
-                "\\("
-                "\\\\"
-                phps-mode-lexer--label
-                "\\)+"))
-   (phps-mode-lexer--return-token-with-str
-    'T_NAME_QUALIFIED
-    0))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at (concat
-                "\\\\"
-                phps-mode-lexer--label
-                "\\("
-                "\\\\"
-                phps-mode-lexer--label
-                "\\)*"))
-   (phps-mode-lexer--return-token-with-str
-    'T_NAME_FULLY_QUALIFIED
-    1))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\\\")
-   (phps-mode-lexer--return-token 'T_NS_SEPARATOR))
-
-  (phps-mode-lexer--match-macro
-   (ST_IN_SCRIPTING ST_VAR_OFFSET)
-   (looking-at phps-mode-lexer--label)
-   (phps-mode-lexer--return-token-with-str 'T_STRING 0))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\\(#\\|//\\)")
-   (let* ((start (match-beginning 0))
-          (end (match-end 0))
-          (_data (buffer-substring-no-properties start end))
-          (line (buffer-substring-no-properties end (line-end-position))))
-     (if (string-match "\\?>" line)
-         (phps-mode-lexer--return-or-skip-token
-          'T_COMMENT
-          start
-          (+ end (match-beginning 0)))
-       (phps-mode-lexer--return-or-skip-token
-        'T_COMMENT
-        start
-        (line-end-position)))))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "\\(/\\*\\|/\\*\\*"
-     phps-mode-lexer--whitespace
-     "\\)"))
-   (let* ((start (match-beginning 0))
-          (end (match-end 0))
-          (_data (buffer-substring-no-properties start end))
-          (doc-com (looking-at-p (concat "/\\*\\*" 
phps-mode-lexer--whitespace))))
-     (let ((string-start (search-forward "*/" nil t)))
-       (if string-start
-           (if doc-com
-               (progn
-                 (phps-mode-lexer--reset-doc-comment)
-                 (phps-mode-lexer--return-token
-                  'T_DOC_COMMENT
-                  start)
-                 (phps-mode-lexer--CG 'doc_comment t))
-             (phps-mode-lexer--return-token
-              'T_COMMENT start))
-         (progn
-           (signal
-            'phps-lexer-error
-            (list
-             (format
-              "Unterminated comment starting at %d"
-              start)
-             start)))))))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "\\?>"
-     phps-mode-lexer--newline
-     "?"))
-   (let ((start (match-beginning 0))
-         (end (match-end 0)))
-     (when (= (- end start) 3)
-       (setq end (1- end)))
-     (phps-mode-lexer--begin 'ST_INITIAL)
-     (when (phps-mode-lexer--parser-mode)
-       (phps-mode-lexer--return-token
-        ";"
-        start
-        end))
-     (phps-mode-lexer--return-token
-      'T_CLOSE_TAG
-      start
-      end)))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "'")
-   (let* ((start (match-beginning 0))
-          (end (match-end 0))
-          (_data (buffer-substring-no-properties start end))
-          (un-escaped-end (phps-mode-lexer--get-next-unescaped "'")))
-     (if un-escaped-end
-         (phps-mode-lexer--return-token
-          'T_CONSTANT_ENCAPSED_STRING
-          start
-          un-escaped-end)
-       ;; Unclosed single quotes
-       (phps-mode-lexer--return-token-with-val
-        'T_ENCAPSED_AND_WHITESPACE
-        start
-        (point-max))
-       (phps-mode-lexer--move-forward
-        (point-max)))))
-
-  ;; Double quoted string
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "\"")
-   (let* ((start (match-beginning 0))
-          (end (match-end 0))
-          (_data (buffer-substring-no-properties start end))
-          (open-quote t))
-
-     ;; Move forward from the double-quote one character
-     (forward-char)
-
-     (while open-quote
-       (let ((string-start
-              (search-forward-regexp
-               (concat
-                "\\(\""
-                "\\|\\$" phps-mode-lexer--label
-                "\\|\\${" phps-mode-lexer--label
-                "\\|{\\$" phps-mode-lexer--label "\\)")
-               nil t)))
-
-         ;; Do we find a ending double quote or starting variable?
-         (if string-start
-             (let ((string-start (match-beginning 0))
-                   (last-character-is-escape-character t)
-                   (is-escaped nil))
-
-               ;; Do we find variable inside quote?
-               (goto-char string-start)
-
-               ;; Backtrack until we find a character that is not a escape 
character
-               (while last-character-is-escape-character
-                 (forward-char -1)
-                 (if (looking-at-p "\\\\")
-                     (setq is-escaped (not is-escaped))
-                   (setq last-character-is-escape-character nil)))
-
-               ;; Do we find variable inside quote?
-               (goto-char string-start)
-
-               ;; Process character but only if it's not escaped
-               (if is-escaped
-                   (forward-char 1)
-                 (setq open-quote nil)
-                 (if (looking-at-p "\"")
-                     (let ((_double-quoted-string
-                            (buffer-substring-no-properties start (+ 
string-start 1))))
-                       ;; (message "Double quoted string: %s" 
_double-quoted-string)
-                       (phps-mode-lexer--return-token-with-val
-                        'T_CONSTANT_ENCAPSED_STRING
-                        start
-                        (+ string-start 1)))
-                   ;; (message "Found variable after '%s' at %s-%s" 
(buffer-substring-no-properties start string-start) start string-start)
-                   (phps-mode-lexer--begin 'ST_DOUBLE_QUOTES)
-                   (phps-mode-lexer--return-token "\"" start (1+ start)))))
-           (progn
-             (setq open-quote nil)
-             (signal
-              'phps-lexer-error
-              (list
-               (format "Found no ending of quote at %s" start)
-               start))))))))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at
-    (concat
-     "<<<"
-     phps-mode-lexer--tabs-and-spaces
-     "\\("
-     phps-mode-lexer--label
-     "\\|'"
-     phps-mode-lexer--label
-     "'\\|\""
-     phps-mode-lexer--label
-     "\"\\)"
-     phps-mode-lexer--newline))
-   (let* ((start (match-beginning 0))
-          (end (match-end 0))
-          (data
-           (buffer-substring-no-properties
-            (match-beginning 1)
-            (match-end 1))))
-
-     ;; Determine if it's HEREDOC or NOWDOC and extract label here
-     (if (string= (substring data 0 1) "'")
-         (progn
-           (setq
-            phps-mode-lexer--heredoc-label
-            (substring data 1 (- (length data) 1)))
-           (phps-mode-lexer--begin 'ST_NOWDOC))
-       (progn
-         (if (string= (substring data 0 1) "\"")
-             (setq
-              phps-mode-lexer--heredoc-label
-              (substring data 1 (- (length data) 1)))
-           (setq
-            phps-mode-lexer--heredoc-label
-            data))
-         (phps-mode-lexer--begin 'ST_HEREDOC)))
-
-     ;; Check for ending label on the next line
-     (when (string=
-            (buffer-substring-no-properties
-             end
-             (+ end
-                (length
-                 phps-mode-lexer--heredoc-label)))
-            phps-mode-lexer--heredoc-label)
-       (phps-mode-lexer--begin 'ST_END_HEREDOC))
-
-     (push
-      `(,phps-mode-lexer--heredoc-label ,start ,end)
-      phps-mode-lexer--heredoc-label-stack)
-     ;; (message "Found heredoc or nowdoc at %s with label %s" data 
phps-mode-lexer--heredoc-label)
-
-     (phps-mode-lexer--CG
-      'doc_comment
-      t)
-     (phps-mode-lexer--return-token
-      'T_START_HEREDOC
-      start
-      end)))
-
-  (phps-mode-lexer--match-macro
-   ST_IN_SCRIPTING
-   (looking-at "[`]")
-   ;; (message "Begun backquote at %s-%s" (match-beginning 0) (match-end 0))
-   (phps-mode-lexer--begin 'ST_BACKQUOTE)
-   (phps-mode-lexer--return-token "`"))
-
-  (phps-mode-lexer--match-macro
-   ST_END_HEREDOC
-   (looking-at
-    (concat phps-mode-lexer--any-char))
-   (let* ((start (match-beginning 0))
-          (end (+ start
-                  (length
-                   phps-mode-lexer--heredoc-label)))
-          (_data (buffer-substring-no-properties start end)))
-     ;; (message "Found ending heredoc at %s, %s of %s" _data (thing-at-point 
'line) phps-mode-lexer--heredoc-label)
-     (pop phps-mode-lexer--heredoc-label-stack)
-     (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
-     (phps-mode-lexer--return-token 'T_END_HEREDOC start end)))
-
-  (phps-mode-lexer--match-macro
-   (ST_DOUBLE_QUOTES ST_BACKQUOTE ST_HEREDOC)
-   (looking-at "{\\$")
-   (phps-mode-lexer--yy-push-state 'ST_IN_SCRIPTING)
-   (phps-mode-lexer--yyless 1)
-   (phps-mode-lexer--enter-nesting "{")
-   (phps-mode-lexer--return-token
-    'T_CURLY_OPEN
-    (match-beginning 0)
-    (- (match-end 0) 1)))
-
-  (phps-mode-lexer--match-macro
-   ST_DOUBLE_QUOTES
-   (looking-at "[\"]")
-   (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
-   (phps-mode-lexer--return-token "\""))
-
-  (phps-mode-lexer--match-macro
-   ST_BACKQUOTE
-   (looking-at "[`]")
-   (phps-mode-lexer--begin 'ST_IN_SCRIPTING)
-   (phps-mode-lexer--return-token "`"))
-
-  (phps-mode-lexer--match-macro
-   ST_DOUBLE_QUOTES
-   (looking-at phps-mode-lexer--any-char)
-   (let ((start (point))
-         (start-error (car (cdr (nth 2 phps-mode-lexer--generated-tokens)))))
-     (let ((string-start (search-forward-regexp "[^\\\\]\"" nil t)))
-       (if string-start
-           (let* ((end (- (match-end 0) 1))
-                  (double-quoted-string (buffer-substring-no-properties start 
end)))
-             ;; Do we find variable inside quote?
-             (if (or (string-match (concat "\\${" phps-mode-lexer--label) 
double-quoted-string)
-                     (string-match (concat "{\\$" phps-mode-lexer--label) 
double-quoted-string)
-                     (string-match (concat "\\$" phps-mode-lexer--label) 
double-quoted-string))
-                 (progn
-                   (let ((variable-start (+ start (match-beginning 0))))
-
-                     ;; (message "Found starting expression inside 
double-quoted string at: %s %s" start variable-start)
-                     (phps-mode-lexer--return-token-with-val
-                      'T_ENCAPSED_AND_WHITESPACE
-                      start
-                      variable-start)))
-               (progn
-                 (phps-mode-lexer--return-token-with-val
-                  'T_ENCAPSED_AND_WHITESPACE
-                  start
-                  end)
-                 ;; (message "Found end of quote at %s-%s, moving ahead after 
'%s'" start end (buffer-substring-no-properties start end))
-                 )))
-         (progn
-           (signal
-            'phps-lexer-error
-            (list
-             (format "Found no ending of double quoted region starting at %d" 
start-error)
-             start-error)))))))
-
-  (phps-mode-lexer--match-macro
-   ST_BACKQUOTE
-   (looking-at phps-mode-lexer--any-char)
-   (let ((start (car (cdr (car phps-mode-lexer--generated-tokens)))))
-     (let ((string-start (search-forward-regexp "\\([^\\\\]`\\|\\$\\|{\\)" nil 
t)))
-       (if string-start
-           (let ((start (- (match-end 0) 1)))
-             ;; (message "Skipping backquote forward over %s" 
(buffer-substring-no-properties phps-mode-lexer--generated-new-tokens-index 
start))
-             (phps-mode-lexer--return-token-with-val
-              'T_ENCAPSED_AND_WHITESPACE
-              phps-mode-lexer--generated-new-tokens-index
-              start))
-         (progn
-           (signal
-            'phps-lexer-error
-            (list
-             (format "Found no ending of back-quoted string starting at %d" 
start)
-             start)))))))
-
-  (phps-mode-lexer--match-macro
-   ST_HEREDOC
-   (looking-at phps-mode-lexer--any-char)
-   ;; Check for $, ${ and {$ forward
-   (let ((old-start (car (cdr (car phps-mode-lexer--heredoc-label-stack))))
-         (old-end (point)))
-     (let ((string-start
-            (search-forward-regexp
-             (concat
-              "\\(\n[\t ]*\\("
-              phps-mode-lexer--heredoc-label
-              "\\)\\|\\$"
-              phps-mode-lexer--label
-              "\\|{\\$"
-              phps-mode-lexer--label
-              "\\|\\${"
-              phps-mode-lexer--label
-              "\\)"
-              )
-             nil
-             t)))
-       (if string-start
-           (let* ((start (match-beginning 0))
-                  (end (match-end 0))
-                  (data (match-string 0)))
-
-             (cond
-
-              ((string-match-p
-                (concat
-                 "\n[\t ]*"
-                 phps-mode-lexer--heredoc-label
-                 )
-                data)
-               ;; Skip possible white-spaces before label
-               (setq start (match-beginning 2))
-               (setq end (match-beginning 2))
-               ;; (message "Found heredoc end at %s-%s" start end)
-               (phps-mode-lexer--return-token-with-val
-                'T_ENCAPSED_AND_WHITESPACE
-                old-end
-                start)
-               (phps-mode-lexer--begin 'ST_END_HEREDOC))
-
-              (t
-               ;; (message "Found variable at '%s'.. Skipping forward to %s" 
data start)
-               (phps-mode-lexer--return-token-with-val
-                'T_ENCAPSED_AND_WHITESPACE
-                old-end
-                start))
-
-              ))
-         (progn
-           (signal
-            'phps-lexer-error
-            (list
-             (format "Found no ending of heredoc starting at %d" old-start)
-             old-start)))))))
-
-  (phps-mode-lexer--match-macro
-   ST_NOWDOC
-   (looking-at phps-mode-lexer--any-char)
-   (let ((start (car (cdr (car phps-mode-lexer--generated-tokens)))))
-     (let ((string-start
-            (search-forward-regexp
-             (concat
-              "\n[\t ]*\\("
-              phps-mode-lexer--heredoc-label
-              "\\)")
-             nil
-             t)))
-       (if string-start
-           (let* ((start (match-beginning 1))
-                  (end (match-end 1))
-                  (_data (buffer-substring-no-properties start end)))
-             ;; (message "Found something ending at %s" _data)
-             ;; (message "Found nowdoc end at %s-%s" start end)
-             (phps-mode-lexer--return-token-with-val
-              'T_ENCAPSED_AND_WHITESPACE
-              phps-mode-lexer--generated-new-tokens-index
-              start)
-             (phps-mode-lexer--begin 'ST_END_HEREDOC))
-         (progn
-           (signal
-            'phps-lexer-error
-            (list
-             (format "Found no ending of nowdoc starting at %d" start)
-             start)))))))
-
-  (phps-mode-lexer--match-macro
-   (ST_IN_SCRIPTING ST_VAR_OFFSET)
-   (looking-at phps-mode-lexer--any-char)
-   (signal
-    'phps-lexer-error
-    (list
-     (format "Unexpected character at %d" (match-beginning 0))
-     (match-beginning 0))))
-
-  )
-
 (defun phps-mode-lexer--re2c-execute ()
   "Execute matching body (if any)."
   (if phps-mode-lexer--match-body

Reply via email to